Keycloak JWT offline valiadation - keycloak

so I want to implement the offline validation of keycloak JWT token. The offline validation happens by taking the signature part of the JWT token and applying server's public key to validate the signature. The process is described here.
However I am facing an issue, that tokens created by keycloak cannot be verified by the use of the server's public key. For quick validation I use this service.
So here is my example:
I authenticated to keycloak and obtained an access token:
eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJMdTZNY1h4M3ZOeVkydjVwREpDMVBFaUpUUjJSbmc0S0lrSG54NnBtUjNjIn0.eyJqdGkiOiI5ODhkMmVkZS00NmZlLTRjN2EtODk3Ny1hMDA2NGEwMzMyYmIiLCJleHAiOjE1Njk5NjU2MzYsIm5iZiI6MCwiaWF0IjoxNTY5OTM2ODM2LCJpc3MiOiJodHRwOi8vbHVja3kubGhzLXN5c3RlbXMuY29tOjE4MDgwL2F1dGgvcmVhbG1zL0JTQ1MiLCJhdWQiOiJic2NzY2xpZW50Iiwic3ViIjoiNWUyMjJlY2UtZmEyMC00Y2Q4LTk4M2MtY2YyOGNiN2MxNjliIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYnNjc2NsaWVudCIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6Ijk5Y2IxMTVlLTE4MTItNDAyYi1hZmFkLWYwOWU1M2VlZDkxMCIsImFjciI6IjEiLCJyZXNvdXJjZV9hY2Nlc3MiOnsiYnNjc2NsaWVudCI6eyJyb2xlcyI6WyJ1bWFfcHJvdGVjdGlvbiIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwiYXV0aG9yaXphdGlvbiI6eyJwZXJtaXNzaW9ucyI6W3sicnNpZCI6Ijc2MjRmMWRmLTVlNTYtNGIzOS1hMjg4LWZhN2MzYmI2YjFmYyIsInJzbmFtZSI6IkRlZmF1bHQgUmVzb3VyY2UifV19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJBdXRvdGVzdCBBdXRvdGVzdCIsInByZWZlcnJlZF91c2VybmFtZSI6ImF1dCIsImdpdmVuX25hbWUiOiJBdXRvdGVzdCIsImZhbWlseV9uYW1lIjoiQXV0b3Rlc3QifQ.douJsDyObXAKylBexZCTQvEU5v3OY5xJtfNxnUhwDpIOoN1lpw7Tdxwf3jsEWi-ZTKVzV3H1zjhorPCs02tAjjpH9bDQHQmSBtn4R8V2dbXbIedBxK0kl_YfnrYTFPX66lQTpHWoWP9qngxoEqOJcFSnDFnPHwwz774PUZdqPA4FZOwb02LxDtUVKdBfM_bI41LDD2Nsvc_sKuTVuq_dbST3CqjlapAo-Q61vgSoH1zMtCGy9XUBOs1nhyeDhAaGVGcPYD3RwqYuRkfKPl0BuuB_5D8Z1xaEp-1G8M06vMIW0HpESp-NUTUb30rGib5EmAlW3rT6M2_8B6oUUtGhhA
The JWT token has been generated with a kid: Lu6McXx3vNyY2v5pDJC1PEiJTR2Rng4KIkHnx6pmR3c.
So In my keycloak installation, the key with this ID has public key:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgk9p0QOXtnzsQIVviM4kEoIGtewKAqUG9CtlQ6Esd6Z2RMu5qvQb8iBQVvkiFSHXGEd3kJqY3H7KZk+pkFuoQSdsLqGM5UhPeMjk2pIog0n0lXDxcd6Ff8hywmiIgfIWJW5DeDwvGTPLR1BiLPiina2qemACwUk5VCVdRzr2ob712PohcyNIa34PasPI1kBve0ks/wKNZK5vnGDPC6orFlJL48t2e2gB0Lz5rAJ1l2MJ+tV3cXjjB5wh62cWyJ/xYThGsK48vaXciTRVn8/sZRoJA4c+ZLKg28YOry9zHnAO8B+mj17Nj5Chpat6iYv00pqA0lMxiiQeK6yXxT6cswIDAQAB
The corresponding certificate:
MIIClzCCAX8CBgFrVaYX1jANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARCU0NTMB4XDTE5MDYxNDEwNTkzNloXDTI5MDYxNDExMDExNlowDzENMAsGA1UEAwwEQlNDUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIJPadEDl7Z87ECFb4jOJBKCBrXsCgKlBvQrZUOhLHemdkTLuar0G/IgUFb5IhUh1xhHd5CamNx+ymZPqZBbqEEnbC6hjOVIT3jI5NqSKINJ9JVw8XHehX/IcsJoiIHyFiVuQ3g8Lxkzy0dQYiz4op2tqnpgAsFJOVQlXUc69qG+9dj6IXMjSGt+D2rDyNZAb3tJLP8CjWSub5xgzwuqKxZSS+PLdntoAdC8+awCdZdjCfrVd3F44wecIetnFsif8WE4RrCuPL2l3Ik0VZ/P7GUaCQOHPmSyoNvGDq8vcx5wDvAfpo9ezY+QoaWreomL9NKagNJTMYokHiusl8U+nLMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEACJ2h6p7b9j8MPJPhvEp00WoT3kv0r3WS/8CFDPugV6WPrEexGO8aCOmn5/4GqoVGux6whnAxEZIQrTtufnMg+LCV5kEhOrHOuM2JHcA/AmkMOSXnnJXlH1gwYvOa1LV0rWxOiWvVI1bsK4Q3gelZu8CEVxluN0SU/g/9tkntFmXqARHl7BEVuBCnnEje8rVonDctmUzsb97DzXVFIIP3sUIq0B+1M3u0+Nm008u30FrZ7OOJm7qXC0KR9XOkqcTYga/4dDJ2h25bpulgFU/c0VYxCRbs+5zEij5RGbj8pW3XayPyNndNH6E00zwOeEgaBajOx+JLchg9hPKGOdeQuw==
At this point it looks like the token cannot be validate with neither the key, nor the certificate... Do I need to set some settings in keycloak to enable the offline validation? Or is it an error on the jwt.io service? What is the correct way to offline validate a keycloak jwt token?
Thank you in advance!

