Azure MSAL - Authentication cannot realize userinfo request - azure

I've implemented msal library in my angular application using Implicit Flow. I can login using microsoft ad account and I have the token needed for authentication requests for api usage.
When I decode token using https://jwt.ms/ I can see that aud key has value of my client app id, how should look like the url for userinfo?
If I will use these endpoints which are described in docs I had error with invalid token:
https://graph.microsoft.com/oidc/userinfo or
https://graph.microsoft.com/v1.0/me/
{
"error": {
"code": "InvalidAuthenticationToken",
"message": "Access token validation failure. Invalid audience.",
"innerError": {
"request-id": "8177b64f-c899-48c3-aceb-xxxxxxxxx",
"date": "2020-03-18T07:41:04"
}
}
}
I've forgot to put my module config.
...
MsalModule.forRoot({
auth: {
clientId: environment.CLIENT_ID,
redirectUri: environment.REDIRECT_URI,
postLogoutRedirectUri: environment.POST_LOGOUT_REDIRECT_URI,
authority: environment.AUTHORITY,
},
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: true,
}
},
{
popUp: false,
consentScopes: [
'user.read',
'openid',
'profile',
],
unprotectedResources: [],
protectedResourceMap: [
['https://graph.microsoft.com/v1.0/me', ['user.read']]
]
})
...
where:
authority url: Authority: 'https://login.microsoftonline.com/xxxxtenant_idxxxx'
client id: App registration client id

If you want to call Microsoft Graph API, you need get the access token with the correct(Microsoft graph api) audience.
When you acquire the access token, you should use https://graph.microsoft.com/User.Read or just User.Read as the scope. You can check the values in app.module.ts
Also, remember to add the User.Read permission for your application on Azure portal. App registrations->your application->API permissions->Add a permission->Choose Microsoft Graph API->Delegated permission->Check the permissions you need.
Update:
Reference:
MSAL Angular to login, logout, protect a route, and acquire an access token for Microsoft Graph.

Solved. The problem is in specified endpoint. When I make request for graph from angular the app interceptor handle this endpoint and use scope (user.read) for graph, and then the correct token will be assigned.
Before I was trying to copy token after authorization and pasting it into postman. So yep, the token was not valid in all.. Thank's for your help.

Related

Why is the Google OAuth 2.0 flow not returning an id_token when exchanged with the authorization code?

