How to debug Bearer error="invalid_token" - azure

We are building an application with a SPA front end and an API backend.
We are using the MSAL authentication library, the frontend and backend are registered as applications in Azure AD.
We get a HTTP 401 error.
To try and debug the problem, we have taken the token from the SPA application, and put it in jwt.io, it looks fine. We have also tried sending the request from Postman, with the bearer token. Still same problem.
Is there a way to find out in what way the token is invalid?

A simple check to get some clue why the token is not accpted, is to set this flag to true in AddJwtBearer:
.AddJwtBearer(opt =>
{
opt.IncludeErrorDetails = true;
...
Doing so, will include why it was rejected in the WWW-Authenticate response header:
HTTP/1.1 401 Unauthorized
Date: Sun, 02 Aug 2020 11:19:06 GMT
WWW-Authenticate: Bearer error="invalid_token", error_description="The signature is invalid"
The second step is to check the logs from the AddJwtBearer handler.

Related

instagram basic display API get request not working?

I'm trying to do a basic get request based on the short-lived token recieved from a previous request to instagram. I know the short-lived-access-token is valid.
The account i'm testing with is a test user and the app is in development mode at facebooks end. Furthermore, the app review is currently pending but i dont think that's the issue since the account i'm testing is a test account and again - the login feature is set to development mode.
When i do the request based on the documentation:
https://developers.facebook.com/docs/instagram-basic-display-api/guides/long-lived-access-tokens/
i get the following response with status code 400:
Sorry, this content isn't available right now
based on this request format:
https://graph.instagram.com/access_token
?grant_type=ig_exchange_token
&client_secret={instagram-app-secret}
&access_token={short-lived-access-token}
Here is the full response:
HTTP/1.1 400 Bad Request
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Vary: Origin
Content-Type: application/json; charset=UTF-8
WWW-Authenticate: OAuth "Facebook Platform" "invalid_token" "Invalid OAuth access token."
Access-Control-Allow-Origin: *
Strict-Transport-Security: max-age=15552000
Pragma: no-cache
Cache-Control: no-store
Expires: Sat, 01 Jan 2000 00:00:00 GMT
x-fb-request-id: Al1knRjoI2Qw1XEVlh4b3Ku
x-fb-trace-id: GasPh1zh4bl
x-fb-rev: 1004118369
X-FB-Debug: 73PsZ2YPe6C2obr8nIdox2r2YOtNoVsuva4y2rRLvd70l06oV8kfdjOzLRhPvLDvpsmc1+5gP42Hc4Pi4AUHLw==
Date: Fri, 16 Jul 2021 04:19:09 GMT
X-FB-TRIP-ID: 1512268381
Connection: keep-alive
Content-Length: 45
Sorry, this content isn't available right now
Had this problem too, but fortunately stumbled upon the solution. What was missing for me that I wasn't requesting the instagram_graph_user_profile permission when authorizing the user.
This permission is listed as being required for the access_token endpoint, and for me made the difference between getting "Sorry, this content isn't available" and a long-lived access token.
i.e.
https://api.instagram.com/oauth/authorize
?client_id={app-id}
&redirect_uri={redirect-uri}
&scope=user_profile,user_media,instagram_graph_user_profile
&response_type=code
Exchanging access_token can be tricky sometimes. Let me walk you through another way to get the access_token.
First, we make a GET call to get the auth code. Scope depends on the permission given to the Test app.
https://www.facebook.com/v11.0/dialog/oauth?client_id={app-id}&redirect_uri={your_redirect-uri}&auth_type={rerequest}scope={email}
Now, Your Test App needs login access which further gets redirected to the URL mentioned in the test app. The URL consists of code. Copy the code and don't include #= part.
To get the access token now we make another GET request.
https://graph.facebook.com/v11.0/oauth/access_token?client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URL}&client_secret=${CLIENT_SECRET}&code=${oauth_code}
This gives you access_token. Copy the access_token and paste that in Access Token Debugger link. You will find out that this comes with no expiry date.

What value to give for "scope" option when I want to access an Azure function API that is protected with Azure AD in Postman

I am working on an Azure Function API that is protected by Azure AD, it's working fine when I request it with browser once I logged in with a valid account, but when I tried with postman it still shows unauthorized access,
I have got an access token to send with the request, but for the scope property I have given is this value, https://graph.microsoft.com/.default which I think might be the problem. But not sure what I am doing wrong and what to put in the scope field in the get new access tokenoption in postman to authenticate to my API.
HTTP Request Postman Making
GET /api/events/active HTTP/1.1
Host: moya-backend-ascentic.azurewebsites.net
Authorization: Bearer ****IHqMgweN86fDnyL4jvz9P6ZllpjjD9t***
User-Agent: PostmanRuntime/7.13.0
Accept: */*
Cache-Control: no-cache
Postman-Token: 655e0672-4928-409e-a709-841a92ee6f14,22cbf978-f196-4099-ae10-d162d3068507
Host: moya-backend-ascentic.azurewebsites.net
accept-encoding: gzip, deflate
Connection: keep-alive
cache-control: no-cache
The scope should be: your-api-client-id/.default.
Replace your-api-client-id with the client id/application id for your API app in Azure AD.
Now since browser-based login seems to be working, you may have setup the wrong kind of authentication on the API.
If the token still doesn't work, you'll need to setup JWT authentication on the app instead of browser/cookie based.
If you are using v2.0 endpoint, the scope should be {your_client_id}/.default. Just like #juunas said.
If you are using v1.0 endpoint, you only need resource parameter. The resource should be {your_client_id}
Note: If you are using the 'get new access token' function in postman, the Access Token URL should be https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token

Azure OAuth to function app issues

I have a very basic function app that takes a GET and returns some static text. Eventually I would like it to write a POST body to a queue but to keep it simple the function just returns text. If I keep auth off, I can load the url and get a response in my browser or postman. If I enable aad auth within the function app and create a simple app reg then goto the site in my browser I get prompted for auth and I can login interactively; no worries so far.
I would like to access the function using a secret key for application usage with no interactive login, so within the app reg I go to Keys and generate one. This is where my problems start. If I use postman and configure oauth using my app id and key I can get a token, I have verified this also by doing a POST to https://login.microsoftonline.com//oauth2/token directly and noting the bearer token reply. However when I try an access my function app using the bearer token (either by manually adding an Authorization header or letting postman add it from the oauth 2.0 form) I am always denied with a 401 stating 'You do not have permission to view this directory or page.' when I do a GET to my function app. Can someone point me in the right direction? Thanks in advance.
Example reply from login url
{
"token_type": "Bearer",
"expires_in": "3599",
"ext_expires_in": "0",
"expires_on": "1525312644",
"not_before": "1525308744",
"resource": "https://<siteaddress>.azurewebsites.net/",
"access_token": "eyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..etc..."
}
Response from get against function app with token
GET /api/t2 HTTP/1.1
> Host: <sitename>.azurewebsites.net
> Authorization: Bearer eyxxxxxxxxxxxxxxxxxxxxxxxxxxxx.....etc....
> Accept: */*
< HTTP/1.1 401 Unauthorized
< Content-Length: 58
< Content-Type: text/html
< WWW-Authenticate: Bearer realm="<sitename>.azurewebsites.net" authorization_uri="https://login.windows.net/<tenantid>/oauth2/authorize" resource_id="<app reg id>"
< X-Powered-By: ASP.NET
< Date: Thu, 03 May 2018 01:12:43 GMT
I believe you're mixing Azure AD integration with function keys (API key authorization).
The latter is a self-contained authorization mechanism and works by appending
?code=<func-key-from-portal>
to the function URL, or by passing a
x-functions-key: <func-key-from-portal>
header with every request to the function. No OAuth is involved when using function keys.
Example:
GET /api/get-issues HTTP/1.1
Host: {funcapp}.azurewebsites.net
User-Agent: ajax-library-of-the-day
x-functions-key: rkW0PqT.....zcUBQ==
or
GET /api/get-issues?code=rkW0PqT.....zcUBQ== HTTP/1.1
Host: {funcapp}.azurewebsites.net
User-Agent: ajax-library-of-the-day

OAuth Authorization code grant - Docusign - Error response while making calls to generate access and refresh tokens from auth code

I am trying to use authorization code grant flow to authorize to my app Documentation here. I am building an app to support auto user provisoning to Docusign using REST APIs. i have created a developer account and have obtained Integrator Key and the secret key.
I made following request to obtain the auth code :
account-d.docusign.com/oauth/auth?response_type=code&scope=signature&client_id=<MY_CLIENT_ID>&redirect_uri=<localhost> and the response on the browser with the code.
I am using curl command to generate tokens using the following request :
curl -iX POST account-d.docusign.com/oauth/token -H "Authorization: Basic base64_representation_of_clientId:clientSecret" -d 'grant_type=authorization_code&code=<Auth Code recieved in the previous step>'
However I am getting this response :
HTTP/1.0 301 Moved Permanently
Location: account-d.docusign.com/oauth/token
Server: BigIP
Connection: Keep-Alive
Content-Length: 0
What can be the possible reason for this error response?
Perhaps try adding the protocol (https://) to the request URI?
curl -iX POST https://account-d.docusign.com/oauth/token...

Clarification on REST APIs around user management in an account

I recently created a docusign developer account and integrator key and was playing with docusign REST APIs and had some questions
I can retrieve full list of users under my account by using following REST call.
https://demo.docusign.net/restapi/v2/accounts/<accountid>/users?additional_info=true
However if I try and retrieve a specific user (other than the one I am passing in my X-Docusign-authentication) header i get http 400 error with message that the "Invalid UserId. UserId specified in request uri does not match authenticated user"
https://demo.docusign.net/restapi/v2/accounts/<accountid>/users/0d51a699-b17a-48b7-95b6-1e9e9806deb6
In both cases i am sending the following header.
X-DocuSign-Authentication: <DocuSignCredentials><Username>{0}</Username><Password>{1}</Password><IntegratorKey>{2}</IntegratorKey></DocuSignCredentials>
I am surprised that while I can read all users fine, I cannot just read one specific user. Surely it doesn't seem like this is security thing since I can read the user via one API but not the other using the same auth token.
What am i missing?
I guess I can go the route of SOBO (Send on behalf of functionality), but I wanted to confirm if above behavior is expected.
Update#1
: I went the SOBO approach and now i get a different error (USER_NOT_ACCOUNT_ADMIN) as shown below
GET /restapi/v2/accounts/{accountid}/users/0fe29a55-5564-42a9-b09d-cbe699db13dd HTTP/1.1
Authorization: bearer {token for authenticating user}
X-DocuSign-Act-As-User: {operating user's email}
Accept: application/json
Host: demo.docusign.net
Connection: Keep-Alive
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
Content-Length: 100
Content-Type: application/json; charset=utf-8
Date: Thu, 17 Oct 2013 21:18:32 GMT
Strict-Transport-Security: max-age=7776000; includeSubDomains
{
"errorCode": "USER_NOT_ACCOUNT_ADMIN",
"message": "User is not an account administrator."
}
I also tried the second SOBO approach of getting a oauth token for the operating user but got back http 400 error with below message
{
"error": "invalid_request",
"error_description": "An OAuth2 error occurred."
}
So while i can get an oauth token for the autheitcating user, i am not able obtain oauth token for the operating user or act on their behalf.
I have made sure that authenticating user is "Account Administrator" and has both "apiAccountWideAccess" and "•allowSendOnBehalfOf" set to true. The only thing set to "false" is "canSendAPIRequests". My account id in sandbox environment is "601565a7-e9c7-463b-9d7c-622aed905ea8" Any ideas?
Update#2
Instead of generating oauth tokens on behalf of both authenticating user and operating user, i tried passing below header and i can finally get another user's profile and update another user's profile.
X-DocuSign-Authentication: <DocuSignCredentials><SendOnBehalfOf>{operating userid}</SendOnBehalfOf><Username>{authenticating userid}</Username><Password>{authenticating user's password}</Password><IntegratorKey>{developer's integrator key}</IntegratorKey></DocuSignCredentials>
Great!
So here is status of what works and what doesn't.
Works with no SOBO header anywhere
GET /restapi/v2/accounts/357938/users?additional_info=true // Read all users
GET /restapi/v2/accounts/357938/users?email=someshchandraatwork#gmail.com&additional_info=true // Read single user by email
POST /restapi/v2/accounts/357938/users // Add users
DELETE /restapi/v2/accounts/357938/users // Close users
*Works with SOBO in X-DocuSign-Authentication header
PUT /restapi/v2/accounts/357938/users/74a021e1-3090-4843-b9ab-cceb7cd119f4/profile // Update user's profile
GET /restapi/v2/accounts/357938/users/74a021e1-3090-4843-b9ab-cceb7cd119f4/profile // Read user's profile
Still doesn't work with or without SOBO**
GET /restapi/v2/accounts/357938/users/74a021e1-3090-4843-b9ab-cceb7cd119f4/settings
GET /restapi/v2/accounts/357938/users/74a021e1-3090-4843-b9ab-cceb7cd119f4
In both not working cases i get following error
Without SOBO i get error that userid doesn't match autheitcating user.
With SOBO i get error than user is not an account admin
I would very much appreciate any help in resolving the not working cases. I can provide more detaisl as needed.
Secondly I want to implement a scenario where I can deactivate a user in an account so they can no longer log into docusign. And subsequently I would like to enable that user back again with same permission that they had before they were disabled.
I see that user has a "userStatus" field and was wondering if I can use that to de-activate the user and then re-activate if needed. If this is supported then what value would correspond to deactivating the user?
The other thing I note is that on DELETE a user, the user is only soft-deleted since I can still query the user with the status "CLOSED". That would solve my "deactivate" problem. However I was not sure if there is a way to reactivate them back again after the user has been "closed"?
I believe this might be an account administration issue. I'm not sure why but I looked at your account settings from DocuSign's side and I saw the "Send on Behalf of" was not checked on your account- which is weird since it seems you have access to the setting in your Console -> Preferences settings.
But in either case I'm wondering if the setting I just enabled on your account has solved your issue, as it might have.
I'm also not sure about the user info portion of your question, let me see if I can come up with anything for that and I'll edit my answer once I do.
In reply to Erign's post above.
Anyone who is an account admin should be able to modify/add/delete users in an account. I'm not sure if your SOBO steps are correct though, can you confirm that you are following THESE STEPS exactly? If so, at which step do you run into issues or get an error?– Ergin5 mins ago
Yes i am following those steps. I am able to generate oauth token for the autheitcating user , but get an error when doing the same for the operating user. Below are my request and responses.
1. REQUEST FOR AUTH TOKEN FOR AUTHENTICATING USER
POST /restapi/v2/oauth2/token HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Host: demo.docusign.net
Content-Length: 139
Expect: 100-continue
Connection: Keep-Alive
grant_type=password&client_id={integratorykey}&username={authenticating user's email}&password={authenticating user's password}&scope=api
RESPONSE
HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Length: 100
Content-Type: application/json; charset=utf-8
Date: Thu, 17 Oct 2013 22:57:26 GMT
Strict-Transport-Security: max-age=7776000; includeSubDomains
{
"access_token": "{authenticating user's token}",
"token_type": "bearer",
"scope": "api"
}
2. REQUEST FOR AUTH TOKEN FOR OPERATING USER
POST /restapi/v2/oauth2/token HTTP/1.1
Authorization: bearer {authenticating user's token}
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Host: demo.docusign.net
Content-Length: 137
Expect: 100-continue
grant_type=password&client_id={integratorykey}&username={operating user's id}&password={empty}&scope=api
RESPONSE
HTTP/1.1 400 Bad Request
Cache-Control: no-cache
Content-Length: 87
Content-Type: application/json; charset=utf-8
Date: Thu, 17 Oct 2013 22:57:29 GMT
Strict-Transport-Security: max-age=7776000; includeSubDomains
{
"error": "invalid_request",
"error_description": "An OAuth2 error occurred."
}

Resources