kid not matching on OAuth 2.0 flow - oauth

I'm using Okta for identity management. As the client in authorization flow, I send an authorize request to Okta. This works successfully, and I get a JWT payload. I want to verify the JWT signature, so I make another call to Okta in order to fetch the keys. However, the key ids (kids) do not match and verification fails.
Initial authorize request:
https://{{site}}.okta.com/oauth2/v1/authorize
?scope=openid
&response_type=id_token
&client_id={{client_id}}
&redirect_uri={{redirect_url}}
&nonce=4euiv0v52at3la15e7qlu1mt43
&state=7c92bqulrmdk2jk0ro9rd3mf5j
Response is a 403, redirecting me to:
{{redirect_url}}/id_token={{id_token}}
The header of the id_token is decoded into:
{
"alg": "RS256",
"kid": "2YKtkekCjCRWN0YqGsjUrNwIQaxGg5ahfHW0_fK8t64"
}
So far so good. I know that the authorization has succeeded. Time to validate the JWT.
However, when this is followed up with:
https://{{site}}.okta.com/oauth2/v1/keys
Or
https://{{site}}.okta.com/oauth2/v1/keys?clientId={{client_id}}
(they both return the same response), I get back this:
{
"keys": [
{
"alg": "RS256",
"e": "AQAB",
"n": "gv1rI9A7mrOoViJZTzUfiZl7YdEzLEofvRoVbXCgeW7aOmoKcAkWGHvqNRGoFgi8auV5b_TSgTXKq_TV1fz643hpAtba3V0Uw2lXchTbqXpmVRYXI1t4FIwRMXLe4Q-kcvp9la21e3D1lszjdPbFNX5GLAhrCW0Thu2HYbTLg6TbDTMaiQCMo15hek0JgZqRGzCkt9kINnwPVLXV_bkSh_fHWo_6G1L0MKYYQcgE6zvPlULLek98-yZ6Nlg6nJUY9nHn0qjhzqqq-bz_Vin8qi3Bt7SjUKwk7HbaugM84AEgDxYE5JgsaALIl5SgIc3GgFEc69qKWymoD-w1a8f1HQ",
"kid": "SOxFkBSLWefjlZoDI49Hk0nqlYtC28cjhTlVAYEzAxs",
"kty": "RSA",
"use": "sig"
}
]
}
Where the kid does not match what I received in the original response.
Where is my mistake?

You need to create an authorization server and use it as the endpoint, for example:
https://{{site}}.okta.com/oauth2/{authorizationServerId}/v1/authorize
You should also be able to use the default one:
https://{{site}}.okta.com/oauth2/default/v1/authorize
Note that this is different than the route you were using (which does not specify an authorization server):
https://{{site}}.okta.com/oauth2/v1/authorize
You should specify an authorization server in your case (like example 1 and 2 above), for both OAuth 2.0 and OpenID Connect.

The problem was that this account was setup with pinned, not rotating keys. oauth2/v1/keys requires the client id to be passed in as a parameter if you are setup with pinned keys; the correct parameter name is "client_id", not "clientId." This results in the expected output.

Related

Customize Oauth2+JWT token response with spring boot

I am using Oauth2+JWT+Spring security in one of my project. When i hit /outh/token using username/password i am receiving access token in the response with other details like
{
"access_token": <token>,
"token_type": <type>,
"refresh_token": <refresh-token>,
"expires_in":<secs>,
"scope": <scope>,
"jti": <value>
}
Is it possible to customize this response like
{
data: {
"access_token": <token>,
"token_type": <type>,
"refresh_token": <refresh-token>,
"expires_in":<secs>,
"scope": <scope>,
"jti": <value>
},
details:{
//extra information
}
}
I'm confused, don't know how to ask more clearly: "what is the additional data you want to send?". Just give an explicit sample.
I'll answer guessing that this data is related to the authorized entity (the user when answering within authorization-code flow and the client within client-credentials flow): non standard data should be set as private-claims, inside the JWT itself and on token introspection endpoint.
How to add such private claims depends on your authorization-server. For spring-security one, this is done with an OAuth2TokenCustomizer. For Keycloak, you have to provide a "mapper", etc.
The client which received a payload like the one you show, will only send the access-token when issuing requests to resource-server(s). It is important that this token holds all of the data needed for resources access decisions. Some claims are specified by OAuth2, OpenID defines some more standard claims, and you are free to put whatever additional data in private claims (within the limits of the maximum token size).
Also, if your client needs to read claims, it should use ID token, not access-token (request openid scope when initiating OAuth2 flow). Access-token should be interpreted by resource-server only.

