Skip to content

Optional Access Token Strategy for Dynamic Client Registration #4060

@vichanse

Description

@vichanse

Preflight checklist

Ory Network Project

No response

Describe your problem

When using OpenID Connect Dynamic Client Registration (RFC 7591), there is no way to enforce a specific access token strategy (jwt or opaque) for dynamically registered clients. Unlike the Admin API, DCR does not allow clients to specify or modify their access_token_strategy after registration.

Currently, all DCR-created clients inherit the global strategies.access_token setting. Administrators who want DCR clients to use a different strategy than admin-created clients have no configuration option to achieve this.

Describe your ideal solution

Add an optional configuration path under oidc.dynamic_client_registration to specify the access token strategy for DCR clients:

oidc:
  dynamic_client_registration:
    enabled: true
    strategies:
      access_token: jwt  # Optional: "jwt" or "opaque"
    default_scope:
      - openid
      - offline

### Workarounds or alternatives

**Behavior:**
- When `strategies.access_token` is set, all DCR-created clients use that strategy
- When not set, existing behavior is preserved (uses global `strategies.access_token`)
- DCR registration payload cannot override this value
- Admin API remains unaffected

### Behavior Matrix

| DCR `strategies.access_token` | Global `strategies.access_token` | DCR Client Token Strategy |
|-------------------------------|----------------------------------|---------------------------|
| Not set                       | `opaque`                         | `opaque` (global default) |
| Not set                       | `jwt`                            | `jwt` (global default)    |
| `opaque`                      | `jwt`                            | `opaque` (DCR override)   |
| `jwt`                         | `opaque`                         | `jwt` (DCR override)      |

### Implementation Notes

**Files likely requiring changes:**

| File | Change |
|------|--------|
| `spec/config.json` | Add schema for `oidc.dynamic_client_registration.strategies.access_token` |
| `driver/config/provider.go` | Add getter `OIDCDynamicClientRegistrationAccessTokenStrategy` |
| `client/handler.go` | Apply DCR strategy in registration endpoint |

**Example configuration getter:**

```go
func (p *DefaultProvider) OIDCDynamicClientRegistrationAccessTokenStrategy(ctx context.Context) string {
    key := "oidc.dynamic_client_registration.strategies.access_token"
    if !p.getProvider(ctx).Exists(key) {
        return "" // Not configured, use global default
    }
    return p.getProvider(ctx).String(key)
}

Example handler logic:

if dcrStrategy := h.r.Config().OIDCDynamicClientRegistrationAccessTokenStrategy(ctx); dcrStrategy != "" {
    c.AccessTokenStrategy = dcrStrategy
}

Backward Compatibility

  • Existing configurations without the new field continue to work unchanged
  • No database migrations required
  • No breaking changes to existing DCR behavior

Version

Hydra version: latest Environment: all

Additional Context

  • RFC 7591: OAuth 2.0 Dynamic Client Registration Protocol

  • This enables use cases where DCR clients should use a different token format than admin-managed clients (e.g., JWT for external integrations, opaque for internal services)

Metadata

Metadata

Assignees

No one assigned

    Labels

    featNew feature or request.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions