Skip to content

Episode 005: 04‐11‐2024 Best Practices for Client Authn

Michael Schwartz edited this page Apr 12, 2024 · 31 revisions

Linkedin Event

Short Title < 50 Char

Best Practices for Client Authn

Long Title

Identerati Office Hours Livestream - Episode 5 - Best Practices for Client Authn

Description

API developers are familiar with using "client credentials"--normally a client_id and client_secret--to authenticate to an API Server (i.e. "Resource Server" or "RS"). In OAuth, client credentials are presented while obtaining an access_token at the token endpoint. The client then sends the access_token to the API in the Authorization header, for example:

Authorization: Bearer mF_9.B5f-4.1JqM).

OpenID Connect Core defines five possible mechanisms for client authentication at the token endpoint:

  • client_secret_basic
  • client_secret_post
  • client_secret_jwt
  • private_key_jwt
  • none

NOTE: In Mike's opinion, PKCE is not a client authn method. It's a correlation identifier, similar in purpose to a state parameter (for the Authorization Server)--it shows that the same client that requested the code is showing up to collect the token.

Nat Sakimura presented a nice security summary of these different mechanisms in 2017:

image

So in the past seven years, you'd expect developers to be moving toward private_key_jwt client authentication, right?

Except they really aren't.

In this episode, we'll dive into best practices for client authentication. Is private_key_jwt really so hard? And if we're moving in this direction, how can we achieve more efficiency, especially with regard to managing trust with clients?

Homework

  • RFC 7523 JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants

  • Software Statement docs in the UK Open Banking DCR Spec

  • Linkedin Post which provides a perspective on how API developers think about this topic. WARNING: we are not advocating this content... it's just for context.

image

Client Authn Process

Current
  • Find developer portal
  • Create client and download client_id / client_secret
  • Enter client_id / client_secret into app, probably in the clear
  • Call token API with BASIC / POST

Future

One time:

  1. Generate a keypair and store it in something like a p12 keystore file
  2. Output keys as jwks
  3. Perform DCR: set jwks param (or point to hosted jwks via jwks_url)

For each token request:

  1. Generate JSON payload and RS256 sign JWT with JWK from JWKS
  2. send request to Token Endpoint with params
    • client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
    • client_assertion=JWT HERE

Sample JWT:

Header:

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "<kid here>"
}

Payload:

{
  "iss": "28d0-4522-b10c-a4902c71c2f8",
  "sub": "28d0-4522-b10c-a4902c71c2f8",
  "aud": "<token endpoint here>",
   "jti": "864f-49c4-aae6-7bfa7af73457",
  "iat": 1516239022,
  "exp": 1516759000 
}

Takeaways

  • Dick disagreed that PKCE is not client authentication. Maybe it is a kind of ephemeral authentication for that session: I'm this client with this redirect_uri and when I come back to get a token, I can prove I'm the one who is associated with this code flow.

  • Ralph asserts that although there are barriers to moving to private_key_jwt authentication, that we're seeing the practice move from the financial services community to enterprise.

  • Step one of private_key_jwt itself is a challenge. If we don't store the key properly, it might not be any more secure than storing the shared secret in clear text. Yes we can use AWS Key Management Service and generate a key and sign a JWT in two commands, but this is not inexpensive for developers. We didn't even get into how one would go from generating the key, to generating a JWKS, and then using a JWK to sign the JWT. For your average developer, this is hard.

  • Dick made an excellent distinction between first party APIs and thirds party APIs--the trust implications are very different. And most APIs are first party. However, what is the appropriate level of security for first party API's--that also depends on the domain.

  • In Australia, Connect.Id is a service that enables citizens to use their bank identity to login to websites. Perhaps this is an example of a service that is seeing a wider audience of API developers, adjacent to the financial services sector, adopt private_key_jwt authentication.

  • We didn't have a chance to address the Linkedin post about "Some popular mechanisms for REST API authentication". But Ralph's list is very different, for example the post has no mentioni of MTLS authentication or DPoP authentication. Perhaps this highlights the disconnect between the API community and the OAuth community about best practices.

Livestream Audio Archive

here

Clone this wiki locally