AADSTS5002710: Invalid JWT token: header is malformed - azure-active-directory

I am trying to implement the "On-Behalf-Of" flow between my Client (ReactJS), Express + Node.js server (API), and Microsoft Graph.
So far I have requested an accessToken from microsoft (Client), and have made a request to my API.
I have ran into the error "AADSTS5002710: Invalid JWT token: header is malformed." when I try to make an Axios post request from my API to https://login.microsoftonline.com/tenantID/oauth2/v2.0/token
Full Error:
{
error: 'invalid_request',
error_description: 'AADSTS5002710: Invalid JWT token: header is malformed.\r\n' +
'Trace ID: 068a382b-6f83-40f6-b1b1-7134223f4500\r\n' +
'Correlation ID: f46a2c03-84e8-46b3-b9d6-467174befa0b\r\n' +
'Timestamp: 2021-01-06 16:26:40Z',
error_codes: [ 5002710 ],
timestamp: '2021-01-06 16:26:40Z',
trace_id: '068a382b-6f83-40f6-b1b1-7134223f4500',
correlation_id: 'f46a2c03-84e8-46b3-b9d6-467174befa0b'
}
The body of my request is according to the tutorial "https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow".
I am constantly getting the error above as the result from microsoft online servers.
I have made the original (Client) request with my own custom scope api://54ee17f...cfe06/Access.Test

