Not Getting a refresh_token - azure-active-directory

This is in continuation with my other question.
I had to finally get the user in question the admin role and then I created a new application registration at https://apps.dev.microsoft.com/
The application was granted admin consent by hitting https://login.microsoftonline.com/common/adminconsent?.. endpoint with the required parameters.
Everything works fine and I was even able to create the outlook mail subscription for this user.
The issue though is, the endpoint https://login.microsoftonline.com/common/oauth2/v2.0/token is not giving me the refresh_token. I tried including the offline_access (reference - http://massivescale.com/microsoft-v2-endpoint-primer/) in the scope for getting the authorization code, but got the following error -
AADSTS65001: The user or administrator has not consented to use the application.
So the situation is like this -
If I use v1.0 endpoint, I get both access and refresh token but
hitting the endpoint
https://outlook.office.com/api/v2.0/Users('dummy#example.com')/subscriptions
sends back a 401 Unauthorized. I understand that the endpoint targets v2.0 but I didn't find one for v1.0.
However, If I use v2.0 endpoint, I am able to create the subscription but only get the access token which is shortly lived and this creates a need for going through this whole process again which I don't want.

As a commenter indicated, you've registered an Azure AD v2.0 application, and are calling the Azure AD v1.0 endpoints. This isn't strictly the problem you're facing, but I recommend reconfiguring your auth endpoints to be for v2.0.
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
I think the issue you may be running into is not configuring static permissions before calling the admin consent endpoint. One of the new features of Azure AD v2.0 is dynamic consent & scopes that allow you to ask for new permissions when requesting them; however, for admin consent you must configure these as static permissions.
You can configure static permissions in Azure AD v2.0 inside the App Reg Portal through the UI below:
Then try hitting the admin consent endpoint again, and finally re-requesting the refresh token with the offline_access scope.

Related

Graph API POST Request (Create List Item) 'accessDenied' error for Guest AD Users

I have quite a strange issue (well I think it is)... I'm building a web application using Ionic Angular and this application needs to submit information to a SharePoint site within our company. Authentication for the application is handled using Microsoft Authentication Library for Angular (v1) and the users of the application can either be AzureAD Guest users, or actual company users. The application successfully authenticates both types of users and they are issued an IDtoken, along with an accessToken. The access token is then used to perform GET, PATCH and POST Graph API requests against particular lists within a SharePoint site.
If I'm logged in as a full user... there is no issue, the app can successfully perform all three request types against the lists. However, if I'm logged into the application as a Guest user, I can only successfully perform GET and PATCH requests, but not POST:
A Postman POST request using the access token retrieved via MSAL authentication
I have checked the scopes within the token using https://jwt.ms and confirm that the following scopes are present:
Sites.Manage.All
Sites.Read.All
Sites.ReadWrite.All
User.Read profile openid email
The permissions for the lists are granted through membership of an Azure AD Domain/Security group and both; the full user and guest user are members.
To further add to this, I've logged into the SharePoint site online as the Guest User and I can successfully See, Add and Edit List items from the list, but I can't seem to do this via the Graph API.
Has anyone seen this behaviour before, or has any pointers?
Thanks in advance.
This is my app registration setup regarding permissions:
API Permissions
Please check your permissions in Azure Portal. When getting the access token with a signed-in user, you need to make sure the delegated permission Sites.ReadWrite.All has been set, and grant admin consent for your tenant.
And the scope should be added this permission for requesting an access token.
POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
client_id=<client_id>
&scope=https%3A%2F%2Fgraph.microsoft.com%2FSites.ReadWrite.All
&code=<authorization_code, see https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow#request-an-authorization-code>
&redirect_uri=<redirect_uri>
&grant_type=authorization_code
&code_verifier=ThisIsntRandomButItNeedsToBe43CharactersLong
&client_secret=<client_secret>
It may be a delay about 5-10 mins after adding the permission.

Azure AD OBO Reconsent

