feat: allow using identity external_id as oauth2 subject#4529
feat: allow using identity external_id as oauth2 subject#4529Micaso wants to merge 2 commits intoory:masterfrom
Conversation
This change adds a configuration option `oauth2_provider.use_external_id`. When enabled, Kratos will pass the identity's `external_id` as the subject (`sub`) to Ory Hydra during the OAuth2 login flow. If the toggle is enabled but no `external_id` is present on the identity, it falls back to the internal Identity ID (UUID) to ensure continuity. Part of the effort to better integrate external identity mappings. Closes ory#4528
|
if I run Also I am quite unsure if I could resolve the issues from the Docker Image Scanners |
jonas-jonas
left a comment
There was a problem hiding this comment.
Awesome, thanks for your work here! I have a few notes.
| headers: | ||
| Authorization: Basic | ||
| override_return_to: true | ||
| use_external_id: true |
There was a problem hiding this comment.
We have the same pattern for the tokenizer, but there the setting is
subject_source: external_id # or id (default)Could you adjust the code here?
There was a problem hiding this comment.
Hi there! Thx for your review and apologies for the delay in getting back to this—I’ve been a bit tied up lately. I changed it like you requested
hydra/hydra.go
Outdated
| if h.d.Config().OAuth2ProviderUseExternalID(ctx) && params.ExternalID != "" { | ||
| subject = params.ExternalID | ||
| } |
There was a problem hiding this comment.
In the tokenizer we return an error if the identity's external_id is unset, and the subject_source is set to external_id.
I think that would be appropriate here, too, as it's otherwise difficult to figure out which ID was used.
Alternatively, we could probably add another claim, that describes the subject_source to the token, WDYT?
There was a problem hiding this comment.
That makes total sense. I agree that consistency with the tokenizer is the best path forward here to avoid confusion over which ID is being used.
I’ve updated the code to return an error if external_id is unset while subject_source is set to external_id. This keeps the behavior predictable across the codebase. Thanks for pointing that out
Replace `use_external_id` boolean config with `subject_source` enum to match the existing tokenizer pattern. The new config accepts: - "id" (default): Use identity ID as OAuth2 subject - "external_id": Use identity's external_id as OAuth2 subject Returns an error when `subject_source` is set to "external_id" but the identity's external_id is unset, ensuring predictable behavior and making it easier to identify which ID was used. This aligns the OAuth2 provider configuration with the session tokenizer implementation for consistency across the codebase. Closes ory#4528
Description
This PR introduces the ability to use an identity's
external_idas the OpenID Connectsubject(subclaim) when Ory Kratos acts as the identity provider for Ory Hydra.Previously, Kratos always passed the internal UUID as the subject. For users migrating from legacy systems or integrating with third-party services that rely on specific string identifiers, this new configuration option allows for seamless identity mapping without requiring a custom consent provider middleware.
The logic implements a safe fallback: if the configuration is enabled but an identity does not have an
external_idset, it will continue to use the Kratos Identity UUID to prevent flow breakage.Related issue(s)
Fixes #4528
Checklist
Further Comments
Solution Choice
I implemented this via a new configuration toggle
oauth2_provider.use_external_id. This maintains backward compatibility by defaulting tofalse.The subject selection logic in
hydra/hydra.gofollows this priority:oauth2_provider.use_external_idisfalse: UseIdentity.ID.oauth2_provider.use_external_idistrueANDIdentity.ExternalIDis present: UseIdentity.ExternalID.oauth2_provider.use_external_idistrueANDIdentity.ExternalIDis empty: Fallback toIdentity.ID.Alternatives Considered
Custom Integration Layer: One could bypass the native Kratos-Hydra integration and handle the
acceptLoginRequestmanually in a custom UI/backend. However, this requires users to write and maintain "glue code" for a very common architectural need. Providing this natively simplifies the Ory stack for enterprise migrations.Testing
driver/config/config_test.goto verify schema parsing.hydra/fake.goto capture and verify parameters.PostLoginHookcorrectly extracts theexternal_idfrom the identity.