·Task
I want to include multiple scopes and allow access for those scopes with the same access token.
I have configured Azure Active Directory as per the attached image.
This condition was specified as follows, and an access token was issued with multiple scopes included.
curl -X POST -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8"
--data-urlencode "client_id=<client_id>"
--data-urlencode "client_secret=<client_secret>"
--data-urlencode "username=testuser#thoughtspot.com"
--data-urlencode "password=*****"
--data-urlencode "grant_type=password"
--data-urlencode "scope=https://<application_id>/session:role-any email openid profile"
https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/token
When I visualized the issued access token on the following site, only session:role-any was included in the access token.
https://jwt.ms/
By the way, when I included only the email openid profile in the scope, the email openid profile was included in the access token.
·question
How can I include multiple (session:role-any email openid profile) tokens above in the access token? Also, is this even possible?
·Reference site
https://docs.thoughtspot.com/cloud/latest/connections-snowflake-azure-ad-oauth
I may be wrong. If so, please let me know the correct way of thinking.
I tried to reproduce the same in my environment and got the results like below:
I agree with junnas, access token does not work with multiple scopes. So, you need to generate two access token one for API and one for Graph.
I generated the access token for two scopes like below:
https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
client_id:ClientID
client_secret:ClientSecret
username:admin#xxxx.onmicrosoft.com
password:*****
grant_type:password
scope:api://*****/app.test email openid profile
Note that: If you are passing two scopes, then it will consider only the first scope while generating the access token.
The decoded access token shows only the API scope like below:
The aud doesn't include Microsoft Graph scope and hence doesn't authorize Graph calls.
So, make sure to generate two access tokens separately, one for API scope and another for Graph scope.
I tried to generate the access token for the Microsoft Graph scope like below:
The decoded token contains Microsoft Graph scope and audience like below:
Related
I have an API that uses Azure AD to provide access to resources. It has one scope api://{client_id}/Api.Read and following API permissions:
User.Read.All,
User.Read.
When I receive an access token from the AD it has only one aud - {client_id} and when I try to access Microsoft graph (e.g. https://graph.microsoft.com/v1.0/me) I get "Access token validation failure. Invalid audience." response as expected.
My question is - Is it possible to access both graph API and my API using one token and how do it?
I am exchanging current token to a "proper" token using on-behalf-of call: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow
Basically, you just make the following call (copied from the link above):
POST /oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com/<YOUR_TENANT>
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&requested_token_use=on_behalf_of
&client_id=<YOUR_CLIENT_ID>
&client_secret=<YOUR_CLIENT_SECRET>
&assertion=<YOUR_CURRENT_TOKEN>
&scope=<YOUR_NEW_SCOPES>
The response contains the new token to access the resources that are requested in the scopes. My scenario is not exactly yours, but I think this should work for your case as well. You need to make this call server-side.
This assumes that the user has already consented that your app is okay to use <YOUR_NEW_SCOPES>, or otherwise this call will result in "interaction_required" or "invalid_grant" error (something like this, don't remember the exact error name) that basically means you need to raise UI prompt for the user to agree to the new scopes (how to do that is another question)
I was trying to Configure Microsoft Azure AD for External OAuth as per the Snowflake tutorial: https://docs.snowflake.com/en/user-guide/oauth-azure.html
The configuration steps went ahead without a hitch and I was able to use the final step: https://docs.snowflake.com/en/user-guide/oauth-azure.html#testing-procedure to obtain the access token from AAD.
However, when I tried to use the access token with Snowflake using a JDBC driver, I obtained the error: "net.snowflake.client.jdbc.SnowflakeSQLException: Invalid OAuth access token.
The Snowflake integration created is of the form:
create security integration ext_oauth_azure_ad
type = external_oauth
enabled = true
external_oauth_type = azure
external_oauth_issuer = '<issuer-url>'
external_oauth_jws_keys_url = '<keys-url>/discovery/v2.0/keys'
external_oauth_audience_list = ('https://<app-id-uri>')
external_oauth_token_user_mapping_claim = 'upn'
external_oauth_snowflake_user_mapping_attribute = 'login_name'
external_oauth_any_role_mode = 'ENABLE';
I tried playing around with this config by changing the external_oauth_token_user_mapping_claim to email since that was the attribute in the decoded JWT access token that matched the login_name but to no avail.
The scope provided in AD is the session:role-any which should be valid for any scope.
Not sure how to proceed post this.
Edit:
The command used to obtain access token is:
curl -X POST -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" --data-urlencode "client_id=<ad-client-id>" --data-urlencode "client_secret=<ad-client-secret>" --data-urlencode "username=<ad-user-email>" --data-urlencode "password=<my-password>" --data-urlencode "grant_type=password" --data-urlencode "scope=<scope-as-in-ad>" 'https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token'
Update:
Tried using the command:
select system$verify_external_oauth_token('<access_token>');
to validate if the token was valid in Snowflake and obtained the result:
Token Validation finished.{"Validation Result":"Failed","Failure Reason":"EXTERNAL_OAUTH_INVALID_SIGNATURE"}
This is strange because I have added the correct issuer based on the configuration step(entityId from the Federation metadata document
)
I've seen a couple questions on this asked on StackOverflow, but none have helped me. I can not get past the 'invalid_grant' error when trying to do an Authorize Code Grant on my 1 admin user in Docusign Sandbox environment.
I have 1 user, who is a DS Admin in the dashboard
I created a new App and obtained the Integrator Key/client_id and Secret Key
Using the guide, https://developers.docusign.com/esign-rest-api/guides/authentication/oauth2-code-grant
I have successfully called and granted permission to the user with
https://account-d.docusign.com/oauth/auth?
response_type=code&scope=signature%20impersonation&client_id=INTEGRATOR KEY&redirect_uri=https://www.docusign.com
and obtained the code returned
I have taken the Integrator Key and secret key, in form INTEGRATOR_KEY:SECRET_KEY and base64 encoded it.
I have tried using Postman and just straight up cURL call to obtain the access token. I have done this numerous times, with numerous new Apps created in Docusign Sandbox. They all return invalid_grant error.
cURL call
curl --header "Authorization: Basic BASE64ENCODING(INTEGRATOR_KEY:SECRET_KEY)" --data "grant_type=authorization_code&code=CODE_RETURNED_FROM_PERMISSION_GRANT" --request POST https://account-d.docusign.com/oauth/token
It's possible that DocuSign isn't able to correctly interpret your request because you're missing a Content-Type header.
Try adding Content-Type: application/x-www-form-urlencoded
The Authorization Code you receive back from DocuSign is only good for a couple of minutes. If you try to use it after that time then you'll receive the invalid grant error.
Also, if you are doing the Authorization Code Grant flow then you should not be requesting the impersonation scope. -- It is only for the JWT flow.
I am making OAuth 2.0 auth code authentication flow with multi-tenant application.
Here is my authorize url:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=my_id&prompt=consent&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauthorize&response_type=code&scope=openid+offline_access&state=17
It goes fine and I receive auth_code. Then I make request with this auth_code to token_url and receive a lot of information, like:
token_type
scope
id_token
access_token
refresh_token
expires_at
ext_expires_in
Seems fine to me, but when I make request on API with access_token like:
https://management.azure.com/subscriptions/my_sub_id/locations?api-version=2016-06-01
with headers:
Content-Type:
- application/json
Authorization:
- Bearer EwBQA8l6BAAURSN/FHlDW5xN74t6GzbtsBBeBUYAAV1IHgHb4dOWblzfd/YsSuFicAMDYbua17QivnAT9/pIaeKAg3uKsK5VGqWLzjMOUQrCpd7R1RAM6RkzI0u8e4rpO7DISG7qLso5H5+U1jb+38/j1urcwlXMMxhy83ZXmdpkLXpZV+vcOV...
It responds with 401 error
body:
encoding: UTF-8
string: '{"error":{"code":"InvalidAuthenticationToken","message":"The access token is invalid."}}'
To be honest I think something wrong with my access_token. It seems not like JWT for me. Documentation says it looks like:
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCEV1Q..."
But my access_token looks like:
"access_token": "EwBYA8l6BAAURSN/FHlDW5xN74t6GzbtsBBeBUYAAZDe7JE/MPLoAi+Fr+1Xxq5eBe5N9l8Q+c4QjkY5PGEzRnBpPe7+v6h+PLdh1cceBQx+/JsB2QCrYSCt7x/zGsQAhwoY/"
Is it fine?
Here is my permissions for application:
Permissions
The main issue you have here is that you have only asked for an access token for the scopes openid offline_access. The resulting access token will be for Microsoft Graph (https://graph.microsoft.com), not for the Azure REST API (https://management.azure.com).
To indicate you would like a token for a given API, the scope parameter in your authorization request should include the delegated permission you would like the app to have for the API. In the case of Azure REST API, there's only one delegated permission: user_impersonation. The identifier URI for the Azure REST API is https://management.azure.com, so the scope value you want to use is:
openid offline_access https://management.azure.com/user_impersonation
Two more important notes:
As you've discovered, you will not always be issued an access token as a JWT which you can decode peek at. The format of the access token is an agreement between the service which issued the token (Azure AD or Microsoft Accounts, in this case), and the service for which the token was issued (Microsoft Graph, in this example).
You should not always include prompt=consent. prompt=consent should only be used if you have already tried signing in the user without the user needs to be re-prompted for consent for a new permission.
If you simply include the required scopes in the scopes parameter, the Microsoft Identity platform will take care of figuring out if it needs to prompt for consent or not. If you always include prompt=consent, you will find that many organizations will be blocked from accessing your app, because they've disabled the ability for users to grant consent themselves (and this parameter specifically states that you require the user to be prompted again).
In this article https://learn.microsoft.com/en-us/rest/api/resources/tenants/list I can get all the Tenants in my account. Now I want to get all the Organization in devops/vsts in each tenant or directory. Currently Im using this article https://learn.microsoft.com/en-us/rest/api/azure/devops/account/accounts/list?view=azure-devops-rest-5.0 and the token I get in the tenants is not working in getting all the organizations. Is theres a way to list all the organization in each tenant in my account? Thanks!
You can get the list via the below azure API call:
GET https://management.azure.com/tenants?api-version=2016-06-01
And for this API call to returns results correctly you need to gain access token and put it in the request header like that:
Authorization: Bearer access_token
And as shown in the documentation, you can gain the access_token from the below Identity end point as it's Implicit flow token:
Authorization URL: https://login.microsoftonline.com/common/oauth2/authorize
So the steps will be:
1- First make a call to:
https://login.microsoftonline.com/common/oauth2/authorize
With the appropriate parameters like the client_id and etc.
2- Gain access_token from the first step response.
3- Use this access_token to retrieve your talents list:
GET https://management.azure.com/tenants?api-version=2016-06-01
Authorization: Bearer access_token
And you can test this via postman or any curl based tool for verifying.