I'm currently developing an application which consists of a frontend SPA which makes request to a Node backend. The Node backend makes requests to MS Graph. For this usecase I set up the OBO flow which works fine.
The SPA uses MSAL.js to request a token for middle tier API with /.default scope. The middle tier API knows the client as 'knownclient' in its Manifest. On very first login the application wants the user to consent to the combined scopes from client and middle tier. (If the user never used the app before)
The problem now is the following: By going further in the development process, new scopes are added for MS Graph in the middle tier API. However the client doesn't show the consent prompt to the user for giving his consent to use the new backend scope although using the /.default scope in the client.
The first approach I had was settings prompt='consent' to the MSAL setting in the frontend. This approach works but results in asking the user for consent every time he logs in.
The intended behaviour would be to just ask for consent if the middle tier API changes its scopes.
How do I have to set up my applications to get this result?
As I said in the comments, if you just add new permissions, don't use prompt='consent', because this will cause the administrator consent page to be triggered every time you log in as a user.
When you add a new permission, you only need to grant the administrator's consent, and there is no need to request the user's consent again. So, you only need to grant the administrator consent in the Azure portal. Or, use the url that the administrator consent to: https://login.microsoftonline.com/{tenant-id}/adminconsent?client_id={client-id}.

How to authenticate to personal OneDrive with Graph REST API

I'm trying to write an R package to let users access the files in their OneDrive folders from R. The API is Microsoft Graph.
Everything is working fine with OneDrive for Business (which is basically SharePoint under the hood, as I understand it). However, I can't get it to work with personal OneDrive.
Custom app registration, consumers authorization endpoint
When I use an app registration under my own AAD tenant, I get the following error from the consumers AAD authorization endpoint:
AADSTS50020: User account 'xxxxx#gmail.com' from identity provider 'live.com' does not exist in tenant 'Consumers' and cannot access the application 'd44a05d5-c6a5-4bbb-82d2-443123722380'(AzureRtest_cli) in that tenant. The account needs to be added as an external user in the tenant first. Sign out and sign in again with a different Azure Active Directory user account.
Custom app registration, 9188040d-6c67-4c5b-b112-36a304b66dad endpoint
From this page it appears that the token should be for the tenant 9188040d-6c67-4c5b-b112-36a304b66dad instead of the generic consumers. When I tried that, I obtained a seemingly valid token. However, talking to the https://api.onedrive.com/v1.0/drive endpoint results in a cryptic 401 error.
Azure CLI app registration, consumers endpoint
As a hack, I tried piggybacking off the Azure CLI's app registration. This fails with
AADSTS65002: Consent between first party application '04b07795-8ddb-461a-bbee-02f9e1bf7b46' and first party resource '00000003-0000-0000-c000-000000000000' must be configured via preauthorization. Visit https://identitydocs.azurewebsites.net/static/aad/preauthorization.html for details
Azure CLI app registration, 9188040d-6c67-4c5b-b112-36a304b66dad endpoint
Finally, I tried using the CLI app registration with this tenant, which also failed:
unauthorized_client: The client does not exist or is not enabled for consumers. If you are the application developer, configure a new application through the App Registrations in the Azure Portal at https://go.microsoft.com/fwlink/?linkid=2083908.
What are the exact steps I need to do to get to my personal OneDrive?
It turns out I had a bug in my code: I was using the tenant consumers.onmicrosoft.com instead of consumers. The process to communicate with Graph for personal OneDrive that worked for me was:
Use the authorization code flow as described here, with the following specs:
tenant: consumers
client id: for my custom app registration
scope: https://graph.microsoft.com/{scope} offline_access openid where the scope is one of those listed here
Use the API endpoint https://graph.microsoft.com/v1.0.
With regard to that last point, note that the documentation here is incorrect or at least outdated, as it still gives https://api.onedrive.com/v1.0 as the endpoint for personal OneDrive requests.

Why do i need to create a Multi-Tenant App?

