Episode 005: 04‐11‐2024 Best Practices for Client Authn - GluuFederation/identerati-office-hours GitHub Wiki
- Host: Mike Schwartz, Founder/CEO Gluu
- Guest: Ralph Bragg, Co-Founder/CTO Raidiam
- Co-Host: Dick Hardt, Founder Hello
Best Practices for Client Authn
Identerati Office Hours Livestream - Episode 5 - Best Practices for Client Authn
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:
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?
-
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.
- 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
One time:
- Generate a keypair and store it in something like a
p12
keystore file - Output keys as
jwks
- Perform DCR: set
jwks
param (or point to hosted jwks viajwks_url
)
For each token request:
- Generate JSON payload and RS256 sign JWT with JWK from JWKS
- send request to Token Endpoint with params
- client_assertion_type=
urn:ietf:params:oauth:client-assertion-type:jwt-bearer
- client_assertion=
JWT HERE
- client_assertion_type=
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
}
-
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.