Skip to content

Support Custom Subject Mapping via Webhook for OAuth2 Flows #4553

@tongium

Description

@tongium

Preflight checklist

Ory Network Project

No response

Describe your problem

While Ory Kratos provides excellent support for identity migration via external_id and standard pairwise subject identifiers, some complex migration scenarios require dynamic logic.

Specifically, when a legacy system uses a custom pairwise algorithm that varies per OAuth2 client, a static mapping is insufficient. Currently, Kratos is limited to using the Internal Identity ID or a pre-defined External ID, which makes it difficult to maintain backward compatibility for specialized subject (sub) requirements.

Describe your ideal solution

Add a subject_hook to the oauth2_provider configuration. This hook would trigger during the login acceptance flow, sending the identity context and the login challenge to an external service. The external service would then return the desired subject identifier.

Example Configuration:

oauth2_provider:
  url: http://hydra-admin.internal
  subject_hook:
    enabled: true
    config:
      url: http://hook-sever.internal
      body: "file:///etc/config/subject-hook.jsonet"

Expected Webhook Response:

The hook should return the mapping between the Kratos Identity and the custom identifier:

{
  "identity_id": "abc",
  "obfuscated_id": "xyz"
}

Implementation Logic

When the hook is enabled and returns a successful response, Kratos would use the obfuscated_id to set the ForceSubjectIdentifier when communicating with Hydra:

alr := hydraclientgo.NewAcceptOAuth2LoginRequest(params.IdentityID)
if params.ObfuscatedID != "" {
    alr.ForceSubjectIdentifier = &params.ObfuscatedID
}

Workarounds or alternatives

Add server between Kratos and Hydra to modify AcceptOAuth2LoginRequest body

oauth2_provider:
  url: http://custom-server.internal

Version

v25.4.0

Additional Context

No response

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