The issue actually was on the jwt.io website. You have to input the public key as follows:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgk9p0QOXtnzsQIVviM4kEoIGtewKAqUG9CtlQ6Esd6Z2RMu5qvQb8iBQVvkiFSHXGEd3kJqY3H7KZk+pkFuoQSdsLqGM5UhPeMjk2pIog0n0lXDxcd6Ff8hywmiIgfIWJW5DeDwvGTPLR1BiLPiina2qemACwUk5VCVdRzr2ob712PohcyNIa34PasPI1kBve0ks/wKNZK5vnGDPC6orFlJL48t2e2gB0Lz5rAJ1l2MJ+tV3cXjjB5wh62cWyJ/xYThGsK48vaXciTRVn8/sZRoJA4c+ZLKg28YOry9zHnAO8B+mj17Nj5Chpat6iYv00pqA0lMxiiQeK6yXxT6cswIDAQAB
-----END PUBLIC KEY-----
This way the service verifies jwt token correctly.

Related

Public key Required to verify the JWT issued by AzDO

I have a JWT issued by app.vstoken.visualstudio.com.
When I tried to do validate that token using
System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.Validate();
its throwing following exception
An unhandled exception of type 'Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException' occurred in System.IdentityModel.Tokens.Jwt.dll
IDX10500: Signature validation failed. No security keys were provided to validate the signature.
I suspect its because its not able to locate the public key for the issuer having
thumbprint = x5t attribute value present in the JWT header
How to get that public certificate or how to tell JwtSecurityTokenHandler.Validate() to fetch the required certificate to validate the JWT signature.
My first approach was to validate token issued by remote website locally.
To validate locally I needed to validate signature of the token using public key of the remote website (since it has used its private key to sign the token).
But instead of doing that I found out that the remote website exposes set of rest apis accessing which requires user to provide valid token as part of "bearer" header in the http request.
Currently I am using that api to determine authenticity of the user.
The remote website was dev.azure.com and it exposes set of apis and sdk to authenticate the token.
Library used : Microsoft.VisualStudio.Services.WebApi

How to Configure OAuth2 Authentication for Apache Kafka Cluster using AZURE AD

due to the lack of INTROSPECT_ENDPOINT in azure AD, I am unable to validate the token.
How to validate the Azure Access token in Java?
Usually, the ADAL or the MSAL SDK will take care of it. But, you can still manually validate the access token you get. Here is the official tutorial: Validating tokens.
In summary, there would be 3 steps:
Get the kid in token header, and the tid in token payload.
Get all sign keys from https://login.microsoftonline.com/{tid_here}/discovery/v2.0/keys, and find the key with kid
x5c in the key is the public certificate. You can use it to verify the signature of a token.

Generate JWT Token in Keycloak and get public key to verify the JWT token on a third party platform

