Token retrieval error after changing password - msal

We are using Azure AD B2C Custom policies with Microsoft Azure Active Directory to authenticate users. We implemented the password change policy as given in the example below.
https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack/tree/main/scenarios/password-change
We created a link the user can visit and change his password. Once the password is changed, the user is redirected to the application again.
However, in some cases, we get the following error when the user is redirected to the application after changing the password.
{
"error": "invalid_grant",
"error_description": "AADB2C90088: The provided grant has not been issued for this endpoint. Actual Value : B2C_1A_Dev_SignupSignin and Expected Value : B2C_1A_Dev_PasswordChange\r\nCorrelation ID: b3a2fdd5-df58-4aa1-8eca-d91503ebb75a\r\nTimestamp: 2022-08-31 12:23:48Z\r\n"
}
This error does not happen to all users. But for some users, it happens always.
We use MSAL Angular library with the following versions.
azure/msal-angular": "^2.1.1"
azure/msal-browser": "^2.22.0"
We appreciate any help to resolve this issue.

Related

Google API 'Purchases.products: get' return 401 ERROR all of a sudden

Purchases.products: get had been working well till 2 weeks ago. However, it starts returning Error suddenly. (I didn't change any options)
It can still refresh token through POST request to https://accounts.google.com/o/oauth2/token with (grant_type, client_id, client_secret, refresh_token) but with the access-token returned, 403 Error happen like the below.
{
"error": {
"errors": [
{
"domain": "androidpublisher",
"reason": "permissionDenied",
"message": "The current user has insufficient permissions to perform the requested operation."
}
],
"code": 401,
"message": "The current user has insufficient permissions to perform the requested operation."
}
}
This is google dashboard representing error rate for Purchases.products: get
I found the question but it is still not working.
---------- EDIT ----------
I want to describe more detail. I don't know if it is right way because I am actually just fixing Legacy system someone did.
The process above(refreshing token and requesting purchase info) is done in server-side. It is for server-side to verify if the purchase-information APP send is correct.
When APP send purchase-information, server-side just call HTTP request(POST and GET) with pre-defined attributes(client_id, client_secret, grant_type).
It means there is no login process anywhere.
In addition, the client_id and client_secret I use seemed created in google-developer-console by create-credentials in below image but not when registering APP.
---------- Edit ----------
I tried to recreate client_id with an owner account. the screenshot is from google developer console->IAM&Admin->IAM
However, it is still the same error.
"The current user has insufficient permissions to perform the requested operation."
The user you have currently authenticated with no longer has access to the data you are trying to access. Either give the user access again or login with a user that does have access.
ClientId
When you wish to work with a Google API you must register your application. When you do so google gives you a client id. This identities your application to google when ever it runs.
Accessing User data
To access private user data you must have permission of the person who owns the data to access it. Your application runs (Denoted by the Client id) the user is prompted to login to google and grant your application consent to access their data.
If the user looses access to the data that they have granted your application access to your application will loose its access.

How to debug Authentication configuration?

We are experiencing problems with Authentication of Service Accounts for domain-wide delegation.
The main problem is it's hard to investigate and debug the auth configuration so
we would like to ask for some tips how to debug the configuration.
Or maybe we are missing some configuration options and you can point us to them.
Our process is:
Create SA(=Service Account) with enabled domain-wide delegation.
Authenticate SA in GSuite admin console(https://support.google.com/a/answer/162106?hl=en).
use client_id from the credentials file. (now email)
scopes are comma-separated without spaces between.
Ensure the "Security > API Reference > API Reference -> 'Enable API Access'" is checked.
For some GSuite domains this is working configuration, but we got some domains where this configuration results in:
google.auth.exceptions.RefreshError: ('unauthorized_client: Client is unauthorized to retrieve access tokens using this method.', '{\n "error": "unauthorized_client",\n "error_description": "Client is unauthorized to retrieve access tokens using this method."\n}')
In our understanding, this is the error saying the client_id and scopes were not added to the "Manage API client access" page. (=List of authenticated clients)
We really ensured that the GSuite domain we are requesting has the proper client_id and scopes added in the list of authenticated clients + has the 'Enabled API Access'.
We even created Shared Desktop with them and did it by ourselves to be fully sure of it.
But the error still persists.
However, we are not able to replicate this problem on our test GSuite domain.
We tried couple of options using same SA as the client:
The impersonated account hasn't permissions to access the resource.
This result in:
googleapiclient.errors.HttpError: https://www.googleapis.com/admin/directory/v1/users?customer=my_customer&alt=json returned "Not Authorized to access this resource/api">
The scopes are just partial:
google.auth.exceptions.RefreshError: ('access_denied: Requested client not authorized.', '{\n "error": "access_denied",\n "error_description": "Requested client not authorized."\n}')
The 'Enabled API Access' is not checked.
googleapiclient.errors.HttpError: https://www.googleapis.com/admin/directory/v1/users?customer=my_customer&alt=json returned "Domain cannot use apis.">
The error we are receiving from the client("Client is unauthorized to retrieve access tokens using this method."), we are able to replicate only if the client_id is not in the list of authenticated clients at all.
But we are sure, the problematic GSuite domains have the SA authenticated in "Manage API client access" page.
We are using these scopes: https://www.googleapis.com/auth/userinfo.profile,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/gmail.readonly,https://www.googleapis.com/auth/plus.login,https://www.googleapis.com/auth/calendar.readonly,https://www.googleapis.com/auth/contacts.readonly, https://www.googleapis.com/auth/admin.directory.user.readonly
Do you have any ideas how to debug/solve this issue?
Here is what you need to do. Double check each step. If in doubt, start over.
Enable "Admin SDK API. This is enabled on a per project basis.
Create a service account. Do not add or remove any privileges. Don't change the service account in any way. If you do you will get an error that you are not authorized.
Enable Domain-wide Delegation on the service account.
Follow this document to delegate domain-wide authority to your service account:
Delegate domain-wide authority to your service account
When creating the service account credentials (from the downloaded Json) you will need the following scopes for full G Suite management:
"https://www.googleapis.com/auth/admin.directory.group",
"https://www.googleapis.com/auth/admin.directory.user"
Impersonate a user account which creates new credentials. The user account needs to be a G Suite superadmin. This account must have logged into G Suite at least once and accepted the Terms of Service.
Create your client using the credentials from step #5.
Working Python Example:
from googleapiclient.discovery import build
from google.oauth2 import service_account
# This is the service account credentials file
credentials_file = 'google-directory-api.json'
# In this example I only need to send email
credentials = service_account.Credentials.from_service_account_file(
credentials_file,
scopes=['https://www.googleapis.com/auth/gmail.send'])
# This user is a G Suite superadmin
impersonate = 'username#example.com'
credentials = credentials.with_subject(impersonate)
service = build('gmail', 'v1', credentials=credentials)
I think we are going to need to take this in stages. Lets start with your first error and see if that fixes your issue.
Background info
There are several types of clients that you can create in Google developer console. Here are the top three.
Browser client: Used for web applications
Native client (other): used for installed desktop applications
Service account: used for server to server communication.
The clients are different the client.json file you download is different and the code used to authenticated to the authentication server is also different.
Error 1: code / client missmatch
unauthorized_client: Client is unauthorized to retrieve access tokens using this method.
Can mean one of two things. Either you have created a service account client and you are not using service account code to authenticate or you are are using the code to authenticate with a service account but you have not created a service account client. You haven't posted what language you are using or any code so I cant tell you if the code you are using is intended to be used with a service account or not. Your going to have to look into this one a bit.
Check in developer console make sure your client is like this If it is check your code. If it isnt then create a real service account client and try again.

Google token refresh returns "Token has been expired or revoked."

I have a Google OAuth2 client approved by Google, which provides offline access to user's account with required scopes. My backend application stores and uses the refresh token to refresh the access tokens as and when needed.
Lately, we are seeing that our token refresh attempt is met with an error from Google with:
{
"error" : "invalid_grant",
"error_description" : "Token has been expired or revoked."
}
There is no additional information.
Nothing has changed in my Google OAuth client. The user has not changed account password. The user has not revoked access to my client.
What could be the reason for suddenly getting such errors for token refresh? And how do I avoid this in future (if possible)?
Are you inadvertently asking for the refresh token multiple times? There is a limit of approx. 25 refresh tokens that an account can have extant.
I had same issue, because I run my code in 2 different files and what I did remove token.pickle file, re-run it again.

Insert User in Google Directory with Service Account

I wrote a PHP application which tries to create an User in my Google Directory. I don't use the Google Libraries. I succeded making requests to the Android Enterprise API. I can enroll and unenroll Enterprise Service Accounts with my MSA. So I assume my Code for the JWT and Requests work.
I created a Service Account and enabled "Domain Wide Delegation" and added the following permission "https://www.googleapis.com/auth/admin.directory.user, https://www.googleapis.com/auth/admin.directory.group" to my API Client under the "Manage API client access" windows.
My Service Account has the status role "Editor" in the "Permissions for project" windows.
So first my script gets the Bearer token from the Google Server, for that I create a JWT and encrypt it with my private key.
The Token contains the following fields
"iss" => sacname#projectname.iam.gserviceaccount.com
"scope" => "https://www.googleapis.com/auth/admin.directory.user, https://www.googleapis.com/auth/admin.directory.group"
"aud" => "https://www.googleapis.com/oauth2/v4/token",
"exp" => timestamp+3000,
"iat" => timestamp
When I do that request I get a bearer token, but when I use that token to make the insert request I always get the message "Not Authorized to access this resource/api" with an HTTP 403.
When I add the field "sub" to my JWT and specify the email of the Project admin "admin#mydomain.com" I can't even get the bearer token, then I get a 401 error with the following message "Unauthorized client or scope in request."
After that I tried something "easy", I just wanted to get a list of all users in my directory. But the Google Server just reponds with an "bad request" error. I got the same error with the API Explorer which is on API Page. Maybe the API is broken ? At least the API Explorer should work.
https://developers.google.com/admin-sdk/directory/v1/reference/users/list
Do you have some ideas why I can't create users with my service account ?
(I had to insert some spaces in the scopes and urls because I'm not allowed to post more than two links)
Greetings
Philip
Adding the sub claim is the right thing to do, because you must impersonate a super admin to use Directory API. If you get a "Unauthorized client or scope in request" response, that might be because there's a typo in the service account client ID you used to authorize (or the scopes), or that not enough time has passed (it usually propagates within a few minutes, but could take up to 24 hours).
See JWT error codes for more details on possible errors and causes.
Do you have some ideas why I can't create users with my service account?
Yes. Your service account seems to have no authority to create users. Check your Service Account's role in GDC to check if it's Owner, Editor, Viewer,etc. The scope of what they can do depends on that. Watch this Google video for a live demo.
Also, try to read more on Using OAuth 2.0 for Server to Server Applications.

Windows Azure: AD app for external access throws error on token issue

I am trying to build an AzureAD access app. I have to enable this app for external tenants. I have enabled external access on this app and it is configured to use the Graph API also. I have tested the app in the tenant in which it was created and everything(auth+ graph api access) works. Now here is the flow for the external tenant
I take the external tenant user to the grant consent URL of my app, the user(who is an admin of the external tenant) grants the access and i get the correct response
Now i want to get the authorization token for this user, so i take the user through the normal Oauth process via
https://login.windows.net/common/oauth2/authorize
followed by
https://login.windows.net/common/oauth2/token/
At this point Azure throws the following error
{"error":"invalid_grant","error_description":"AADSTS50000: There was an error issuing a
token. AADSTS65005: No permission to access \u0027https://graph.windows.net\u0027
resource is configured for \u0027d2037ff7-24e4-4cac-8e5e-16e370b36238\u0027 application,
or it is expired or revoked.\r\nTrace ID: 472aa92f-35a2-4ed9-ab07-
12488cc9e6f5\r\nCorrelation ID: b163dde5-eac5-4c82-99ad-0e1100487cb9\r\nTimestamp: 2013-
09-23 05:28:41Z","error_codes":[50000,65005],"timestamp":"2013-09-23
05:28:41Z","trace_id":"472aa92f-35a2-4ed9-ab07-12488cc9e6f5","correlation_id":"b163dde5-
eac5-4c82-99ad-0e1100487cb9"}
Why this error even when the app has been granted access. I tried to lookup the STS errors
but found no explanation. Any ideas?
[update]
SAML process continues to work for the external tenant however i.e I can use the app for SAML(SSO) login for this external tenant. The problem only seems to be coming for getting access to the graph API.
Try adding &prompt=consent or &prompt=admin_consent to the full authorize URL to re-request the user consent. My experience has been that the consent will be randomly revoked (maybe a bug) and will not ever be automatically re-requested (definitely a bug).

Resources