OIDC signature verification - verification

We are testing our own OIDC-IDP with a commercial client. (We don't have access to the clients code.) After some tests, the client always returns
OpenID Connect token validation failed: Token signature invalid (ID_TOKEN)
The IDP is in the wild of the web, the client is in our own network with a SSL breaker in between. We have a test client, also in the WWW, which works fine.
My question is, which certificate does the OIDC-client use to verify the signature. Is it the certificate of the website of the IDP? If so could it be that the reason for this error, is the ssl-breaker replacing the original certificate?

Note about OIDC lingo
OpenId Provider (OP) is analogous to SAML2 IdP
Relying Party (RP) is analogous to SAML2 SP
I knew what you were referring to when you wrote "IdP" and "client", but I want to mention that you'll commonly see OP and RP used for OIDC documentation / discussions.
Context and suggestions
The commercial RP you're testing with states that signature verification of the ID Token (i.e. JWT) is failing. To specifically answer your question, no, it is not using the x509 cert from the OP website to verify the signature. The key the RP uses to verify signature will depend on whether you've configured your OP to sign ID Tokens using:
HS256 (symmetric key algorithm); or
RS256 (asymmetric key algorithm)
Please have a look at the accepted answer on this thread for context:
RS256 vs HS256: What's the difference?
In the former case (HS256), your OP signs the ID Token with a secret key. And your RP must verify the signature using that same secret key. (NB: as you probably know, it's important to keep this shared secret key safe and secure.) If this is your environment, perhaps the commercial RP has a configuration option that allows you to upload or copy/paste in the secret key.
In the latter case (RS256), your OP signs the ID Token with a private key, but your RP verifies the signature using its public key counterpart. If this is your environment, perhaps the commercial RP has a configuration option to specify "jwks_uri" and "kid". These refer to the URI that your public key is published to, and its key ID, respectively.

Related

Use of AddSigningCredential(cert) in Identity Server 4

I have set up an IdentityServer 4 application as per the following answer. The author has used X509Certificate2 in AddSigningCredential(cert). I used AddDeveloperSigningCredential() in development, which has created a tempkey.jwk file in my project folder.
I then tested this Identity Server 4 application with postman:
The above call results in the successful generation of Token. Now, I need to go into production. I have created an Azure App Service to host the Identity Server 4 application.
I have a very little understanding of Digital Certificates and Identity Server 4. I have gone through a few articles/answers but I am getting super confused. Just need to understand all of it in easy words.
My questions are:
How can I create the X509Certificate2 certificate, as done here?
How would the Client application be using this certificate?
Where is it being used in development mode, as I am not providing any Public Key in the Postman call?
How can I create the X509Certificate2 certificate?
This answer might help here: https://stackoverflow.com/a/58136780/1658906.
How would the Client application be using this certificate?
It only uses the public key from the certificate if verifying the token.
Your identity provider (your IdentityServer app) uses the certificate to digitally sign the tokens.
An app that wishes to verify a token issued by the identity provider can use the public key from the certificate to verify the token is valid.
Apps usually get the public key from the discovery endpoint: https://identityserver4.readthedocs.io/en/latest/endpoints/discovery.html.
Getting it from there instead of hard-coding the public key is best practice since it enables key rotation more easily.
The certificate's private key needs to be kept really secure.
If someone has the certificate private key, they can create any token they want, and it'll be considered valid by the applications.
Meaning they could impersonate any user or elevate their permissions etc.
Where is it being used in development mode, as I am not providing any Public Key in the Postman call?
Client apps do not use it when requesting a token.
Only if you want to verify if a token is valid.

Validate client certificate

In my project, I need to check and validate client certificate for each users' request and then give them access to calling my APIs. My users are machines (other API or library). They append a certificate(s) to their request and send it to my hosted API.
I implement a custom authentication handler and retrieve client certificates successfully. Right now, I compare client certificate with a list of valid certifications in my appsetting.json (Thumbprint, Issuer and Serial number).
If all of these three properties are same as the client-certification, I return return Task.FromResult(AuthenticateResult.Success(ticket)); otherwise I return
return Task.FromResult(AuthenticateResult.Fail("certificate is not valid"));
everything works fine but I do not feel good about how I validated client certificate. I would like to know if there is elegant way for validating client certificate rather than my solution in ASP.NET CORE.
Issuer and Serial number are controllable by an attacker, so they are not suitable for validation purposes.
Thumbprint is a SHA1 of multiple properties of the certificate, including issuer, serial number, public key. That's probably OK, for now, and can't be changed by .NET because it's a Windows feature, but thumbprints are meant for reference, not security.
A better approach would be to compare the certificate Signature and hash, and put a minimum quality on the hash of SHA256 or higher. cert.SignatureAlgorithm.Value; will give you the algorithm as an OID, you can then new up an System.Security.Cryptography.Oid with that and get use the FriendlyName property to get the algorithm in text, but getting the actual signature isn't supported, you have to restore to 3rd parties like BouncyCastle. So that's probably out, because it seems silly to take a dependency for that.
Really this boils down to how you register the client certificates. What I would do is ask for the certificates (or have a registration process somewhere, like, say nuget has for signing certificates), put them into the X509Certificate2 class then create a SHA256 hash of the RawData property and add that to your allow list. Then do the same for incoming client certificates and compare the SHA256 of the rawdata from the inbound certificate against your allowed list. Of course now you have to cope with certificate expiration ...

Verify JWT on browser

I have been reading about JWT and I understand it has three parts namely, header, payload and signature.
I keep the hashing algorithm used in headers, basic information in a payload eg. name, age , role, expiry etc in payload and then both of these are base64 encoded and then hashed using the
algorithm specified in headers to obtain the JWT
I have a frontend where I can login using username and password.
The login request goes to a server which authenticates it and returns a JWT. Lets suppose the algo used is HS256 which is a symmetric key algorithm.
So the server will have the secret key using which the JWT will be generated.
As part fo login request's response, the browser will have the JWT.
Now this JWT could be tampered with on the way so before it is used, I should verify the authenticity of JWT.
To verify, I need the secret key.
Questions:
How do I get this secret key on the frontend?
The payload can keep any information about a user (Not any sensitive information eg. passwords). Since JWT can be tampered with on the way, is it not dangerous to use the payload information without verifying the JWT on frontend?
The server which receives the JWT is the one who verifies the token. If someone modified the token, verification will fail and access will be denied, as (hopefully) no one outside the server knows the secret and therefore can't create a valid token. If the client knows the secret, esp. in browser/js envrinoments and with symetric hashing algorithmns, it's a big security risk and someone could steal the secret and create a new token with a valid signature.
Any bearer token should only be used over HTTPS. And TLS, which secures the HTTPS connection has integrity checks built in to prevent modification in transit.
So there's no need to verify the token on the client side.
Also it' better to treat the JWT token as some opaque string. This allows the issuing server to encrypt its content without breaking your application.
As others have pointed out, the client should never be in possession of the signing key, because the client can never be trusted.
Now, if the token is signed with an asymmetric key, you could download the public key and verify the token without compromising the security of the system. There are JavaScript libraries out there that can do this, but there's no reason you should be doing this.

When to use RS256 for JWT?

So, right now I'm building an API for third parties uses and I was reading about RS256 and HS256. What I understood was that diff between is that in the first one you use a public key to verify and a private key to sign, and the other one, use just one key.. So if you use RS256 if because you want to keep your secret key secure and want the client to verify the token, but what I don't understand why you would like to verify the token in the client? Because you do a post request to the server, then it sends you back a token and whenever you want to make an authorized request you just use that token and the server verifies it and let you continue if its ok. So, why you would like to verify the token in the client? I thought it was a backend's duty.
I think maybe I'm wrong in something, hope you help clear this. Thanks.
EDIT:
So, my question is, I know the differences between RS256 and HS256 but what I don't understand it's the flow of how is use it. Right now I'm developing a third party api, and I just need to return a token when the client ask for it and then in the request that needs it, just verify from the server if it's a valid token. From what I understand, RS256 it's used when you want to verify your token from the client, if that's right, someone can give me an example of when or why would you want to verify the token in the client?
Use RS256 when:
tokens are signed by a third party, usually an Identity Provider(e.g. oauth2/oidc), and you need to verify that the token has been issued by a trusted entity
tokens are signed by clients, usually to get access to an API, where clients have previously registered the public key
tokens are signed by a centralized authentication server in a SingleSignOn system and they are used to get access to several federated servers
tokens are used to transfer data between two parties, not neccesarily for authentication purposes, and the signature is used to ensure the identity of the signatory
Use HS256 when:
tokens are signed and validated by the same server

ADFS 2.0. Figuring out purporse and value of each X.509 certificate

I'm new to all this security features, and recently I was asked to look into ADFS 2.0. I found ADFS uses the following types of X.509 certificates to communicate with Relying Party (RP):
Common for all RPs:
1) Service communication
2) Token-signing
3) Token-decrypting
Specific for RP:
4) Encryption certificate
Help me out please to figure out which one is really important and needed in a real-life production scenario where all 3 parts are involved: user, service provider (our company), IdP(ADFS) (on customer's server).
1) What I found regarding first certificate in MS help: "This is the same certificate that a federation server uses as the SSL certificate in Internet Information Services (IIS)" I'm not sure it's true coz I was able to replace them separately not affecting each other so they definitely might function in parallel. So no idea what this certificate is needed for.
2) Second one is for signing up issued tokens so that RP is able to make sure the token is really issued by trusted ADFS, not intercepted, right?
3) Third one is probably for reverse purposes: ADFS makes sure the message is really from trusted RP.
4) Encryption certificate for specific RP helps encrypt whole message (token), so that even if you got https public key and intercept a message from ADFS, you can not read it not having other public key which supposed to be only know to RP, correct?
Correct me if I'm wrong please.
All this certificates are optional and Micorosoft says nothing about importance of which, the only mention I cound in WIF SDK help saying it's better to use token encryption certificate in real life. The thing is we have HTTPS protocol being established for ADFS-RP communication (IIS is set up to use https on both sides). Is not it enough for secure communication? I wonder: do we really need 2), 3) and even 4)?
In a real life scenario, you have at least two:
1.) SSL certificate - just common sense nowadays, and recommended by the SAML 2.0 SSO profile. This could be the same certificate as IIS that's front-ending ADFS.
2.) Token signing / verification (not "decrypting") certificate - required to conform to SAML 2.0 profiles that use "front channel bindings" (HTTP Redirect/POST). If you're the Identity Provider (IdP) then you'll have the private signing key - if not, just the certificate (w public verification key). Indeed this is to verify that the assertions have been issued by a trusted party, and not tampered with. It is absolutely critical for federation otherwise anyone can forge their way into your environment (as the SP (RP)).
An encryption certificate would indeed be used to encrypt portions of your SAML messages - which is common if you're trying to hide information that may be passed via a user's browser (like sensitive attributes within a SAML Assertion's Attribute Statement).
1 and 2 are mandatory.
ADFS will not let you add a RP binding via importing metadata if it's not a https connection.
The definition of a claim is "A statement about a subject; for example, a name, identity, key, group, permission, or capability, made by one subject about itself or another subject. Claims are given one or more values and then packaged in security tokens that are issued by a security token service (STS)". To ensure the validity of the token it needs to be signed.
Whether the token itself is encrypted depend on the security requirements.