AAD v2.0: unable to use .default scope with device code flow - oauth-2.0

I'm wondering if anyone has run into this problem. I'm trying to authenticate to OneDrive using AAD v2.0, and the device code flow. My app has the following permissions configured in the Azure portal:
Microsoft Graph:
email
Files.ReadWrite.All
offline_access
openid
profile
User.Read
Each time I try to authenticate, I get the following error message from the token endpoint:
AADSTS70011: The provided value for the input parameter 'scope' is not valid. One or more scopes in 'https://graph.microsoft.com/.default openid offline_access' are not compatible with each other.
However, when I use the usual authorization code flow, it works. Similarly, if I use the scope https://graph.microsoft.com/Files.ReadWrite.All openid offline_access instead of https://graph.microsoft.com/.default openid offline_access, it also works.
Is there something about the .default scope that is incompatible with the device code flow?
More info:
The app can be used by "Accounts in any organizational directory (Any Azure AD directory - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox)". I'm authenticating to the "consumers" tenant because I want to access my personal OneDrive.

Just remove openid offline_access from the scope, it should be https://graph.microsoft.com/.default, when you use /.default, they are not needed, all permissions registered by the application will be included.
Reference - https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#the-default-scope
Update:
I can reproduce your issue with /consumers and a personal account in the auth url, if I modify it to /<tenant-id>, it works fine, you could refer to the steps below.
1.In the postman, use the request below.
Request URL:
POST https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/devicecode
Request Body:
client_id=<client-id>
scope=https://graph.microsoft.com/.default
2.In the browser, navigate to the https://microsoft.com/devicelogin, input the code and login your user account, the app will let you consent the permission, click the Accept.
3.After login successfully, in the postman, use the request below.
Request URL:
POST https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token
Request Body:
grant_type: urn:ietf:params:oauth:grant-type:device_code
client_id: <client-id>
device_code: <device_code in the screenshot of step 1>

Related

OIDC Azure AD token?

