oauth-2.0oauthopenid-connect

OAuth2/OIDC : how to identify client application


TL/DR: my questions are at the end of this message but basically I'm asking what are the standards to identify a client application from a web-service perspective?

More context: we are working at my company on re-building our authentication and authorization mechanisms for a year now. As many companies we have multiple web-services, talking between them (M2M), that can be called from our internal organization or from outside (by external companies). For increasing security level and inter-operability we have moved to OAuth2/OIDC protocols (based on Keycloak as Authorization Server), and it's working well.

The problem we are facing now is, in order to notify our customers of breaking changes, depreciations, warnings, etc (and for increasing audit capability), we need to identify the customer application, not the user, calling each of our web-services (then attach an email - or whatever - to this identity, but this is out of my question's scope). We can't rely on the user account since the user account can legitimately be used from another customer application. We can't rely on low-level protocols (e.g using the source IP to identify them is impossible because of NAT and many reasons). We assume that we can't neither rely on the Access Token or ID Token (e.g the azp claim) since these tokens could legitimately be used downstream by other processes (who are not the parties who have requested a token) (and since the specification of the azp claim is ambiguous and depends on implementation - e.g Google does not respect the standard if I'm correct).

So my questions are:

  1. Could you confirm the OAuth2 and OIDC protocols are not designed to handle this use-case (or am I missing something?)?
  2. Therefore should we implement some custom logic (e.g an additional information, owned by the caller, signed by some authority, to pass in some HTTP header for each request to our web-services, something like that) or is there some well-known standards for that?
  3. Another option could be to rely on API Keys but it makes us uncomfortable because we would lose OAuth2/OIDC and their inter-operability benefits, standards, etc?

Thanks a lot for your expertise!

What we tried: as described above, we have evaluated multiple approaches and identify pros/cons of some of them, but we haven't been able to identify a standard and universal way to perform what we want (identifying a client application, not a user, without losing standards benefits).


Solution

  • IDENTIFYING CLIENTS

    In an M2M setup you use the client credentials grant and the authorization server will issue a claim like client_id in the access token. The exact identifier may depend on the authorization server.

    This allows you to distinguish callers and then look up their particular permissions as part of your API logic. This is common in B2B deployments where multiple business partners are each registered as a distinct client and the access token enables you to tell them apart.

    Your token issuance logic could also potentially issue custom claims to the access token, eg a department_id or partner_id.

    ACCESS TOKEN SCOPE

    Your concerns about where an access token can be used should be managed by issuing scopes and an audience claim. Each API should validate that an access token meets its own expected values for these fields.

    Scopes are often areas of the business. Eg an access token with a scope of retail/sales would not be usable against an API that requires a scope of commercial/sales. The audience can represent a single API or a logical set of APIs.

    This mechanism allows access tokens to safely flow between APIs when you want them to, or prevent that when you do not.

    USER BASED FLOWS

    In some cases (eg microservice setups) an app gets a user level access token and calls your API 1, which then calls your API 2, which also needs to work with the user identity.

    In such cases the token received by API 2 should maintain the user identity in the access token and you should avoid getting a new access token for API 2 using the client credentials grant.

    If API 1 trusts API 2 it might simply forward the original access token. Or API 1 could use the token exchange standard from RFC 8693 to get a new access token with updated (eg reduced) scopes and audience.

    SUMMARY