OAuth Access Token Exchange Protocol

179 views Asked by At

We have an application registration on Azure AD to which users authenticate to by requesting their own access token:


{
  "aud": "CLIENT_ID",
  "iss": "https://login.microsoftonline.com/TENANT_ID/v2.0",
  "iat": 1701270410,
  "nbf": 1701270410,
  "exp": 1701274744,
  "aio": "AUQAu/8VAAAAHAdHfHVno15JVZNMHln+AtJiQ5c9jjw5ny4AfK+0gq8siK+6H8bxHnE40bQMa5+oH/oTRxuuy2F/mYdD8w7RyQ==",
  "azp": "04b07795-8ddb-461a-bbee-02f9e1bf7b46",
  "azpacr": "0",
  "name": "USER_FULL_NAME",
  "oid": "USER_OBJECT_ID",
  "preferred_username": "USER_EMAIL_ADDRESS",
  "rh": "0.ARcA9s6n4x-uDUih6CznvYX1DqJqF4JIEcZBhyJIsPIi-CwXAO0.",
  "roles": [
    "READ"
  ],
  "scp": "read",
  "sub": "SVfA-IJg9t-Z73Le-dad5EAOyq3QjwU1oS5csbOTbGI",
  "tid": "TENANT_ID",
  "uti": "vOTt0phu40yVrNAqqj8oAA",
  "ver": "2.0"
}

Using this token, the app reg is able to authenticate and authorize the user to execute some code/logic associated to it.

Now we want to use OAUTH Token Exchange Protocol so that our app registration can use the user's access token to request a new access token from Snowflake. I know that this is feasible with Oauth access tokens according to the following article:

https://www.scottbrady91.com/oauth/delegation-patterns-for-oauth-20

so basically one would do something similar to:

POST /token
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&client_id=OUR_APP_REG_CLIENT_ID
&client_secret=OUR_APP_REG_CLIENT_SECRET
&scope=api2
&subject_token=USER_ACCESS_TOKEN
&subject_token_type=urn:ietf:params:oauth:token-type:access_token

but I am not sure if it is possible to achieve it with Snowflake. And if the token exchange protocol can be used with Snowflake; can somebody show us the steps to configure it and what are the other parameters that we have to provide during the POST request? Thanks.

Using On Behalf Of documentation, I was able to achieve what looks like token exchange using this query:

curl.exe -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 

"grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&client_id=

{CLIENT_ID}&client_secret={CLIENT_SECRET}&assertion=

{user_access_token}&scope=https://graph.microsoft.com/.default&requested_tok
en_use=on_behalf_of" 

https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token

but when validating the token on jwt.io it says that the signature is invalid.

1

There are 1 answers

0
Sridevi On BEST ANSWER

Note that, you will get "Invalid signature" error if you trying to validate the access token generated with Microsoft Graph scopes.

I registered one Azure AD application and added permissions of 2 exposed APIs along with Microsoft Graph API:

enter image description here

Now, I generated one user access token that have similar token claims as you like this:

enter image description here

When I ran your curl request in Postman with Microsoft Graph scope, I got access token in response:

curl.exe -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 

"grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&client_id={CLIENT_ID}
&client_secret={CLIENT_SECRET}
&assertion={user_access_token}
&scope=https://graph.microsoft.com/.default
&requested_token_use=on_behalf_of" 

https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token

Response:

enter image description here

There is no need to validate tokens generated with Microsoft Graph API scopes. If you validate it, it will throw "Invalid Signature" error.

You can directly call Microsoft Graph API using above access token without any validation:

GET https://graph.microsoft.com/v1.0/me

Response:

enter image description here

Alternatively, you can generate the token for other APIs that are meant for application.

In my case, I ran below curl request by replacing scope with other exposed API value like this:

curl.exe -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 

"grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&client_id={CLIENT_ID}
&client_secret={CLIENT_SECRET}
&assertion={user_access_token}
&scope= api://<API_appId>/test.read
&requested_token_use=on_behalf_of" 

https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token

Response:

enter image description here

When I decoded this token in jwt.io, signature validated successfully as below:

enter image description here enter image description here