Search code examples
authenticationoauth-2.0jwtkeycloakopenid-connect

Is it safe to use "sub" claim in keycloak token for user id in internal DB


I'm working on an application that may support social logins in future (in addition to our own keycloak username/email signup).

I'm trying to determine if it's safe to use the "sub" claim that comes in keycloak ID token, as a primary key (the "_id" field) for users in our internal mongo db. I'd ideally like to use an id from the token, as it may save me needing to make an extra User lookup in some cases in our api.

I see Microsoft azure docs show their auth token has both "sub" and "oid", where the "oid" is recommended to be used for user lookup internally as it's globally unique. See this section.

This ID uniquely identifies the user across applications - two different applications signing in the same user will receive the same value in the oid claim. The Microsoft Graph will return this ID as the id property for a given user account.

So is there an equivalent of the "oid" claim in keycloak, do I need to add a custom claim to achieve the equivalent, or am I ok just to use the "sub" claim instead?


Solution

  • Looking JSON Web Token (JWT) documentation, namely at "sub" (Subject) Claim section:

    4.1.2. "sub" (Subject) Claim

    The "sub" (subject) claim identifies the principal that is the subject of the JWT. (...). The subject value MUST either be scoped to be locally unique in the context of the issuer or be globally unique. The processing of this claim is generally application specific. (...). Use of this claim is OPTIONAL.

    From my interpretation of this text alone, it is not guaranteed that the sub claim for a given user will be the same among different applications (i.e., clients). Moreover, that claim is optional.

    So to answer your question precisely we need to look at the context of OpenID connect:

    The primary extension that OpenID Connect makes to OAuth 2.0 to enable End-Users to be Authenticated is the ID Token data structure.

    sub : REQUIRED. Subject Identifier. A locally unique and never reassigned identifier within the Issuer for the End-User, which is intended to be consumed by the Client (...).

    Okey, from this text and the fact that to get the ID Token you must pass to the request the openid scope, you can be sure that the sub claim will be presented in the ID Token.

    Regarding the question whether the sub will be the same for all Clients, this is also address in the same document under the Subject Identifier Types section:

    Subject Identifier Types

    A Subject Identifier is a locally unique and never reassigned identifier within the Issuer for the End-User, which is intended to be consumed by the Client.

    Two Subject Identifier types are defined by this specification:

    public - This provides the same sub (subject) value to all Clients. It is the default if the provider has no subject_types_supported element in its discovery document.

    pairwise - This provides a different sub value to each Client, so as not to enable Clients to correlate the End-User's activities without permission.

    The OpenID Provider's Discovery document SHOULD list its supported Subject Identifier types in the subject_types_supported element. If there is more than one type listed in the array, the Client MAY elect to provide its preferred identifier type using the subject_type parameter during Registration.

    Since a while now, keycloak support both public and pairwise subject identifier types. If not explicitly specified the public one is used by default.

    So to conclude:

    or am I ok just to use the "sub" claim instead?

    Yes, as long as you take into account the subject identifier type being used.