Outlook Oauth .default suffix error trying smtp and imap after getting token

Im trying to access an Outlook email using Oauth , Already set this permissions on Azure App:
So, using Oauth 2.0 client credentials grant I obtain the access Token:
But, when I try to authenticate with that token it fails, so I read that it was necessary to generate a second token call using that first one as a parameter and using imap and smtp scopes concatenated, and I tried like in the examples:
And as you see, I get this suffix error :
{
"error": "invalid_scope",
"error_description": "AADSTS1002012: The provided value for scope https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send
is not valid. Client credential flows must have a
scope value with /.default suffixed to the resource identifier (application ID URI).\r\nTrace ID: 41d2086b-f83e-41d8-b405-115249b27901\r\nCorrelation ID: 6afef855-3fc9-4259-864b-4ec8e293e9d0\r\nTimestamp: 2022-04-29 00:02:06Z",
"error_codes": [
1002012
],
"timestamp": "2022-04-29 00:02:06Z",
"trace_id": "41d2086b-f83e-41d8-b405-115249b27901",
"correlation_id": "6afef855-3fc9-4259-864b-4ec8e293e9d0"
}
Any idea what am I doing wrong ?, why the first token its not enough or how do I get the access one in the second call ?
Thanks in advance !!

"AADSTS54005: OAuth2 Authorization code was already redeemed, please retry with a new valid code or use an existing refresh token" Az API Management

I am trying to obtain an authorization token to consume a published API in Azure API Management, for which I am performing the following steps:
Call the authorization URL as follows:
https://login.microsoftonline.com/common/oauth2/authorize?
client_id=<CLIENT_ID>
&response_type=code
&response_mode=query
&redirect_uri=<REDIRECT_URI>
&scope=SCOPE
Immediately after, I call the following URL with the obtained authorization code and other parameters in the body and to send them as form-data:
POST https://login.microsoftonline.com/common/oauth2/token
client_id=<CLIENT_ID>
scope=SCOPE
grant_type=authorization_code
client_secret=<CLIENT_SECRET>
code=<AUTHORIZATION_CODE_PREVIOUS_STEP>
As a result, I get the following error and cannot continue:
{
"error": "invalid_grant",
"error_description": "AADSTS54005: OAuth2 Authorization code was already redeemed, please retry with a new valid code or use an existing refresh token.\r\nTrace ID: f0264d85-2f41-4009-9e8e-1a211209e100\r\nCorrelation ID: c6b15ffb-82e8-49aa-941f-6c85be4d9601\r\nTimestamp: 2022-01-18 15:06:55Z",
"error_codes": [
54005
],
"timestamp": "2022-01-18 15:06:55Z",
"trace_id": "f0264d85-2f41-4009-9e8e-1a211209e100",
"correlation_id": "c6b15ffb-82e8-49aa-941f-6c85be4d9601"
}
I understand that the authorization code is for one use only but, in my case, on the first attempt I get this error.
Any help is appreciated

How is signature verified on OKTA JWT token? [duplicate]