There is an Endpoint to a backend server which gives a JSON response on pinging and is protected by an Apigee Edge Proxy. Currently, this endpoint has no security and we want to implement Bearer only token authentication for all the clients making the request.
All the clients making the requests to API will send that JWT token in Authorization Bearer and Apigee Edge will be used to verify the JWT Token.
How do I use Keycloak to generate this JWT token?
Also, Apigee needs a public key of the origin of the JWT token (the server which signed the JWT token, in this case, I believe that is Keycloak).
So my second doubt is, while I use Keycloak to generate the JWT token, how to get the public key using which the server will verify if the token is valid?
This got figured out with the help of this medium article. All the steps I have mentioned below have a detailed description in the article (Refer step 1 to 9 for token part, other steps are related to Spring Boot application) but I would like to give a overview of those in reference to my question.
Generating a JWT token using KeyCloak
Install and run KeyCloak server and go to the endpoint (e.g http://localhost:8080/auth). Log in with an initial admin login and password (username=admin, password=admin).
Create a Realm and a Client with openid-connect as the Client Protocol.
Create users, roles and map Client Role To User.
Assuming the server being on localhost, visiting the http://localhost:8080/auth/realms/dev/.well-known/openid-configuration gives details about all security endpoints
http://localhost:8080/auth/realms/dev/protocol/openid-connect/token sending a POST request with valid details to this URL gives the JWTtoken with.
Getting the public key of the KeyCloak server
Going to Realm Settings and click on Public key pops up with the Public key of the server for that Realm. Refer to this image for better understanding.
Add -----BEGIN PUBLIC KEY----- and append -----END PUBLIC KEY----- to this copied public key to use it anywhere to verify the JWTtoken. You public key should finally look something like this:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhAj9OCZd0XjzOIad2VbUPSMoVK1X8hdD2Ad+jUXCzhZJf0RaN6B+79AW5jSgceAgyAtLXiBayLlaqSjZM6oyti9gc2M2BXzoDKLye+Tgpftd72Zreb4HpwKGpVrJ3H3Ip5DNLSD4a1ovAJ6Sahjb8z34T8c1OCnf5j70Y7i9t3y/j076XIUU4vWpAhI9LRAOkSLqDUE5L/ZdPmwTgK91Dy1fxUQ4d02Ly4MTwV2+4OaEHhIfDSvakLBeg4jLGOSxLY0y38DocYzMXe0exJXkLxqHKMznpgGrbps0TPfSK0c3q2PxQLczCD3n63HxbN8U9FPyGeMrz59PPpkwIDAQAB
-----END PUBLIC KEY-----
Validating the token on a third party platform
jwt.io is a great website for validating JWTtokens. All
we have to do is paste the token and public key. Read the introduction of the website here to know more about validating the tokens.

Secure Apigee Edge proxy with keycloak?

We are using two-way TLS communication between Apigee Edge and Backend server (which is exposed using NginxIngress in Kubernetes). However, we want to integrate Apigee Edge with keycloak to secure the Apigee Endpoint endpoint (e.g https://org-name-env.apigee.net/path).
I am new to Apigee and Keycloack and after searching a lot, I am posting this question to get proper documentation on using Keycloak with Apigee Edge. Any article, community answers, suggestions, direction, documentation or POC will be helpful.
Apigee Community is a great place to ask these type questions https://community.apigee.com/
I'm not 100% sure about the entirety of this position, but I believe that Apigee Edge's approach to 2-way TLS on the south-bound leg is not directly extensible to support an external key-management service like KeyCloak. The Apigee trustStore and 'target endpoint' configs are largely fixed. That said, in your Apigee policies you don't have to use Apigee's concept of a target endpoint as your traffic's ultimate destination. With some additional complexity in the Edge policy definition, additional JS, etc, you could call out to KeyCloak's admin API and then use the response objects to construct your own south-bound 2-way TLS secure calls to your back-end services.
Below is the document I created to do the setup and created a markdown document for the same which looks something like below:
1 Generating JWT token using KeyCloak
Assuming the basic setup of KeyCloak like Realm, Roles, Users etc being done, create JWT token for a user. (You can validate this JWT token from jwt.io using the public key of KeyCloak realm to make sure the JWT token is valid and signed). The public key can be found in Realm Settings. Refer to this image to get the public key. Add -----BEGIN PUBLIC KEY----- and append -----END PUBLIC KEY----- to this copied public key to use it in Apigee configuration and on jwt.io. Here is how a valid and usable public key will look like :
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhAj9OCZd0XjzOIad2VbUPSMoVK1X8hdD2Ad+jUXCzhZJf0RaN6B+79AW5jSgceAgyAtLXiBayLlaqSjZM6oyti9gc2M2BXzoDKLye+Tgpftd72Zreb4HpwKGpVrJ3H3Ip5DNLSD4a1ovAJ6Sahjb8z34T8c1OCnf5j70Y7i9t3y/j076XIUU4vWpAhI9LRAOkSLqDUE5L/ZdPmwTgK91Dy1fxUQ4d02Ly4MTwV2+4OaEHhIfDSvakLBeg4jLGOSxLY0y38DocYzMXe0exJXkLxqHKMznpgGrbps0TPfSK0c3q2PxQLczCD3n63HxbN8U9FPyGeMrz59PPpkwIDAQAB
-----END PUBLIC KEY-----
Refer this post from medium.com for more details on JWT generation with KeyCloak.
2 Using VerifyJWT policy in Apigee
Assuming basic Apigee policy created for the server endpoint, add a AssignMessage policy to give the public key in the PreFlow section of the Proxy, so that all the requests will go via this policy and a public key of KeyCloak will be assigned to a variable. Click here to know more about configuring flows in Apigee.
AssignMessage policy XML will look something like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="Assign-Message-1">
<DisplayName>Assign Message-1</DisplayName>
<Properties/>
<AssignVariable>
<Name>public.key</Name>
<Value>-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhAj9OCZd0XjzOIad2VbUPSMoVK1X8hdD2Ad+jUXCzhZJf0RaN6B+79AW5jSgceAgyAtLXiBayLlaqSjZM6oyti9gc2M2BXzoDKLye+Tgpftd72Zreb4HpwKGpVrJ3H3Ip5DNLSD4a1ovAJ6Sahjb8z34T8c1OCnf5j70Y7i9t3y/j076XIUU4vWpAhI9LRAOkSLqDUubRX/ZdPmwTgK91Dy1fxUQ4d02Ly4MTwV2+4OaEHhIfDSvakLBeg4jLGOSxLY0y38DocYzMXe0exJXkLxqHKMznpgGrbps0TPfSK0c3q2PxQLczCD3n63HxbN8U9FPyGeMrz59PPpkwIDAQAB
-----END PUBLIC KEY-----</Value>
<Ref/>
</AssignVariable>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>
Note: It is always recommended to use KeyValueMap instead of directly using the values like private key or secret etc.
Next step is to use JWTPolicy to verify the JWT token using the public key assigned in the previous step. Mention the variable name which has the public key as its value in PublicKey tag.
The final XML file will look something like below.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VerifyJWT async="false" continueOnError="false" enabled="true" name="Verify-JWT-1">
<DisplayName>Verify JWT-1</DisplayName>
<Algorithm>RS256</Algorithm>
<PublicKey>
<Value ref="public.key"/>
</PublicKey>
<Subject>Subject from the JWT token</Subject>
<Issuer>http://issue-of-the-token.com</Issuer>
<Audience>aud1,aud2</Audience>
</VerifyJWT>
Note : Additional inputs can be verified using AdditionalClaims tag.
Click on AssignMessage, JWTPolicy or KeyValueMap to know more.

ADFS Export Default Token Signing Certificate Private Key

How can I export the Token Signing Certificate that is created when ADFS 3.0 is installed? When I open up the certificate MMC, I am able to see the certificate however the message 'You have a private key that corresponds to this certificate' is missing and I am unable to export the private key. I read in the article ADFS deep dive: Certificate Planning that I can find it in Active Directory in the following container:
CN=ADFS,CN=Microsoft,CN=Program Data,DC=domain,DC=com
However, although I can get to that container, all I see is a GUID inside and do not know how to export the private key out of Active Directory.
How can I get the private key?
******************************************** EDIT ********************************************
In case anyone comes to this later, the certs are actually in the personal cert store of the ADFS service account but they are NOT exportable. You almost certainly want the SSL cert private key NOT the token signing cert private key. The documentation
I was following to set up ADFS for SharePoint was a little confusing. The private key had to exported for the SSL cert, however the thumbprint of the token signing cert had to be placed in the web config. I was incorrectly trying to export the private key of the token signing cert.
******************************************** EDIT ********************************************
You mean the self-signed ones you get with automatic rollover?
If so, where do you see these with mmc?
They are stored in a combination of an AD container and the ADFS DB.
So you can't export in the normal manner.
For a very good reason - security. If you have the private key you can send / hack anything and it will be accepted as coming from ADFS.
The public key is available in the metadata.
If you have to do this, turn off automatic rollover and use your own certificates.