I have been doing some R&D on using the MicrosoftGraphAPI to fetch the skus subscribed by my organization.
I have created an app as described in the documentation. I did all the steps in the above link except 'Assign application to role'.
Using postman am able to get the oauth2 token by sending a post request using the link
https://login.microsoftonline.com/<mytenantid>/oauth2/token
with the client_id, client_secret, resource(https://graph.microsoft.com) and grant_type(client_credentials) parameters.
After this token is obtained I can fire a get request https://graph.microsoft.com/v1.0/subscribedSkus with the Authorization header set as Bearer {token} which will return the SKUs subscribed by my organization.
So far so good. :-)
Now the requirement is I need to fetch the subscribed SKUs by one of the client (let's say having the azure ad tenant id 'ABCDEFG') of my organization.
I can successfully do that by registering an app in the client's tenant 'ABCDEFG' with the same steps as above.
This approach is fine if my organization has say 1 or 2 clients.
However, if the client numbers are more than say 30 this approach of registering an application in each Azure AD instance is not feasible.
If the application that I registered in my organizations AAD was multi-tenant then how should it help me?
What will be the steps needed to obtain the access token for each tenant?
Can somebody assist with some detailed explanation?
Since you need application-level access, you would assign one of the Application permissions listed in the documentation for getting SKUs: https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/subscribedsku_list.
Directory.Read.All, Directory.ReadWrite.All
In this case you should require the Read Directory Data (Directory.Read.All) application permission.
Then you mark your app as multi-tenanted.
Now then in order for another org to use your app, they will have to be on-boarded.
You will need some kind of page where their administrator can click a button/link to start using your app.
This should redirect the admin to:
https://login.microsoftonline.com/common/oauth2/authorize?client_id=your-client-id&prompt=admin_consent&response_type=code+id_token&redirect_uri=url-where-to-send-user-back
Once they sign in, they will be presented with a consent screen, where they can approve the permissions that your app requires.
If and when they do that, they will be redirected back to your app (to the URL you specified) and you can use the Id token to know which Azure AD tenant registered.
During this process a service principal for your app is created in their tenant, and the required permission is granted to it.
This means you can then get an access token for their tenant from: (using the same credentials)
https://login.microsoftonline.com/their-tenant-id/oauth2/token
Remember that access tokens are specific to an Azure AD tenant, so you will have to get an access token for each tenant.
One thing I would like to point out is that you should instead try to use delegated permissions if possible.
The application permission given here gives quite large access to your app, and some admins might not use your service for that reason alone.
Delegated permissions are more complex to handle, but allow your app to act on behalf of a user instead of purely as itself.

Accessing Intune graph api using send-on-behalf authorization gives response as unauthorized

I Followed the Active Directory .NET WebAPI onBehalfOf sample.
In the web api created another endpoint to access Intune app protection policy from url
https://graph.microsoft.com/beta/deviceAppManagement/managedAppPolicies,
in azure provided permission to app to access Graph API.
In the call to AquireTokenAsync changed the resource Id to https://graph.microsoft.com/.
This returned the JWT token that contained:
"aud": "https://graph.microsoft.com/",
"scp": "DeviceManagementApps.ReadWrite.All User.Read",
However fetching the endpoint
https://graph.microsoft.com/beta/deviceAppManagement/managedAppPolicies
Returns an HTTP response of 401 Unauthorized.
What is missing?
This generally implies one or both of the following issues:
You need to obtain Admin Consent. The DeviceManagementApps.ReadWrite.All scope requires that an Admin consent to the permissions before a normal user can can authorize the scope.
You're app's registration doesn't have the correct scopes defined in Azure. Make sure your registration is selection scopes for Microsoft Graph and not Azure AD Graph API. These are two distinct APIs and the differences are greater than simply the resource URI.
Also note that the Client Credentials grant (aka Application scope) isn't supported by the Intune APIs. You can only call these endpoints using Delegated permissions (Authorization Code or Implicit grants).

Resources