I was decoding a JWT token via jwt.io (in the Debugger section) to see Headers, Payload. Surprisingly, it also verified, and I could see it (jwt.io debugger) is able to retrieve the public key as well.
So my question is: Does JWT token provide the public key as well as part of the JWT token?
I am pasting part of it (can't paste full due to security reasons, will be truncating part of the actual JWT token)
F3cy5jb21cL2V1LXdlc3QtMV9ZckVRYjY5Z1giLCJleHAiOjE2MDE2Mzg4OTMsImlhdCI6MTYwMTYzNTI5MywidmVyc2lvbiI6MiwianRpIjoiNmI2YmZiNmYtY2M0MS00N2Q5LWI0YzYtOTBmOGFmNWM2MjQ1IiwiY2xpZW50X2lkIjoiMTM0MWxxa3N1ZmUwbm1vaW9kdnRjc2t2cWIifQ.RtKfz54uBgSZ1gc4KRPjzL4dPe5AbH2YMJu-DDvIxBzgMjqT9q4ApGzcWYB62-MgDUf-F_hK0kF9eIwAi9fARhp 0HGGnyiuydW_our6zE3EphLvXQByTDY5xzOUuSvt7WbDZWeSfpHcjrBttRSJAPOsZ2gInafKjZgWKyGL4vJB9swEhOMSSpTQDGWKenJCyp4emhe8E4XGzYTo9WEb-Wqg6sI__LrusDNd917FaocPKBxA
Decoded messages (again truncated)
Headers
{
"kid": "cJ0PzkBXPyjX7FM67jcOECIY=",
"alg": "RS256"
}
Payload:
{
"sub": "13lqs0moiodvtcskvqb",
"token_use": "access",
"scope": "example.com/Manage",
"auth_time": 1601293,
"iss": "https://cognito.eu.amazonaws.com/",
"exp": 1601638,
"iat": 10353,
"version": 2,
"jti": "cc1-47d9-b6-5c6245",
"client_id": "nmodvtcb"
}
In there, can see the Public key (truncated)
-----BEGIN PUBLIC KEY-----
QEFAAOCAQ8AMIIBCxmf9bakWk
556KYmIZB+Sy1ftkkGa4qlUsmRvcG2Hll+7HBWp1ao6MVLskjdaaKg8iH1Iz4DKG
lgqT/ndwhoxvTBuvm0X2CZoNzZn4S8wDTr78m/S/YegZRhv6y58gkiKSEmbbC/g5
Bp+AF88NwBvLm1jdd
-----END PUBLIC KEY-----
Where from the debugger in jwt.io is retrieving the public key? I am not able to understand this.
The token contains the issuer (iss) of the token and the key id (kid), which identifies the public key that is needed to verify the signature
With this information, jwt.io can find the public key in form of a JWK (JSON Web Key) on a JWKS endpoint (/.well-known/jwks.json), to verify the token. A JWKS (JSON Web Key Set) contains an array of JWKs, the link shows an example.
According to the cognito documentation, this mechanism is used, when you use the Amazon user pool to authenticate your users.
Providing keys via a jwks endpoint is a standard mechanism which is also used by other providers, e.g. Microsoft Azure.
I've been trying to understand that myself too. If you open developer tools and see requests made by jwt.io when you paste the token in the debugger page you'll see it makes additional requests.
In my token the iss was:
"iss": "http://localhost:8080/auth/realms/myrealm"
hence jwt.io added the standard path /.well-known/openid-configuration and made XHR request to
http://localhost:8080/auth/realms/myrealm/.well-known/openid-configuration
Where it found a lot of information in json and among them there was jwks_uri
{
...
"jwks_uri": "http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/certs",
...
}
And then there was another XHR request to the above url and response was jwks.
Having that public key the jwt.io could verify the token. At least that's what I think happens.

How can I manually validate token I got from my custom authorization server by using jwt.io?

I am learning about OAuth2 and OpenID Connect by experimenting with ASP.NET Core and IdentityServer4. So far I created a protected API server, an authorization server and a client by following a certain Udemy course. Things worked out well as client is able to get access token from the authorization server and use it to access protected API in the ASP.NET Core Web API project.
However, I am curious how can I manually validate JWT I get from my authorization server. The token I get is this:
eyJhbGciOiJSUzI1NiIsImtpZCI6IjdiMjM1NzYyMTRlOTg3ZjE3NTdjMWYxNDE1ZTg4OGEyIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1NTMyNTYxNzMsImV4cCI6MTU1MzI1OTc3MywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjpbImh0dHA6Ly9sb2NhbGhvc3Q6NTAwMC9yZXNvdXJjZXMiLCJiYW5rT2ZEb3ROZXRBcGkiXSwiY2xpZW50X2lkIjoiY2xpZW50Iiwic2NvcGUiOlsiYmFua09mRG90TmV0QXBpIl19.boION1QMOxuHxgIkBT0hZchkCEzINSpIS20Az5HkkkkrbH72IHqC2u9tOQobCsPt4okSPIuKGmgsGY2oyPMNcQpZPAOivmKXknhij_lhTv7pzaSXmFFSSpih-eigk4243VkGz8fTH9vA_IHmQ59o9zv0Wva_pKBt9lBSd39BDocNblJR092VHl66gAp79iEJctDzEKBBdN_E-RCrgPPsetU_sO0wqgOuxA0wECAo_jQhPu3LkuU9sKfj2HAFGLVxwz0Is3SAg1XIXeZylivAJdXThMkVypjrFBTeehso_9g26MVY4bKCfZ5Bx75NmYUbOfpX1gLPSo0CWvTfHhwaNg
When I decode it on jwt.io website I get Header:
{
"alg": "RS256",
"kid": "7b23576214e987f1757c1f1415e888a2",
"typ": "JWT"
}
and Payload:
{
"nbf": 1553256173,
"exp": 1553259773,
"iss": "http://localhost:5000",
"aud": [
"http://localhost:5000/resources",
"bankOfDotNetApi"
],
"client_id": "client",
"scope": [
"bankOfDotNetApi"
]
}
Since I used RS256 algorithm for signing I need to add public key to the jwt.io to verify the token. But where do I get this public key?
If I go to discovery endpoint of my auth server (eg. http://localhost:5000/.well-known/openid-configuration/jwks) I get following data:
{
keys: [
{
kty: "RSA",
use: "sig",
kid: "7b23576214e987f1757c1f1415e888a2",
e: "AQAB",
n: "509tIiUvmKkjjGOwzKElduRqpRND7YO-Op-IlsAeNwTlxY9_t22XfCqmxUyNvuvmdIVYXz-utl5bee3Tjwp8e7ok-Vn2uX-nI0jBcjTIKL0arbd7Qo5XgvICU4x-UcINrHtqMnY4S_R0uMKgaJkl3105bh9svQh--65tknjiKqmefT4M5SLHStWTisy2e0YwiaqvLam-O_rtbEawMy5-4avZep33y9Wz_JlgWyQ4jKD1Kn8mNGybjRoW3FJRkqzVNUSrGzjqwdDPL1cZOzM2HnbBqwVSFNnJiRYxPxKL_N8Q4CS9e2OVRjTof_EdzTTGC5mkOPhBCjpmvYS5d0j6JQ",
alg: "RS256"
}
]
}
But which of these is public key? I tried pasting values for n, e and kid to jwt.io page under public key textfield in the "verify signature" section, but I always get "Invalid signature" error.
So how do I get public key for RS256 token from discovery endpoint and how can I use it to validate token in manually in jwt.io website?
Put there the whole (first and only) keys object value, including curly brackets, at least the following:
{
"kty":"RSA",
"kid":"7b23576214e987f1757c1f1415e888a2",
"e":"AQAB",
"n":"509tIiUvmKkjjGOwzKElduRqpRND7YO-Op-IlsAeNwTlxY9_t22XfCqmxUyNvuvmdIVYXz-utl5bee3Tjwp8e7ok-Vn2uX-nI0jBcjTIKL0arbd7Qo5XgvICU4x-UcINrHtqMnY4S_R0uMKgaJkl3105bh9svQh--65tknjiKqmefT4M5SLHStWTisy2e0YwiaqvLam-O_rtbEawMy5-4avZep33y9Wz_JlgWyQ4jKD1Kn8mNGybjRoW3FJRkqzVNUSrGzjqwdDPL1cZOzM2HnbBqwVSFNnJiRYxPxKL_N8Q4CS9e2OVRjTof_EdzTTGC5mkOPhBCjpmvYS5d0j6JQ"
}

Resources