Why are there two certificates at the endpoint to retrieve the JWK encoded keys if only one key is needed to verify the signature of a JWT?
These are the instructions where I found the endpoint: https://developers.google.com/identity/gsi/web/guides/verify-google-id-token
It is up to the auth server to decide how many keys they use. As you see there are two keys defined, each with a unique key ID (kid). Each key may have a dedicated purpose based on several criteria, such as scope, client type, key rotation, etc.
The JWT returned contains an attribute kid that specifies which key it was signed with. If you are verifying JWT signature, you have to use a key identified by the kid from JWT.
Related
I’m trying to implement a custom grant type with IdentityServer but im lost.
I have multiple applications that are already logged in an other IdentityServer with PKCE and it needs to access multiple APIs protected by an other one. How can I make it work ? Shall I implement a IExtensionGrantValidator and register IdentyServer signing keys in the one protecting the APIs ?
Sharing the keys between the IdentityServer instances would allow you to use tokens from an issuer in APIs that require tokens from another issuer.
In fact, you don't even need to share the signing keys, you can use different signing keys and add the signing key of one instance as a validation key to another.
Then when APIs want to validate a token in the backend, they will fetch the openid configuration from the OIDC provider (IdentityServer) and validate the JWT signature using the keys broadcasted by the server.
To illustrate, IdS demo app defines a single key
https://demo.identityserver.io/.well-known/openid-configuration/jwks. When you add multiple validation keys using AddValidationKey, you'll see all those keys in .../jwks metadata. Then the app will use all those tokens for validation.
// in instance A
services.AddIdentityServer()
.AddSigningCredential("CN=signing key for instance A")
.AddValidationKey("CN=signing key for instance B")
// in instance B
services.AddIdentityServer()
.AddSigningCredential("CN=signing key for instance B")
.AddValidationKey("CN=signing key for instance A")
References
http://docs.identityserver.io/en/latest/topics/crypto.html#signing-key-rollover
https://brockallen.com/2019/08/09/identityserver-and-signing-key-rotation/
I want to implement an OpenID Connect server, I don't know how should I manage JWK for clients? just a single JWK to sing all JWT tokens or generate JWK per client?
I appreciate any tutorial link to help me.
Each client should have their own JWK. OpenID Connect Dynamic Client Registration 1.0 defines jwks and jwks_ur as client metadata.
Ok, I researched about it and what I got is this:
Google uses a single endpoint to get its JWK and verify signatures. no matter for what clients.
Auth0 uses a single private key per tenant, so it uses a single public/private key for all clients in that tenant.
Keycloak uses a single key per realm. so all clients in that realm use that single public key.
My Conclusion
If our OP is multi-tenant, public/private keys can be unique per tenant, otherwise uses a single public/private key pair for all clients. Please note we should have key rotation also.
If an authentication server supplies multiple JSON Web Keys (e.g. https://www.googleapis.com/oauth2/v3/certs) which should be used to verify an OpenID Connect id_token as part of the OPenID Connect Implicit Flow?
Should the id_token be verified with the first JSON Web Key, all of the JSON Web Keys, or is the id_token considered valid if it can be verified with any of these provided JSON Web Keys?
Thanks!
When there are multiple keys in play that the OpenID Connect provider could use to sign an id_token, the header of the id_token would typically contain a key identifier (in the kid element) of the key that is actually used. That corresponds to the kid element in the JWK published on the (jwks_uri) endpoint that you describe. So the id_token would only be valid if it can be verified using the key that is associated with the kid in the header.
I want to validate a SessionSecurityToken issued by a STS. By validate, I mean certify that the token is not crafted and verity that the token is issued from the STS.
Conceptually, I know that if the STS encrypt (or sign) the token with it's private key, I could decrypt (or validate signature) with a public key.
From what I understand, the STS I am using (ThinkTecture Identity Server) uses a Symmetric Signing Key to sign to token.
The SessionSecurityToken I received contains a SecurityKeys property. What represent this SecurityKeys? MSDN documentation tells: "Gets the keys associated with this session. This is usually a single key."
Is it the SymmetricKey used by my STS? If so, it means that the symmetric key is not well protected, and if anybody gets this key, he could fake a token.
Is it the token signature? If so, how can I validate the signature (assuming that I have the symmetric key)?
Any other useful information to help me understand the way we validate a SessionSecurityToken?
So first of all - STSes don't issue a session token. They issue (i guess you use WS-Fed) a SAML token. This token is signed with an X.509 certificate.
The relying party then takes the incoming SAML token and turns it into a session token and writes that to a cookie.
So why do you want to validate that? This is done automatically by the SAM.
Why does OAuth include both an access token and an access token secret as two separate values? As a consumer or OAuth, all of the recommendations that I have seen indicate that I should store the token and secret together and essentially treat them as one value.
So why does the specification require two values in the first place?
Actually, the access token secret is never transmitted to the provider. Instead, requests transmit the access token, and then use the secret to sign the request. That is why you need both: one to identify, and one to secure
There are 2 secrets, one is token secret and other is consumer secret. Secrets are used to sign the requests (to generate the oauth signature) but not transmitted in the request header where token is sent in the header to identify the client and verify if it has access.