Validating JWT signed with hmac-sh256 - hmac

I am working on a project to use the Katana OpenID Connect middleware to authenticate with a third party (OpenAM) provider. The provider is signing the JWT with hmac-sh256. When the OpenID middleware is validating the JWT via a call to ValidateToken it is throwing the following exception:
{"IDX10503: Signature validation failed. Keys tried: 'System.IdentityModel.Tokens.X509AsymmetricSecurityKey\r\n'.\nExceptions caught:\n 'System.InvalidOperationException: IDX10618: AsymmetricSecurityKey.GetHashAlgorithmForSignature( ... ) threw an exception.\nAsymmetricSecurityKey: 'System.IdentityModel.Tokens.X509AsymmetricSecurityKey'\nSignatureAlgorithm: ...hmac-sha256', check to make sure the SignatureAlgorithm is supported.\nException: 'System.NotSupportedException: Crypto algorithm 'http://www.w3.org/2001/04/xmldsig-more#hmac-sha256' not supported in this context.\r\n at System.IdentityModel.Tokens.X509AsymmetricSecurityKey.GetHashAlgorithmForSignature(String algorithm)\r\n at ......
What am I missing or does the default SecurityTokenHandler really not support that algorithm?
Thanks,
Gordon

I'm not familiar with Katana but to me it looks like the wrong code path is triggered: the exception complains about an assymetric security key but the hmac-sha256 algorithm is based on a symmetric key (i.e. the client secret)
also note that you need a relatively recent version of OpenAM because it contained an HMAC related bug before: https://bugster.forgerock.org/jira/browse/CAF-112; something at least more recent than OpenAM-12.0.0-SNAPSHOT_20140417

Related

Java code for verification of FusionAuth HS256 signed id token

How to verify HS256 ID Token using FusionAuth java Client libraries ?
Description: I have created an app in FusionAuth that has a Client ID and Client Secret generated, I have not touched any other section/tab like JWT etc, default JWT signing algo is OIDC standard HMAC SHA256.
I tried using following code approach to validate the token based on public key, but its not working for HS256 signed token, I searched over internet and found public key is not applicable for HS256
Could you please provide me a Java code to verify HS256 signed token using FusionAuth Java client libraries (https://github.com/FusionAuth/fusionauth-jwt).
Please also let me know that do I need any additional configuration on FusionAuth Admin Console.
Code which I tried: It's giving blank public keys.
List<JSONWebKey> keys = JSONWebKeySetHelper.retrieveKeysFromJWKS("http://localhost:9011/.well-known/jwks.json");
Map<String, Verifier> publicKeyVerifiers = new HashMap<String, Verifier>();
JWT jwtDecoded = JWT.getDecoder().decode(idToken, publicKeyVerifiers);
Tokens received by apps should usually be signed with an asymmetric key. You can then verify the digital signature of the token with its signing public key, which is provided via the JWKS endpoint. The most mainstream algorithm for tokens is RS256. Perhaps you need to reconfigure as suggested here?. I think your code will then work also.
HS256 is a symmetric algorithm, which feels wrong, since clients would only be able to verify JWTs if they had the full signing key. This enables a malicious client to mint their own tokens, whereas only the Authorization Server should be able to do that. For this reason, if JWTs are ever signed with symmetric keys, the JWKS endpoint will not provide the token signing keys.
Meant to say Curity have a good related doc:
JWT Best Practices
It looks like there is an example in the README:
// Build an HMC verifier using the same secret that was used to sign the JWT
Verifier verifier = HMACVerifier.newVerifier("too many secrets");
// Verify and decode the encoded string JWT to a rich object
JWT jwt = JWT.getDecoder().decode(encodedJWT, verifier);
// Assert the subject of the JWT is as expected
assertEquals(jwt.subject, "f1e33ab3-027f-47c5-bb07-8dd8ab37a2d3");
https://github.com/FusionAuth/fusionauth-jwt#verify-and-decode-a-jwt-using-hmac
With HMAC signing you need to distribute the secret ("too many secrets" in the example above) to all locations which need to verify the JWT.

How to validate an OAuth2 access token (JWT) without accessing the auth server

Trying to understand the 2-legged client credentials scheme in OAuth2. Some people state that JWT is great format for Access Token because it is self-contained and resource server doesn't need to verify the token from the authorization server (STS). But how is this done? The only way I see the resource server could itself validate the JWT is by storing a public key on the server, which is used to verify the signature.
When using a JWT as an access token, the Resource Server doesn't need to call out to the Authorization Server to verify it. Indeed the Resource Server will need to store the public key of the Authorization Server to do so. Obtaining that public key is an out-of-band process.
Verification of a JWT consists of checking the signature plus some additional checks on claims embedded in the token e.g. timestamps (iat, exp, nbf) and identifiers (aud).
The advantage of JWT over other forms of signed data/tokens is that JWTS are standardized and flexible wrt. cryptography used by them which makes it possible to use standard libraries to create/verify them instead of having to write custom code.

What is the Signing Credential in IdentityServer4?

We are in the process of implementing Identity Server 4 with our .NET Core web app.
I went trough the Identity Server documentation. When configuring the Identity server (using DI) there is the line:
.AddTemporarySigningCredential
I'm trying to understand what this Signing credential is but couldn't figure out. Therefore I don't know if it's ok to use the built in temporary, or if I should provide a different one.
My question is, what is a signing credential and how should I use it?
In the Identity server documentation this is the definition:
Adds a signing key service that provides the specified key material to
the various token creation/validation services. You can pass in either
an X509Certificate2, a SigningCredential or a reference to a
certificate from the certificate store.
So it seems important :)
The Authorization Server will sign tokens with a key. Resource Server(s) should verify that the token's integrity with a key. Together they form a (usually asymmetric, e.g. public/private) key (pair). By default IdentityServer will publish the public key for verifying tokens via the /.well-known/openid-configuration endpoint.
For development scenarios, you typically want to skip the fuss of properly managing secrets like said keys (which is really important to do properly in production!). For these development scenarios you have the option of using adhoc solutions like AddTemporarySigningCredential, which was used for .NET Core 1.x.
With .NET Core 2.x this will change and you will need the AddDeveloperSigningCredential() extension method.
That answers the question of what it is. On how to use it: you simply call the method you need depending on your .NET Core version inside the ConfigureServices(...) method of your application's Startup class.
Apart from that you don't need to do anything special, except of course take care that you use a proper key pair in production.
See also the docs on Cryptography, Keys and HTTPS and the bit on Configuring Services for Keys. From the latter document, here's a relevant alternative for production cases:
AddSigningCredential
Adds a signing key service that provides the specified key material to the various token creation/validation services. You can pass in either an X509Certificate2, a SigningCredential or a reference to a certificate from the certificate store.

How to keep client secret for OAuth2 login to Parse server secure?

I want to enable users in my macos app to be able to securely login to my Parse Server using third-party Oauth2 login. I have been searching for the best approach to do this, but still have some problems. If I understand correctly, logging in requires:
Enable oauth in my Parse server config file (for twitter, google etc).
Get the access token to the provider (e.g. twitter) using a client side OAuth login. I am currently using OAuthSwift.
Login to Parse using the provided access token (from 2) as suggested in the swift example provided here, i.e.
[[PFUser logInWithAuthTypeInBackground:provider authData:authData] continueWithBlock:^id(BFTask<id> *task) {
return task;
}];
This login approach requires the use of the client key and client secret for each provider. How can I safely store these keys-secrets on my Parse server and access them programmatically? Should I use PFConfig and access them during runtime? Is that safe? Or is there something I am doing very wrong here? If anyone has a better approach or an example as to how I should enable OAuth login I would appreciate it (since I am on macos I can not use TwitterUtils and FacebookUtils).
No secret key should ever be used on your client. The client key can be considered "public", and is actually optional (though recommended).
Your secret key should only be stored on your server, preferably as a config/env variable (Note: NOT PFCONFIG). Any use of it should be on your server, and you can create a cloud code function that will use the key as needed and return necessary values to your client. The client should call this, receive a key you need, and then use it appropriately.
Although I'm also not familiar with a client secret key in general? This is the first I've seen of it. I wonder if you've misunderstood any documentation?

OAuth 2.0 Access token is not encrypted?

I am using System.IdentityModel.Tokens.jwt library for jwt access token and after i call WriteToken, I can get back the access token value from ReadToken in another program. So the access token is not actually encrypted by default?
Not encrypted, but it should be signed so as to prevent tampering.
The jwt library has a ValidateToken method to check the token signature is correct using your token signing cert or key.
You would need to rely on SSL for encryption.
This Blog post gives a bit more detail on the difference between signing and encrypting the token.
If you think it sounds a little crazy for Oauth2.0 to rely on SSL then you wouldn't be alone. Check out Eran Hammer's thoughts on Oauth2.0 and why he walked away from it.