Search by

kopexa / mautic-oauth-bundle

kopexa

OAuth 2.1 authorization server for Mautic (authorization code + PKCE S256, refresh tokens, dynamic client registration, RFC 8414 metadata, JWKS). Used by MCP clients such as Claude and ChatGPT.

Package info

github.com/kopexa-grc/mautic-oauth-bundle

Type:mautic-plugin

pkg:composer/kopexa/mautic-oauth-bundle

Statistics

Installs: 163

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

v0.4.1 2026-11-03 19:10 UTC

This package is auto-updated.

Last update: 2026-11-03 19:10:57 UTC


README

Packagist ci

OAuth 2.1 authorization server for Mautic 7, so MCP clients (Claude, ChatGPT, …) can connect with the standard MCP authorization flow.

Installation

Requires Mautic 7.2+ (Composer-based installation) and PHP 8.4+:

composer require kopexa/mautic-oauth-bundle
php bin/console mautic:plugins:reload

Configure the signing and encryption keys (kopexa_oauth_private_key, kopexa_oauth_encryption_key) in Mautic's config/local.php or, in the kopexa image, via environment variables.

Already included in the hardened Mautic image ghcr.io/kopexa-grc/mautic.

It provides:

  • authorization code grant with PKCE (S256 only) and rotating refresh tokens
  • dynamic client registration (RFC 7591)
  • authorization server metadata (RFC 8414)
  • JWKS
  • RFC 9068 JWT access tokens with an RFC 8707 audience
  • revocation (RFC 7009)

Consent is shown under /s/, so Mautic's own login (password or SAML) authenticates the user.

Built on league/oauth2-server.

Configuration, security model and endpoints: docs/oauth.md.

Parameter Env (kopexa image)
kopexa_oauth_private_key MAUTIC_OAUTH_PRIVATE_KEY RSA private key (PEM)
kopexa_oauth_encryption_key MAUTIC_OAUTH_ENCRYPTION_KEY secret for codes / refresh tokens
kopexa_oauth_redirect_hosts MAUTIC_OAUTH_REDIRECT_HOSTS allowed redirect hosts
kopexa_oauth_resource MAUTIC_OAUTH_RESOURCE token audience (default <site_url>/mcp)
kopexa_oauth_access_ttl / kopexa_oauth_refresh_ttl via MAUTIC_CONFIG_PARAMETERS seconds (3600 / 2592000)
kopexa_oauth_scopes, kopexa_oauth_default_scopes, kopexa_oauth_optin_scopes via MAUTIC_CONFIG_PARAMETERS operator overrides for scopes, see below (default: none)

Scopes

The server has no scopes of its own: the bundles that enforce scopes declare them. Implement ScopeProviderInterface in an autoconfigured service; the server collects all providers:

use MauticPlugin\KopexaOAuthBundle\Scope\ScopeDefinition;
use MauticPlugin\KopexaOAuthBundle\Scope\ScopeProviderInterface;

final class MyScopes implements ScopeProviderInterface
{
    public function scopes(): iterable
    {
        yield new ScopeDefinition('reports:read', 'Read reports', default: true);
        yield new ScopeDefinition('reports:delete', 'Delete reports', optIn: true);
    }
}
Flag Effect
default granted when a client requests no scope; always kept on the consent page (cannot be unticked)
optIn shown highlighted and unticked on the consent page: the user has to tick it, even if the client requests it

The scopes appear in the metadata (scopes_supported), the client registration response and on the consent page. A scope declared by two providers is an error. Operators can add scopes or replace descriptions (kopexa_oauth_scopes: scope => description) and make further scopes default or opt-in (kopexa_oauth_default_scopes, kopexa_oauth_optin_scopes). kopexa/mautic-mcp-bundle declares the mcp:* scopes this way.

Development

  • bin/check.sh checks the package (PHP lint, composer validate, version consistency). CI runs it on every push and pull request.
  • tests/functional/run.sh installs the plugin into a real Mautic 7 and tests it over HTTP; CI runs it on PHP 8.4 and 8.5.
  • End-to-end tests also run in kopexa-grc/mautic-stack: its smoke test installs this package into the Mautic image and exercises it end to end.
  • Commits follow Conventional Commits (feat:, fix:, docs:, chore: …); they drive versions and the changelog.
  • Releases are automated with release-please: it keeps a release PR open that bumps VERSION, the plugin version and CHANGELOG.md. Merging it tags v<version> and creates the GitHub release. Packagist and mautic-stack's Renovate pick the tag up.
  • Dependencies are kept current by Renovate, once a month (security fixes immediately). Composer constraint updates are committed as fix(deps): and so lead to a patch release; CI-only updates (ci:) do not.

Apache-2.0 · Kopexa