How to obtain access token from azure - azure

I am stuck with the authentication to use the REST API for getting subscription billing information from Resource Usage API
I would like to get help with how to obtain token for non interactive clients. I chose to use the REST API since azure client seems to not support Resource Usage API.
As the Authorization code grant (interactive clients) describes , I have called the request with my subscription id but token is not returned properly.
[root#visual src]# curl -XPOST https://login.microsoftonline.com/xxxxx/oauth2/token -d ""
{"error":"invalid_request","error_description":"AADSTS90014: The request body must contain the following parameter: 'grant_type'.\r\nTrace ID: 32981285-a021-45c3-8d2f-62db49d2c2f1\r\nCorrelation ID: d88849dd-20f9-462e-9ce9-66b6fde0170e\r\nTimestamp: 2017-03-04 04:06:44Z","error_codes":[90014],"timestamp":"2017-03-04 04:06:44Z","trace_id":"32981285-a021-45c3-8d2f-62db49d2c2f1","correlation_id":"d88849dd-20f9-462e-9ce9-66b6fde0170e"}[root#visual src]#
How can I obtain the token?

A token will not be returned if you don't supply some credentials :)
If you want to do a non-interactive request with client credentials for example, your request must contain (in URL-encoded form format):
grant_type=client_credentials
client_id=your-app-client-id
client_secret=your-app-client-secret
resource=resource-uri-for-api-you-want-the-token-for
The resource URI could be for example https://graph.windows.net/ for the Azure AD Graph API.
You can also get tokens with the password grant if you wish to use a username and password. In that case, you must send:
client_id, client_secret and resource as above
grant_type=password
username=your-username
password=your-password

Related

Docusign UserInfo endpoint returns 401 Unauthorized when access token is provided

I am integrating my API backend with DocuSign in order to send and retrieve envelopes. I am using the JWT Grant flow.
Authentication options
In the DocuSign development environment, I am able to retrieve an access token using the JWT flow and the Docusign C# SKD.
I need to then call the oauth/userinfo endpoint in order to retrieve the base_uri field to use for making calls to Docusign.
When I make a GET request to https://account-d.docusign.com/oauth/userinfo, including the access token in the Authorization header as Bearer <access_token>, I receive a 401 Unauthorized response, and this message in the body:
{
"error": "internal_server_error",
"reference_id": "<some GUID>"
}
I have tried this using curl, Postman and the C# SDK and all give the same result.
Curl syntax:
curl --header "Authorization: Bearer <access token>" https://account-d.docusign.com/oauth/userinfo
user-info endpoint documentation
JWT flow (step 4)
As far as I can see, I appear to be calling the API according to the documentation and I have set up the account with an RSA key pair which is required for system integrations (created within the Docusign admin portal).
Can anyone think of a reason this could be happening?
Since you're using the C# SDK as you mentioned, you can call this endpoint using the same SDK if you have a valid token.
https://developers.docusign.com/docs/esign-rest-api/sdk-tools/c-sharp/reference/
public OAuth.UserInfo GetUserInfo(string accessToken);
You can confirm that your token is valid by trying to use it for other API calls.
A token from the developer account should be useful to make this call in the developer account only. If you need this for production (typically reason to need the base_uri) then you have to call it with account.docusign.com not account-d.docusign.com.
I have now been able to get the base_uri from UserInfo endpoint using the RequestJWTUserToken method in the C# SDK. Using this token allows me to hit the REST API endpoint.
Both methods appear to hit the same oauth/token endpoint and use the same grant type, only RequestJWTUserToken includes the "sub" claim for the userId.

SharePoint Rest API how to get Access Token?

Just starting to work with SharePoint and Microsoft authentication and trying to get a SharePoint List into a JavaScript App. From Microsoft documentation, I need to use the following:
GET https://{site_url}/_api/web/lists/GetByTitle('List Title')
Authorization: "Bearer " + accessToken
Accept: "application/json;odata=verbose"
Have searched everywhere to find an definitive answer to how to obtain this accessToken. All the documentation I can find from Microsoft seem to be out of date. Does anyone know the current method to obtain an accessToken?
To call SharePoint specific APIs you need to get a SPO specific access token. You can "swap" an regular MS Graph refresh token for an SPO specific token by doing the following:
Get a delegated auth token from graph as you normally would
(https://learn.microsoft.com/en-us/graph/auth-v2-user)
Use the refresh_token you got and exchange it for an SPO access token by calling the auth endpoint again:
POST https://login.microsoftonline.com/{{tenantName}}/oauth2/v2.0/token
With the following form data:
client_id=<APP ID>
client_secret=<APP SECRET>
refresh_token=<REFRESH TOKEN FROM ABOVE>
grant_type=refresh_token
scope=https://<YOUR TENANT NAME>.sharepoint.com/Sites.Read.All
Take the access token and call the SPO API
You must ensure your app is registered with the correct permissions. In the case above the app must have Sites.Read.All for example.
You could refer to this article to get access token:
https://global-sharepoint.com/sharepoint-online/in-4-steps-access-sharepoint-online-data-using-postman-tool/
Post https://accounts.accesscontrol.windows.net/<Tenant ID>/tokens/OAuth/2
Body:
grant_type client_credentials
client_id <Client ID>
client_secret <Client Secret>
resource 00000003-0000-0ff1-ce00-000000000000/<tenant>.sharepoint.com#<Tenant ID>
My test result:
There is not much documentation for SP API, but it still works. You may follow documentation to get token for Graph API by whatever type of authentication is suitable for your scenario, but instead of passing scopes for Graph API (which is "https://graph.microsoft.com/.default"), you should pass scopes for Sharepoint API which is "https://{your tenant name}.sharepoint.com/.default"
".default" will provide you the access with all permissions which was assigned in Azure AD - so also make sure, that Azure admin has granted you required API permissions for SharePoint API.
This will also work for MSAL.

Authenticate for Azure REST API without login

I have a backend process that doesn't directly interact with the user. I want to access reservations associated with my Azure account but I'm having trouble with the authentication step. I was following the guide here and I managed to get the authentication request to work by calling
https://login.microsoftonline.com/{tenant-ID}/oauth2/token
as a POST with the following x-www-form-urlencoded body:
grant_type=client_credentials&
client_id={client-ID}&
client_secret={client-Secret}&
resource=http://myapp42
However, when I attempt to call:
https://management.azure.com/providers/Microsoft.Capacity/reservationOrders/{order-ID}/reservations/{reservation-ID}?api-version=2019-04-01
with the bearer token I received during the authentication step, I get the following error message:
The access token has been obtained for wrong audience or resource 'http://myapp42'. It should exactly match with one of the allowed audiences 'https://management.core.windows.net/', 'https://management.core.windows.net', 'https://management.azure.com/', 'https://management.azure.com'
However, if I modify the resource on the request to be one of these, http://management.core.windows.net/ for instance, the authentication then fails with:
AADSTS500011: The resource principal named https%3A%2F%2Fmanagement.core.windows.net%2F was not found in the tenant named {tenant-ID}. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.\r\nTrace ID: b54cedea-3804-41cf-bd27-fcf0ed1c4700\r\nCorrelation ID: 2371d375-6c89-4f05-83c9-c4629b3340a8\r\nTimestamp: 2020-02-05 01:59:57Z
How do I authenticate so that I can then get my reservations without having to login?
Update:
The service principal has both the Owner and Contributor roles assigned.
Update 2:
Thanks to #Jim Xu, I was realized that I needed to refrain from url-encoding the URL. That allowed me to get the access token with a value of https://management.azure.com/ for the resource field. However, at this point, when I attempt to call the REST API with the resulting bearer token, I get the following error:
The client '{Object-ID}' with object id '{Object-ID}' does not have authorization to perform action 'Microsoft.Capacity/reservationOrders/reservations/read' over scope '/providers/Microsoft.Capacity/reservationOrders/{order-ID}/reservations/{reservation-ID}' or the scope is invalid. If access was recently granted, please refresh your credentials
Note: The object ID returned by this error is the one associated with the service principal.
Update 3:
I checked the reservation and it seems that the principal does not have a role in that reservation's access control. However, I also cannot assign the principal a role because it does not show when I search for principals during the role-assigning process.
If you want to call Azure Rest API to get the information of reservation Orders, you need to assign Owner\Contributor for the service principal.(the action needs Microsoft.Capacity/reservationOrders/read permission).
The steps are as below
Get access token
POST : https://login.microsoftonline.com/{tenant-ID}/oauth2/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&
client_id={client-ID}&
client_secret={client-Secret}&
resource=https://management.azure.com/ or https://management.core.windows.net
Call the api
GET : https://management.azure.com/providers/Microsoft.Capacity/reservationOrders/{order-ID}/reservations/{reservation-ID}?api-version=2019-04-01
Authorization: Bearer <token>
For more details, please refer to the issue and the issue
update
If you have assigned role but you still cannot get access token, please try to encode your url.

Wrong access_token from AAD with OAuth2 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).

Azure Get All Organzations in multi tenants

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.

Resources