I am trying to configure a third party web application to use Azure AD as the OIDC provider. The authentication works fine, however I am looking for some claims and not able to find an ID or Access Token. Here is the flow as I am seeing it
Call to the login page of the web application. This gets a 302 redirect to the Microsoft OAuth endpoint as below
The URL is https://login.microsoftonline.com/-tenantid-/oauth2/v2.0/authorize?client_id=-clientid-&redirect_uri=-encodedCallbackURI-&response_type=code&scope=openid+email+profile&state=123 This does a 302 to below URL
Next call is to https://login.microsoftonline.com/-tenantid-/oauth2/v2.0/authorize?client_id=-clientid-&redirect_uri=-encodedCallbackURI-&response_type=code&scope=openid+email+profile&state=123&**sso_nonce=O.eyJ0eXAiOiJK......**&client-request-id=-guid-&mscrid=-guid- This returns a 200
Next is the redirect back to the hosted web application indicated in teh callback - https://webApplicationURL/callback?code=0.AQ4Ayjxg80......&state=123&session_state=5b7c2e43-9eab-4bb1-9f24-d020f144d30d
At this point, the user has successfully been authenticated. However, I would like to find the ID or Access Token received.
The sso_nonce(in #3) is in a JWT format but has no claims.
The code(in #4) doesn't have any of the claims either and doesnt really seem to be a JWT token format.
So where is the ID Token or Access Token that I can use to decode and see what claims are getting passed (or not)?
Thanks in advance,
Jake.
To get tokens while calling login page of the web application, you can execute the below request in browser by including response_type as id_token+token:
https://login.microsoftonline.com/<tenant_ID>/oauth2/v2.0/authorize?
client_id=da5daf42-xxxx-xxxx-xxxxxx04a52 //your AppID
&response_type=id_token+token //Required
&redirect_uri=https://jwt.ms //your Redirect URL
&response_mode=fragment
&scope=openid+profile+email
&state=12345
&nonce=678910
Make sure to enable tokens for your web application before executing the above request like below:
Go to Azure Active Directory -> App Registrations -> Your App -> Authentication -> Enable tokens -> Save
I tried to reproduce the same in my environment and got the below results:
When I executed the above-mentioned request in the browser, it asked me to sign in like below:
After successful sign-in, it took me to the redirect URL with tokens in the address bar like below:
When you copy-paste the above in Notepad or any, you can find both access_token and id_token like this:
I got the claims successfully when I decoded the token like below:
Reference:
OpenID Connect (OIDC) | Microsoft Docs

Add a member to MS Teams using Graph API

I am attempting to add a member to my MS Team using the Graph API and an Azure app token:
Endpoint: https://graph.microsoft.com/v1.0/teams/c924e9b8-*****/members
Body:
'#odata.type':'#microsoft.graph.aadUserConversationMember'
'roles':'[]'
'user#odata.bind':'https://graph.microsoft.com/v1.0/users('41134b16-6f68*****')
When I send this request I am getting:
"code": "InternalServerError"
"message": "Failed to execute request."
I can't seem to find any information on what this error means. Is anyone familiar with this error?
The issue must be due to Web App token generated from Developer portal.
Steps to Resolve:
Check if the required permissions are provided to the app
registration you are using for the webapp i.e.
TeamMember.ReadWriteNonOwnerRole.All with admin consent like below :
Go to Postman>>new_request>>authorization>>Select Oauth2.0 in type>> select Grant type as Client Credential>> fill necessary
details provided below and then click on new access token.
Access Token URL : https://login.microsoftonline.com/my-tenant-id/oauth2/v2.0/token
ClientId: azure ad App reg ID
ClientSecret: Secret generated for the same app
scope: https://graph.microsoft.com/.default
Once the above is done you will be successfully able to do the
operation :

Get Azure AD directory users in a Rails app

I have a Rails 6 application and I want to use Azure Active Directory as an authentication system (with open id connect, saml2 and ldap).
The authentication is done.
Now I am trying to display user information like names or email addresses. I also want to be able to export all users of a directory.
I have tried to set a configuration up like so:
In my Rails app, in the admin panel, an admin can configure Azure AD for my application
in the config, the admin copies and pastes the configuration link provided by Azure AD (a JSON response)
Then, copies and pastes the app client_id
Then, the tenant_id (directory id)
Here is a piece of code that I expected to work:
def update_oidc
identity_provider = IdentityProvider.find_by(provider_type: 'open_id_connect', id: params[:id])
client_id = params[:client_id].strip
metadata_url = params[:metadata_url].strip
tenant_id = params[:tenant_id].strip
metadata = HTTParty.get(metadata_url).parsed_response
identity_provider.update(config: {
metadata: metadata,
metadata_url: metadata_url,
client_id: client_id,
tenant_id: tenant_id,
})
if tenant_id
directory_access_url = "https://graph.windows.net/#{tenant_id}/users?api-version=1.6"
result = HTTParty.get(directory_access_url).parsed_response
identity_provider.directories.find_or_create_by(tenant_id: tenant_id).update(
business_phones: result["business_phones"],
display_name: result["display_name"],
given_name: result["given_name"],
job_title: result["job_title"],
email: result["user_principal_name"],
mobile_phone: result["mobile_phone"],
office_location: result["office_location"],
surname: result["surname"]
)
end
redirect_to identity_provider
end
As the tenant_id is the directory id, i thought that we might be able to access user info this way (and following the Microsoft Docs). The thing is, it doesn't work because even though I'm connected to my Azure AD directory in my app, when I run result = HTTParty.get(directory_access_url).parsed_response, i have an authentication error telling me the token has expired or that i need to be connected.
I don't want to use PowerShell or anything like this. I want to be able to access directories data through my app.
Can someone tell me what i'm doing wrong or come up with an idea ?
Thanks
Just according to your code, I think you want to get the collection of users via the Azure AD Graph REST API Get users using jnunemaker/httparty library.
However, it seems to be missing the required header Authorization with its value like Bearer eyJ0eX ... FWSXfwtQ as the section Authentication and authorization of the offical document Operations overview | Graph API concepts said. Meanwhile, you have done the authentication with OpenID Connect, but Azure AD Graph API requires the access token as Authorization value from OAuth2 as the content below said.
The Graph API performs authorization based on OAuth 2.0 permission scopes present in the token. For more information about the permission scopes that the Graph API exposes, see Graph API Permission Scopes.
In order for your app to authenticate with Azure AD and call the Graph API, you must add it to your tenant and configure it to require permissions (OAuth 2.0 permission scopes) for Windows Azure Active Directory. For information about adding and configuring an app, see Integrating Applications with Azure Active Directory.
Azure AD uses the OAuth 2.0 authentication protocol. You can learn more about OAuth 2.0 in Azure AD, including supported flows and access tokens in OAuth 2.0 in Azure AD.
So I'm afraid you have to get the access token manually via OAuth2 for Azure AD again for using Graph API, or just simply refer to the sample code samples/authorization_code_example/web_app.rb using the adal library of GitHub repo AzureAD/azure-activedirectory-library-for-ruby for Ruby.

Oauth2.0 Google API token issue - Error: redirect_uri_mismatch

I have trouble creating a Google API OAuth2.0 token though following all the steps here: [OAuth2 Authentication](
https://developers.google.com/adwords/api/docs/guides/authentication?authuser=1)
When trying to create the token through the OAuth2.0 playground:
OAUTH 2.0 playground
I end up with this error:
Discussion on similar threads tried to give some guidance but without any luck in my case.
Add google.com in the authorized domain list of your app's OAuth consent screen.
Click on the application for which you want to configure for the next step:
Make sure to also add 'https://developers.google.com' in the Authorized JavaScript origins and 'https://developers.google.com/oauthplayground' in the Authorized redirect URIs[click 'save' below once added]:
You are applying your own client id and client secret to Oauth2 playground you are also using browser credentials.
For browser credentials to work it must be able to return the token to an endpoint that can handle it and that endpoint (Redirect uri) must be registered in the Google Developer console for that project.
if you check your first picture under the check box you clicked
You will need to list the URL https://developers.google.com/oauthplayground as a valid redirect URI in your Google APIs Console's project. Then enter the client ID and secret assigned to a web application on your project below:
Try adding that URL as it says.

How to access another user's data via the Graph API?

Using the Graph API and related authentication/authorization flows, how can I access data of all users in an organization? Also, multiple organizations/tenants need to be able to use the app.
As an example: I have an app which needs to read events from all calendars of all users under contoso.onmicrosoft.com. I would like that jack#contoso.onmicrosoft.com, the administrator, authorizes the app which will then be able to read the mentioned the data. Using the Managed API this can be easily done via impersonation.
However, I am trying to do the same with Graph API and OAuth, but I can't find a straight forward solution, or I must be missing something very obvious. I have created an app through manage.windowsazure.com (multi-tenant), and configured it so that it requires Microsoft Graph API (all application and delegated permissions).
I did the following:
1) Point jack#contoso.onmicrosoft.com towards https://login.microsoftonline.com/common/oauth2/authorize?response_type=code&redirect_uri=<my redirect url>&client_id=<my client id>
2) Jack authorizes the app
3) I get back: <my redirect url>/?code=<my authorization code>&session_state=<blah>
4) I send a POST request like below:
POST https://login.microsoftonline.com/common/oauth2/token
Headers: content-type: application/x-www-form-urlencoded
Body:
grant_type=authorization_code&code=<my auth code from step above>
&redirect_uri=<my redirect url>
&client_id=<my client id>
&client_secret=<my client secret>
&resource=https%3A%2F%2Fgraph.microsoft.com%2F
5) When I do the following:
GET https://graph.microsoft.com/v1.0/users/jack#contoso.onmicrosoft.com/messages
Headers: Authorization: Bearer <auth token from step #4>
I get a 200 OK response with the messages.
When I do the following:
GET https://graph.microsoft.com/v1.0/users/anyotheruser#contoso.onmicrosoft.com/messages
Headers: Authorization: Bearer <auth token from step #4>
I get a 403 Forbidden response with:
{
"error": {
"code": "ErrorAccessDenied",
"innerError": {
"date": "2016-06-07T08:47:27",
"request-id": "5b629e30-e6bd-474d-b3dd-8ce25c5ad1c4"
},
"message": "Access is denied. Check credentials and try again."
}
}
The flow/URLs you've referenced are for the authorization code flow which leverages delegated scopes.
A) If you want the app to only work (i.e. access all calendars) for admins then you are using the right flow.
B) If you want the app to work for all users after the admin consents to it, you'll need to use the app (client credentials) flow and use application scopes. This means that you'll need to separate out consent from the regular auth flow.
For consent you'll need to to point the admin to the following url:
GET https://login.microsoftonline.com/common/oauth2/authorize?resource=https://graph.microsoft.com/&client_id=<YourClientId>&client_secret=<YourClientSecret>&response_type=code&redirectUri=<YourRedirectUri>&prompt=admin_consent
For auth flow you'll need a single call from your web server:
POST https://login.microsoftonline.com/common/oauth2/token
body resource=https://graph.microsoft.com/&client_id=<YourClientId>&client_secret=<YourClientSecret>&response_type=code
Or better yet, just use ADAL's AquireToken(resource, clientCredentials) overload.
Once that's done, your app should be good to go to make requests to Graph.
Regardless if you want to stick to A) or switch over to B), to double check that things are set up correctly you can:
Check the token that you get back from Graph (the one you attach to the request along with Bearer) and confirm that it has a roles entry with the roles you need i.e. Calendars.Read
NOTE: The following steps 2.a & 2.b require you to have admin to a test tenant where you'd be consenting to the application.
2.a Use GraphExplorer (https://graphexplorer2.azurewebsites.net/) and confirm that consent has been properly set up by querying
beta/servicePrincipals?$filter=displayName eq '[YourApplicationName]'
If nothing shows up, then the no one has consented to the application.
2.b (only applicable for auth code flow with delegated scopes) Use GraphExplorer and confirm that either delegation has been authorized correctly by querying
beta/oauth2permissiongrants?$filter=clientId eq '[IdFrom ServicePrincipal in 2.a]'
And ensuring you get either a result for the specific user in question or for "AllPrincipals".
More info on app vs delegated scopes here: http://graph.microsoft.io/en-us/docs/authorization/permission_scopes
More info on app flow here: https://graph.microsoft.io/en-us/docs/authorization/app_only
Please use the app-only auth flow (see https://graph.microsoft.io/en-us/docs/authorization/app_only) to use the application permissions - for the token request (step 4) you need to pass grant_type=client_credentials instead of grant_type=authorization_code.

Resources