There's a clear diagram of the how this process works in Google's OAuth 2.0 docs. I've implemented the diagram as expected. My app hasn't been verified by Google yet, so the OAuth consent screen shows a warning and only allows whitelisted emails to be used in the OAuth process (until the app is verified). Using my email addresses, the code works perfectly. As soon as I started using some friends' emails for testing (all of which were whitelisted in the Google Developer Console), I'm not receiving the id_token. Interestingly, I'm not seeing any errors. Exchanging the code, I'm still receiving the access_token and refresh_token but not the id_token.
I don't think it's a problem with my code since I receive the id_token when using my personal email accounts, but here's my code anyways.
class GoogleOauthService implements GoogleOauth {
#client;
constructor() {
this.#client = new google.auth.OAuth2(
process.env.GOOGLE_CLIENT_ID,
process.env.GOOGLE_CLIENT_SECRET,
process.env.GOOGLE_REDIRECT_URL
);
}
async getTokens(
params: GoogleOauth.GetTokensParams
): GoogleOauth.GetTokensResult {
const { tokens } = await this.#client.getToken(params.code);
return {
accessToken: tokens.access_token,
refreshToken: tokens.refresh_token,
scope: tokens.scope,
tokenType: tokens.token_type,
idToken: tokens.id_token,
expiryDate: tokens.expiry_date,
};
}
}
I'm not receiving any errors from the call. tokens results in the following:
{
access_token: 'secret access token',
refresh_token: 'secret refresh token',
scope: 'https://www.googleapis.com/auth/calendar',
token_type: 'Bearer',
expiry_date: 1673742003175
}
If anyone has any idea why Google isn't giving the id_token for some emails, I'd appreciate the insight.
The issue you were having was related to your scope of authorization you are not requesting the proper ones.
Here is a little background information on why you needed to change your scope.
Oauth2 is used for authorization, so if you want to request permission from a user to access their private user data.
I can see that you are requesting the scope of https://www.googleapis.com/auth/calendar You are using Oauth2 to request permission of a user to access their google calendar data this is Oauth2. The response will be an access token granting you access to their google calendar data and a refresh token. This is what Oauth2 responds with
{
access_token: 'secret access token',
refresh_token: 'secret refresh token',
scope: 'https://www.googleapis.com/auth/calendar',
token_type: 'Bearer',
expiry_date: 1673742003175
}
Then we have Sign-in or authentication or Open Id connect which was actually built on top of Oauth2. Open Id connect allows you to verify that the user behind the machine is in fact the owner of the account. This is authencation not authorization. We are authenticating or signing in a user. Open Id connect returns an access token and a refresh token and an id token.
{
"access_token": "[redacted]",
"id_token": "[redacted]",
"expires_in": 3599,
"token_type": "Bearer",
"scope": "openid https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile",
"refresh_token": "[redacted]"
}
To use open id connect you need to use the profile, openid, and/ or email scopes. Then you will get back an access token granting you access to use profile information as well as the refrshtoken, and also an id token.
The id token is the key part of open id connect it gives you information on the user itself if you take it over to jwt.io you can decrypt the jwt.
{
"iss": "https://accounts.google.com",
"azp": "407408718192.apps.googleusercontent.com",
"aud": "407408718192.apps.googleusercontent.com",
"sub": "[MyInternalGoogleId]",
"email": "[MyEmailAddress]",
"email_verified": true,
"at_hash": "Je-vk1k8MRaqK0gw3yXj7g",
"name": "Linda Lawton",
"picture": "https://lh3.googleusercontent.com/a/AEdFTp46WTOIbHj5Nl1VJRFf4Izj9YrX61i75F16H1qSA1Q=s96-c",
"given_name": "Linda",
"family_name": "Lawton",
"locale": "en",
"iat": 1673784532,
"exp": 1673788132
}
The Id token allows you to verify after a user has been authenticated that they are in fact the owner of the account and just signed in.
as opposed to authorization which will only give you an access token with no guarantee that the one sending the access token was the user who owns the account, it could be an automated server app which has been granted authorization to access the users data.
I'm now able to retrieve the id_token for accounts that I was previously unable to. The change I made was including the following in my OAuth 2.0 scopes
[
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email',
];
Once these two scopes were included, the id_token appeared.

Which scope use to get the access token for Microsoft credential