I follow the tutorial to use On-Behalf-Of flow in Postman. But it works well.
My steps here:
Add API permission of Web API B to Web API A
Request Web API A to get access token(assertion of next step) with auth code flow
GET
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize
?scope={like api://1108f6-xxxxxxx-9f622/test} openid
&redirect_uri={redirect_uri of Web API A}
&nonce=123
&client_id={client-id of Web API A}
&response_type=id_token token
Request Web API B to get the access token for Microsoft Graph API
POST
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&client_id={client_id of Web API B}
&client_secret={client_secret}
&assertion={access token from previous step}
&scope=https://graph.microsoft.com/user.read offline_access
&requested_token_use=on_behalf_of
Call Microsoft Graph API, like GET https://graph.microsoft.com/v1.0/users.
You could decode your access token(assertion) in https://jwt.io/, and check the HEADER.

Related

Quickbooks Online Integration with Mule

I am trying to integrate Quickbooks online with Mule. So far, I can complete the OAuth dance and retrieve the access token via the HTTP connector using the authorization code configuration.
The steps followed include:
COnfiguring the HTTP Request connector for OAuth dance which includes
Added authorization, callback URL, token URL, and client credentials
Configured payload for saving the access and refresh tokens
To trigger the oauth flow , I hit the authorize URL which in return gives me the realmId and authorization code
To make subsequent requests to the APIs using the extracted token I need the realm ID as well but I am not able to extract that.
The realmId is returned in the initial call along with the authorization code in the payload but when the process happens through mulesoft, there is no way to capture it and without the realmId I cannot make requests to the API.
Following is the XML configuration for HTTP:
<http:request-config name="HTTP_Request_configuration" doc:name="HTTP Request configuration" doc:id="36a1c561-9498-4dbf-b323-5c726b20cb6a" >
<http:request-connection protocol="HTTPS" host="sandbox-quickbooks.api.intuit.com" port="443">
<http:authentication >
<oauth:authorization-code-grant-type externalCallbackUrl="http://localhost:8082/callback" localAuthorizationUrl="https://localhost:8082/login" authorizationUrl="https://appcenter.intuit.com/connect/oauth2" clientId="ABNxxKq4xy1KWs1BteaIIAhY3NC7G5jg9YZg3h15Zf3waDdEja" clientSecret="5k5GxV3HIBtM7DRSQOqlBqtjWfg07tFNAFeW9EeJ" tokenUrl="https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer" localCallbackUrl="http://localhost:8082/callback" state="abc" scopes="com.intuit.quickbooks.accounting">
<oauth:custom-parameter-extractors >
</oauth:custom-parameter-extractors>
</oauth:authorization-code-grant-type>
</http:authentication>
</http:request-connection>
</http:request-config>
I need a way to extract the realmId and set it dynamically instead of hardcoding.
[This is the first request which gets the auth code and realmId before token exchange][2]
This is how realmId will be used in subsequent requests after token exchange
It is to be noted that I am not manually saving and reusing any variables, it is all happening as part of the Mulesoft HTTP connector oauth config
Reference guide for oauth in Mulesoft

Graph API Not able to access "https://graph.microsoft.com/v1.0/me/messages" endpoint

I am trying to access "https://graph.microsoft.com/v1.0/me/messages" API by JAVA SDK provided by Microsoft.
I am using the below code.
final AuthorizationCodeCredential authCodeCredential = new AuthorizationCodeCredentialBuilder()
.clientId("b****08f-*****-4d49-****-cba7d9a****c")
.clientSecret("8***7Q~GW0N******Y_N*****Zi******")
.authorizationCode("0.AVUAoIQSV...")
.redirectUrl("http://localhost/auth-responses")
.build();
Now it is giving me error like "The tenant for tenant guid '571284a0---****-a94eea6c6b3f' does not exist."
I tried the Same thing by postman, here I tried to get token by below end point.
"https://login.microsoftonline.com/common/oauth2/token"
after getting the token I am using it in "https://graph.microsoft.com/v1.0/me/messages" as Bearer Token. Still, I am getting the same issue.
But the token I am receiving in every case is not same as graph explorer Access Token
If I copy Graph Explorer Access Token and use it in postman then it gives me the desired result.
I am using a personal account for all of this process which ends with "#outlook.com".
I want to know why I am getting different access tokens than graph explorer access tokens and why that access token is not able to access the endpoints.
I have tested in my environment.
The access token generated from the Graph Explorer will be different from the access token generated from the Postman. This is because, the access token generated from graph explorer uses only the user credentials. The access token generated from postman uses client id and the client secret along with user credentials.
If the app registration supports Accounts in any organizational directory (Any Azure AD directory - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox), then only you can use personal account to generate the access token and use it to call the request for https://graph.microsoft.com/v1.0/me/messages only if the app registration have Microsoft Graph mail.read delegated permissions.
Paste the below URL in the browser. The code will be generated. Copy the code.
https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/authorize?
client_id=app-client-id
&response_type=code
&response_mode=query
&scope=mail.read
Make the below POST request in the postman to generate the access token :
POST https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token
Headers :
Content-Type: application/x-www-form-urlencoded
Body :
client_id: App Client ID
grant_type: authorization_code
scope: user.read%20mail.read
code: Code received in the first step
client_secret: Client Secret Generated in the App
Copy the Access token and make the below get request in the postman to read the messages :
GET https://graph.microsoft.com/v1.0/me/messages
Headers:
Authorization : Bearer access-token

Azure API Authentication and MSGraph

I am looking into a Node.JS API that has authentication through Azure AD, which all seems to be working ok, when i pass access token generated by logging into the web app, it authenticates and returns data.
However i now need the API to access MSGraph to retrieve Profile Photo etc. Ho do i pass authentication to MSGraph, i believe the accesstoken is different isnt it because they are different scopes. So how do i generate a new accesstoken for MSGrpah after i have logged into my app.
API endpoint just queries a db of users returning a JSON response, but i want to append the users profile image in base64Image to the response.
How do i do this
Thanks
You could use On-Behalf-Of flow, the OAuth 2.0 On-Behalf-Of flow (OBO) serves the use case where an application invokes a service/web API, which in turn needs to call another service/web API.
Sample:
POST /oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&client_id=2846f71b-a7a4-4987-bab3-760035b2f389
&client_secret=BYyVnAt56JpLwUcyo47XODd
&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InowMzl6ZHNGdWl6cEJmQlZLMVRuMjVRSFlPMCJ9.eyJhdWQiOiIyODQ2ZjcxYi1hN2E0LTQ5ODctYmFiMy03NjAwMzViMmYzODkiLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3L3YyLjAiLCJpYXQiOjE0OTM5MjA5MTYsIm5iZiI6MTQ5MzkyMDkxNiwiZXhwIjoxNDkzOTI0ODE2LCJhaW8iOiJBU1FBMi84REFBQUFnZm8vNk9CR0NaaFV2NjJ6MFFYSEZKR0VVYUIwRUlIV3NhcGducndMMnVrPSIsIm5hbWUiOiJOYXZ5YSBDYW51bWFsbGEiLCJvaWQiOiJkNWU5NzljNy0zZDJkLTQyYWYtOGYzMC03MjdkZDRjMmQzODMiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJuYWNhbnVtYUBtaWNyb3NvZnQuY29tIiwic3ViIjoiZ1Q5a1FMN2hXRUpUUGg1OWJlX1l5dVZNRDFOTEdiREJFWFRhbEQzU3FZYyIsInRpZCI6IjcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0NyIsInV0aSI6IjN5U3F4UHJweUVPd0ZsTWFFMU1PQUEiLCJ2ZXIiOiIyLjAifQ.TPPJSvpNCSCyUeIiKQoLMixN1-M-Y5U0QxtxVkpepjyoWNG0i49YFAJC6ADdCs5nJXr6f-ozIRuaiPzy29yRUOdSz_8KqG42luCyC1c951HyeDgqUJSz91Ku150D9kP5B9-2R-jgCerD_VVuxXUdkuPFEl3VEADC_1qkGBiIg0AyLLbz7DTMp5DvmbC09DhrQQiouHQGFSk2TPmksqHm3-b3RgeNM1rJmpLThis2ZWBEIPx662pjxL6NJDmV08cPVIcGX4KkFo54Z3rfwiYg4YssiUc4w-w3NJUBQhnzfTl4_Mtq2d7cVlul9uDzras091vFy32tWkrpa970UvdVfQ
&scope=https://graph.microsoft.com/user.read+offline_access
&requested_token_use=on_behalf_of

On behalf of token issue (AADSTS50013: Assertion contains an invalid signature)

I'm getting an error (mentioned below) when I'm trying to use Cortana Bot user token (which is a Graph token) to generate an "on-behalf-of" token to another consuming Web API application using ClientAssertionCertificate / ClientCredential targeted to another consuming Web API by passing its AppId as ResourceId and userAssertion generated by using Cortana Bot user token.
When checked our Bot AAD settings it is configured with other consuming Web API (API B) as valid application along with Graph application. Do we need to do any additional setting in AAD to get this on-behalf-of token?
AADSTS50013: Assertion contains an invalid signature.
[Reason - The provided signature value did not match the expected signature value.,
Thumbprint of key used by client: '9DB0B05B5D70DD7901FB151A5F029148B8CC1C64',
Found key 'Start=11/11/2018 00:00:00,
End=11/11/2020 00:00:00'
]
Trace ID: a440869f-b8f5-4d87-ba1a-6bd8dd7ba200
Correlation ID: 651e1fa8-2069-4489-a687-e68e5206e193
Timestamp: 2019-01-02 07:14:45Z
Following is the flow and Sample code how we are trying to get an on-behalf-of token for other consuming Web API (API B).
Flow Steps:
Cortana asks for user Sign-in
User Sign-in to Cortana
Cortana sends this user token (generated targeting to use https://graph.microsoft.com as Audience) to Microsoft Bot Framework API
Microsoft Bot Framework API validates and wants to consume this token for calling other Web API (which is called API B).
As this Cortana user token cannot be used directly, it needs to be generated as an on-behalf-of token to API B from Microsoft Bot Framework API.
Following is the code sample used to generate an on-behalf-of token from Microsoft Bot Framework API:
public async Task<string> GetOnBehalfOfTokenAsync(string authority, string resource, string scope = "", string token = "")
{
AuthenticationResult output;
var clientId = ConfigurationManager.AppSettings["API-B-ClientId"];
// Read certificate which can be used for getting token to API B using ClientAssertionCertificate
// GetCert() is used to get the Certificate based on Thumbprint configured in Web.config file.
var certificate = this.GetCert();
// 'authority' is https://login.microsoftonline.com/{tenant id}
var authContext = new AuthenticationContext(authority);
var cllientCertificateCredential = new ClientAssertionCertificate(clientId, certificate);
// 'token' is the user token which was received from Cortana.
var userAssertion = (!string.IsNullOrWhiteSpace(token)) ?
new UserAssertion(token, "urn:ietf:params:oauth:grant-type:jwt-bearer",
TokenHelper.ExtractUserInfoFromAuthToken(token, "upn")) : null;
try
{
// 'resource' is the Resource Id of API B
// if UserAssertion is null then get token with ClientAssertionCertificate else get
// on-behalf-of token using UserAssertion and ClientAssertionCertificate
if (userAssertion == null)
{
output = await authContext
.AcquireTokenAsync(resource, cllientCertificateCredential)
.ConfigureAwait(false);
}
else
{
output = await authContext
.AcquireTokenAsync(resource, cllientCertificateCredential, userAssertion)
.ConfigureAwait(false);
}
}
catch (Exception ex)
{
logger.log("Error acquiring the AAD authentication token", ex);
}
return output.AccessToken;
}
Getting an exception which was mentioned above at this step:
output = await authContext
.AcquireTokenAsync(resource, cllientCertificateCredential, userAssertion)
.ConfigureAwait(false);
My understanding is: first you get user token from your Cortana access ms graph API; and then you want to use the user token to generate the OBO token in Microsoft Bot Framework API; final, you want to use the OBO token to access API B from Microsoft Bot Framework API.
You want to get OBO token in Microsoft Bot Framework API, you should use the API id and the secret, for this, I have never tried this.
On my side, I use v1 endpoint, I create two API (API A and B) and my flow is:
First, my app requests token1 for API A;
Next, use the token1 to request OBO token2 for API B from API A;
Final, use the OBO token2 to request OBO token3 for aad graph API from API B.
For the OBO in v1 endpoint, please read link1.
For the OBO in v2 endpoint, please read link2.
We could able to resolve this issue by configuring our dependent custom API (API B) "user_impersonation" scope to Cortana channel configuration to our Bot. With this configuration change, we do not need to generate On-Behalf-Of token to API B from our Microsoft Bot application.
Thanks to all who has supported to provide solutions for this thread...

Google Endpoints - Invalid Token, allowed_client_id using token from OAuth2.0 Playground

So in my google cloud project I generated a Web Client ID, and follow the steps in
https://developers.google.com/adwords/api/docs/guides/oauth_playground
to get the authentication token.
In my #endpoints.api(allowed_client_ids=) I've put the client id inside it. Then in OAuth2 playground I sent a http request using the authentication token which I have acquired (e.g: Bearer ya29.bwL-f-hz-wcxFq_i-IlEQaJDiinwIP7ad7CaZoRkJRdGrsxxs4Wc9ZeNOgVlhD69zOQk) to the API.
But the problem is, it did not recognize the token, and said it is an invalid token. To compare with, I put endpoints.API_EXPLORER_CLIENT_ID together inside the allowed_clients_ids=, and when I tested it using API Explorer it just works. So am I doing something wrong?
You have specify your own client id and client secret. see this
screenshot

Resources