IdentityServer 3 signing certificate expiry - x509

What happens when the signing certificate (used for signing jwt tokens) expires when using IdentityServer 3?
It's unclear to me and I can't find any documentation, other than that it's possible to get a warning that it has expired. (Ref. https://identityserver.github.io/Documentation/docsv2/configuration/events.html)
Is there any mechanism that stops the use of expired signing certs?
And what happens on the client side (client being the Web API that uses IdentityServer for authentication) when validating a token signed by an expired certificate? (For example if https://github.com/IdentityServer/IdentityServer3.AccessTokenValidation is used as a middleware.)

Well I've just tested this (on IdentityServer4) and it seems to continue to work happily with an expired signing certificate, here's my test cert's validity:
I'm able to login, get an ID token and an access token and then access an API with the access token. What IdentityServer does do however is to log a warning:
2017-07-13 12:15:54.871 +02:00 [Warning]
Certificate "CN=test_expired_signing_certificate" has expired on "13/07/2016 14:14:37"
This matches what the IdentityServer (3) docs say here:
IdentityServer raises a number of events at runtime, e.g:
snip...
Expired/invalid/no signing certificate
By default these events are forwarded to the configured log provider - a custom event service can process or forward them in any way suitable for the environment.
So this would be your way of detecting it when it's already too late. A better option is to rollover signing keys periodically and within the validity of the keys, this is the common approach which also allows for a compromised key to be revoked if necessary. See this issue where the process is discussed, basically IdentityServer can handle two keys:
[Middleware refreshes] the metadata document ... once a day.
The metadata doc can hold 2 keys - primary and secondary and the middleware will load and use both when present (JWTs have a key identifier that allows picking the right one).
When you start to rollover - set both keys and at some point swap primary and secondary.

Disclaimer: I never worked with IdentityServer3
The outside world doesn't know your certificate and therefore doesn't know it's expired. The outside world merely sees your public key at:
YourIdentityServer.com/.well-known/openid-configuration
or more accurately:
YourIdentityServer.com/.well-known/openid-configuration/jwks
You can play around with this: Create a new cert on startup (see https://gist.github.com/mykeels/408a26fb9411aff8fb7506f53c77c57a). Even if you set the TimeSpan to one minute, it will keep working.
But once you wait 1 minute and restart your IdentityServer your token from last sign in will be considered invalid, because it was created with the now outdated signing key. It is checked against the new public key and fails.
It seems to be recommended to periodically replace your cert with a new one, while also keeping the previous key around, see "signing key rollover":
https://docs.identityserver.io/en/dev/topics/crypto.html#signing-key-rollover

Related

Azure AD B2C Custom Policy Key Management: Can I upload 2 policy keys and use both of them for id hint token validation?

I have a custom Azure AD B2C Sign Up Invitation flow with a single policy key. The key is used to sign the token that's contained in the invitation link email and is then validated at sign up time. The cert is expiring soon and I'm trying to figure out how to not impact users who've not accepted an invitation.
The id token that we generate is good for 1 month.
I have a key container (B2C_1A_IdTokenHintCert) that has the current key. The key container is referenced in my custom policy. I'd like to add the renewed cert to the same key container so that there are 2 keys in the on container and then swap out the cert on the web server that generates the link with the signed token.
I'd like for both old links that are signed with the current cert and new links generated with the new cert be valid during signup.
Is this possible?
You can only have one value per policy key id. However, you can upload your new certificate as a new policy key, then add an additional technical profile into your user journey that validates your token hint against the new policy key. Example: Step 1 tries to validate the token hint against policy key 1, if it's not successful, then try to validate the token hint against policy key 2. That way old links and new links can both be validated.
You can have more than one certificate inside a key container. The system will use both to determine if the invitation token is valid up until the cert itself expires.

Managing rollover with Saml 2 metadata

We are trying to implement a smooth rollover for our saml 2 service provider signing certificates.
We have created new certificates with a notBefore at the date of the rollover in the future. Those certificates are exposed on our metadata endpoint, along the certificates currently used to sign saml messages. They are not yet valid since the notBefore property is in the future. Our service provider will start using them when they become valid.
However some partners are having issues with their identity providers complaining that the new certificate is not yet valid.
So my question is the following: are we allowed to expose future certificates that are not yet valid? If not, how are we supposed to manage the signing certificate rollover in saml 2?
Unfortunately the SAML specification doesn't address how certificate roll over should be handled. Therefore, there's no consistent approach.
What you're doing seems reasonable but then I can also understand why some partners would complain about a certificate that isn't (yet) valid.
Some providers simply update their published SAML metadata at the time of certificate roll over. In other words, the metadata contains the current certificate only rather than any past or future certificates. This then places the onus on the partners to ensure they monitor the metadata and switch the certificate immediately.
Of course, this isn't always practicable. In my experience, it's usually best to communicate with the partners that the certificate will roll over on a certain date and provide them with the new certificate and/or metadata prior to that date. Partners should handle signatures generated by either the new or old certificate for an interval of time around the roll over date to ensure a smooth transition. On the roll over date, you'd also publish the new metadata.
You'd probably want an overlap between the old certificate's NotAfter and the new certificate's NotBefore.

JWT architecture for multiple users?

Most examples always take into consideration only one users using the system in the JWT/Flask tutorials. I want to understand this at a multi-user level but cannot find the correct resources.
Lets say we have the following secret key:
app.config['SECRET_KEY'] = 'randomkey'
Two Questions:
Would this key be the same for every user? if so, wouldn't this provide a security risk because if the key was stolen, anyone would have access to do whatever they want?
If it is not the same, how is the key stored on the server-side so it could be authenticated when requesting information? Would it be stored within the user's table under current token or something?
In this case, that key is the JWT signing key It could also be different from flask's secret key setting (see flask docs). It's not used for encryption so it's not intended to be a shared secret between server and users. Its role is to provide the server with a proof that the JWT content was generated by the server itself: it's a proof of integrity.
Having knowledge of that key means having the right to issue JWTs on behalf of the application, attackers could impersonate servers or make requests with some modified claims, eg pretending to be other users. This means that these keys are quite sensible from security perspective
Turns out that 1 app : 1 key, with some remarks
This key should theorically never change: if at time T1 KEY=x, a user could login in and receive a JWT signed with KEY=x. at T2 KEY=y, the user will invoke some API using the previous JWT and the server will try to verify(signature(payload , x) , y). So every user will be logged out automatically
Despite 1. It would be good to rotate the key. In this case the authentication system should save a buffer of old keys and use them to validate oldest JWT. Since a JWT should be short-lived, it could be useful set a rotation time grater than JWT expire time and just keep the last used key along with the current
This key is a secret and should be managed exactly as other secrets. Aside from terrible approaches like leaving it plaintext in the code/config, there are secret managers from cloud providers, or kubernetes secrets if you use the latter, as well as secret managers from configuration management tools (salt, ansible) or Hashicorp's Vault that is a specialized storage engine for sensible data. Anyway, it's more infra/security team concern if you are in a structured organization

Azure AD Signing Keys for JWT

When you use Open ID connect with Azure AD, the JWT issued token (id token) is signed with an asymmetric key. I saw the public key to verify that signature is available in the metadata file, https://login.microsoftonline.com/common/discovery/keys. However, I couldn't find any documentation about how those keys are generated. How can you change the keys that are available there or how can I specify a different key to sign the JWTs for my tenant ?
All sources and information suggests that this certificate roll over is done by Azure AD them self. Consumers are not able to do a manual roll over or put a certificate of their preference. This claim is supported by this answer. Also, please check this press release which mention a roll over happened in 2016
From your end you must be be ready to accept a rollover any time. Best practice is to fetch key information through discovery document. This is explained in the openid connect documentation
According to this piece of documentation, only way how to have your own signing key for your application, is custom claims mapping. Although description is very vague and instructions how to do it are scarce.

Why does OidcClient not support validating a jwt signed using symmetric key /client secret

Although Thinktecture.IdentityServer supports signing a jwt using a symmetric key, the OidcClient class does not support validating a token using one - it only supports validating tokens signed using a certificate.
Is this deliberate and are there problems or any limitations with signing a jwt with the client secret?
I am getting some push back with requiring client apps to have a certificate and if I can avoid it without compromising security I would like to do so.
IIRC OidcClient is quite old - we just did not implement it. And you apps don't need a certificate, they just need to be able to verify a signature using asymmetric crypto.
Using a symmetric key makes only sense for server-based apps since that key must be stored securely (otherwise anyone who reverse engineers the app can create valid identity tokens).
The other option is to send the id token back to idsrv to validation (for clients that don't have the required crypto libraries). This endpoint does not exist currently in beta 1 - but is on our todo list.