I'm trying to do postman access token request to reach the following api :
however the result returned is always the same:
"error": {
"code": "Unauthorized",
"message": "Unauthorized",
"target": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
POST : https://login.microsoftonline.com/%7Btenant-id%7D/oauth2/v2.0/token
Body:
client_id : my client id
scope :https://graph.microsoft.com/.default
client_secret : my client secret
grant_type : client_credentials
Header:
Content-Type : x-www-form-urlencoded
The response return me a token that is apparently not recognized by the first request...
I've tried several scopes such as : /.default, user.read openid profile offline_access, https://graph.microsoft.com/.default...
Even if they are all returning me a token, none of them seems to work.
I've also added the right to WindowsDefenderATP > Vulnerability.read, from the azure portal.
Is the problem the scope? What scope should I use if I have a client credential grant type?
You can follow this page in documentation.
You need an application permission since you are making the request with only application credentials.
In this case I think you need the Vulnerability.Read.All permission.
Don't forget to grant admin consent after adding the required permission.
Here is the scope you should use:
https://api.securitycenter.microsoft.com/.default

Im implementing Microsoft Azure oauth2 on our web app, but when fetching access token using auth code, we are seeing below error

{
"error": "invalid_grant",
"error_description": "AADSTS9002313: Invalid request. Request is malformed or invalid.\r\nTrace ID: 1740a160-8c95-42da-aa37-562693c30300\r\nCorrelation ID: 918e8299-271d-46a9-9e9b-5893a348f934\r\nTimestamp: 2022-01-24 11:49:44Z",
"error_codes": [
9002313
],
"timestamp": "2022-01-24 11:49:44Z",
"trace_id": "1740a160-8c95-42da-aa37-562693c30300",
"correlation_id": "918e8299-271d-46a9-9e9b-5893a348f934",
"error_uri": "https://login.microsoftonline.com/error?code=9002313"
}
Solution 1:
If you are trying to get get token using OAuth 2.0 code grant flow, then Request access token using authorization code.
https://login.microsoftonline.com/YourTennatId.onmicrosoft.com/oauth2/authorize?client_id=YourClentId&response_type=code&redirect_uri=https://www.getpostman.com/oauth2/callback&response_mode=query&scope=offline_access%20user.read%20mail.read
Use the authorization code to request an access token:
Token Request Endpoint: https://login.microsoftonline.com/YourTenantId/oauth2/token
client_id:YourClientId
scope:https://graph.microsoft.com/User.ReadWrite.All
redirect_uri:https://www.getpostman.com/oauth2/callback
grant_type:authorization_code
client_secret:YourAppsSecret
code:Paste Your Code Here
Post Man Format:
Solution 2:
After you app registration in the Azure Portal,
enter this link in the browser to get the code:
https://login.microsoftonline.com/{tenant}/oauth2/authorize?
client_id={your-client-id}
&response_type=code
&redirect_uri=https://localhost:4500/web/completeoauth/ms
&response_mode=query
&state=12345
and use postman to get the access token like below:

Fetching user information from Azure AD

I have created an application on Azure AD and I have assigned User.Read.All permission to my application.
That being said, I can generate an access token for the app from Postman. When generating access token I supply -
client_id: xxxx
client_secret: yyyy
grant_type: client_credentials
scope: https://graph.microsoft.com/.default
Using the generated access token (as header Authorization: Bearer zzzz) I send a GET request to https://graph.microsoft.com/v1.0/users/jhon.doe#domain.com. Which gives me error -
403 Forbidden
{
"error": {
"code": "Authorization_RequestDenied",
"message": "Insufficient privileges to complete the operation.",
"innerError": {
"request-id": "aaa-bbb-ccc-ddd",
"date": "2019-09-10T12:44:46"
}
}
}
Can anyone tell me what wrong I am doing?
Thanks in advance.
You need to add Application permissions.
Not delegated permissions.
In your screenshot we can see that they are delegated, which means they only apply in situations where there is a user involved in the authentication.
Since you use client credentials authentication, there is no user involved, only the app.
When you add required permissions, there should be an option to choose between Delegated and Application.
Choose Application, choose the necessary permissions, and grant them.

ProjectServer 2013 REST APIs with Windows Azure Access Token

I'm trying to use Project Server 2013 REST APIs with Windows Azure access tokens but getting GeneralSecurityAccessDenied error.
I have register my app in Azure AD on the Management Portal to get client_id, redirectUri.
The permissions to the application are “Office 365 SharePoint Online” and “Windows Azure Active Directory”.
I’m calling the authorization endpoint in the following URL, is this correct?
https://login.windows.net/common/oauth2/authorize?response_type=code&client_id= &redirect_uri=&resource=https://.sharepoint.com
Then I’m calling token endpoint URL
https://login.windows.net/common/oauth2/token with the following parameters
grant_type is authorization_code
code is “Access Code Returned from the first call”
redirect_uri is <MY URL>
resource is https://<mytestdomain>.sharepoint.com
This gives me Access Token and Refresh Token, but when I use the Access Token to do something it gives me the error “GeneralSecurityAccessDenied”
My POST request is
https:// <mytestdomain>.sharepoint.com/sites/pwa/_api/ProjectServer/Projects/Add
Authorization is Bearer <Access Token>
Content-Type is application/json;odata=verbose
The request body is
{
'parameters' : {
'Name':My Test ',
'Description': Test Project',
'Start':'1/28/2015'
}
}
The Error response is follows.
{
"error": {
"code": "20010, Microsoft.ProjectServer.PJClientCallableException",
"message": {
"lang": "en-US",
"value": "GeneralSecurityAccessDenied"
}
}
}

Resources