I am not able to approve my Azure active directory (PIM) pending request programmatically through Graph API? - azure

I am try to approve the prividedge identity management (PIM) request through graph api but when i try to approve it the api is return forbidden. See the below screenshots
The pending request should be approved.

First, I want to know what API permission you consented for using this graph API, because to be honest, I didn't find this graph API, I only found this document which contained the API request you used.
According to the error message, I'm afraid you gave the wrong api permission or you used client credential flow to generate the access token to call the API. So it's better to provide the request you used to generate access token.
Finally, I found an answer here which successfully call the API but with Powershell script. According to this sample, we should give PrivilegedAccess.Read.AzureAD,RoleAssignmentSchedule.ReadWrite.Directory,PrivilegedAccess.ReadWrite.AzureAD delegated API permission and use it to generate access token. We need to use auth code flow/ROPC flow so that the token generated should contain scp claim with API permissions as value. Then using that token to call the API.
You may try request below to generate the access token for a test:
POST https://login.microsoftonline.com/{TenantId}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
client_id=azure_ad_app_id_consented_api_permission
&scope=PrivilegedAccess.Read.AzureAD RoleAssignmentSchedule.ReadWrite.Directory PrivilegedAccess.ReadWrite.AzureAD
&username=user_name_better_to_use_account_with_Global_Administrator_role
&password=password
&grant_type=password

Related

Obtain SharePoint specific access token for a non-user application

I am working on a PHP web app that needs to make HTTP requests to the Sharepoint API with Sites.Selected permission to a specific SharePoint site. It is NOT viable for me to provide a user sign-in experience so I need to treat it as a non-user/daemon application.
I've read the docs and looked at many different forums for the solution but as of yet I've been unsuccessfull in obtaining a SPO specific access token, although I think I'm close.
I am using this StackOverflow answer as a guide: https://stackoverflow.com/a/63386756/19038862
This is what I've done:
Registered an Azure App: (Image of my Azure App Overview)
Created a client secret in the App dashboard: (Image of the client secret page)
Successfully sent a request to https://login.microsoftonline.com/{{app_tenant_id}}/oauth2/v2.0/token using the client secret in Postman: (Image of Postman request)
The request made in step 3 returns an access token (I assume a MS Graph access token?), but it DOES NOT return a refresh token, which is what the afforementioned StackOverflow answer suggests you need to "swap" for an SPO specific access token.
How do I obtain this refresh token so that I can swap it for a SPO access token? Or what better way is there to get my hands on a SPO specific access token from a non-user app?
I wrote this gist to guide you into getting Sites.Selected access to the desired site:
https://gist.github.com/ruanswanepoel/14fd1c97972cabf9ca3d6c0d9c5fc542
This guide shows you how to configure this as Application permissions, and via the Graph API.
I've found going through the Graph API is the best way to go.
Also strangely it's not possible to get delegated Sites.Selected permissions. You must set it up as an Application permission.
In the guide is described that you have to get a delegated auth token from graph but you are getting an application auth token. The token response of this flow does not contain a refresh_token. See here.
But you already wrote that you are not able to provide a user sign-in experience. One workaround would be to once manually get the access_token and refresh_token of a user with the delegated flow and then periodically get a new access_token with the refresh_token on your server. You could store these values in your database and update them when you fetch a new one.
First, the daemon-based client credential flow does not return a refresh token for you. You also can't redeem the refresh token of the graph API for an access token for SPO, which are two completely different API resources.
To get an access token for SPO you just need to set scope to: https://{tenant-name}.sharepoint.com/.default.

Call SharePoint REST API from Teams Tab

I have a Teams Tab application that needs to do some manipulations with the team's site.
The User needs to be authenticated, and all operations are executed on behalf of the user.
Calling the graph API is somewhat documented, I have found a good article here for example:
https://bob1german.com/2020/08/31/calling-microsoft-graph-from-your-teams-application-part3/
But I want to call SharePoint REST API directly, not through the graph API because I want to do some operations that are not supported by graph API (yet?), like creating a page.
How can I achieve this?
As far as I understand I need to exchange the token I get from teams to another token that can be used to call SharePoint. (on_behalf_of flow). I added the scopes for SharePoint to the app registration, and requesting those when exchanging the token (https://microsoft.sharepoint-df.com/AllSites.Read for example). But I keep getting 401 access denied.
Please note that this is NOT about calling graph API. This is about the "normal" SharePoint REST API. For calling graph API it works.
More details and REST calls:
https://gist.github.com/nbelyh/ec17a4e398069e35c2a2a5dc4447fb2a
I'm not sure if it matters regarding the "on behalf flow" vs "app only" flow, but from my experiments, aquiring tokens for graph call isn't same as acquiring token for SP rest call.
Specifically, endpoints aren't the same. Here's how I execute rest request from insomnia:
I guess the key is to use https://accounts.accesscontrol.windows.net/{{ tenantId }}/tokens/OAuth/2 instead of https://login.microsoftonline.com/{{ tenantId }}/oauth2/v2.0/token
Thank to #JeremyKelley-Microsoft for the answer, just posting it here for others:
You need to use https://{tenant}/AllSites.Read (or https://{tenant}/.default) as a scope, it DOES work. The {tenant} is the customer's tenant. Here is the flow:
0. Application registration permissions
1. get the token from teams
microsoftTeams.authentication.getAuthToken() => <teams_token>
2. trade for graph token (on-behalf-of flow)
POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
client_id: <**your client id**>
client_secret: <**your client secret**>
grant_type: urn:ietf:params:oauth:grant-type:jwt-bearer
assertion: <**teams_token**>
requested_token_use: on_behalf_of,
scope: https://{tenant}/AllSites.Read
=> returns the <access_token>
3. use access token to access sharepoint REST API (get root site)
GET https://{tenant}/_api/web
headers:
authorization: "bearer " + <access_token>
In my opinion, SharePoint api could be accessed via access token through a http request. So if you've achieved the feature of calling graph api, I think the operation is similar. First, create azure ad application and create client secret, then you need to add application according to the api you need to call, finally, using client credential flow or any other suitable flow to generate the access token.
Or you mentioned 'not through the graph API' means what I said above? If I misunderstand someplace, pls point it out, and I think it's better to tell us which api you'd like to call.
==========================UPDATE============================
According to the link you provided in the comment, I found the apis in it(e.g GetSite: https://graph.microsoft.com/v1.0/sites/root) requires the api permission of 'graph->Sites.ReadWrite.All'(they are all graph apis), so when you generate the access token, you need to add it in the scope, and of courese, you need to add the api permission first in azure portal. Then you could call the api.

Get a msgraph access token using another access token

I created an Azure app for which I created custom scopes through the "Expose API" screen. I have a single page application that uses the code flow to login into the application requesting these custom scopes. On my ASP.NET Core web application, I added the authentication layer to use JWT as bearer. Works pretty well and I can secure my web APIs as expected.
Now, I also added API permissions for msgraph because I want to be able to create online meetings with it. The flow would be:
The user logs in using my custom scope audience
He sends a call to a secure web api to create something
Something is added to the database
An online meeting is created on behalf of the user
The "issue" is that the access token received by my web API is not valid for msgraph, I need to get one, on behalf of the user related to the access_token. However, I have no idea how to get a msgraph token using another access_token. I don't even know if that's possible.
However, if it's not possible, how am I supposed to create the online meeting from the .NET Core part of my application ?
Take a look at the On Behalf Flow, specifically the example "First case: Access token request with a shared secret". You can use your existing access token as the assertion parameter.
The following HTTP POST requests an access token and refresh token with user.read scope for the https://graph.microsoft.com web API.
//line breaks for legibility only
POST /oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&client_id=2846f71b-a7a4-4987-bab3-760035b2f389
&client_secret=BYyVnAt56JpLwUcyo47XODd
&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InowMzl6ZHNGdWl6cEJmQlZLMVRuMjVRSFlPMCJ9.eyJhdWQiOiIyODQ2ZjcxYi1hN2E0LTQ5ODctYmFiMy03NjAwMzViMmYzODkiLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3L3YyLjAiLCJpYXQiOjE0OTM5MjA5MTYsIm5iZiI6MTQ5MzkyMDkxNiwiZXhwIjoxNDkzOTI0ODE2LCJhaW8iOiJBU1FBMi84REFBQUFnZm8vNk9CR0NaaFV2NjJ6MFFYSEZKR0VVYUIwRUlIV3NhcGducndMMnVrPSIsIm5hbWUiOiJOYXZ5YSBDYW51bWFsbGEiLCJvaWQiOiJkNWU5NzljNy0zZDJkLTQyYWYtOGYzMC03MjdkZDRjMmQzODMiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJuYWNhbnVtYUBtaWNyb3NvZnQuY29tIiwic3ViIjoiZ1Q5a1FMN2hXRUpUUGg1OWJlX1l5dVZNRDFOTEdiREJFWFRhbEQzU3FZYyIsInRpZCI6IjcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0NyIsInV0aSI6IjN5U3F4UHJweUVPd0ZsTWFFMU1PQUEiLCJ2ZXIiOiIyLjAifQ.TPPJSvpNCSCyUeIiKQoLMixN1-M-Y5U0QxtxVkpepjyoWNG0i49YFAJC6ADdCs5nJXr6f-ozIRuaiPzy29yRUOdSz_8KqG42luCyC1c951HyeDgqUJSz91Ku150D9kP5B9-2R-jgCerD_VVuxXUdkuPFEl3VEADC_1qkGBiIg0AyLLbz7DTMp5DvmbC09DhrQQiouHQGFSk2TPmksqHm3-b3RgeNM1rJmpLThis2ZWBEIPx662pjxL6NJDmV08cPVIcGX4KkFo54Z3rfwiYg4YssiUc4w-w3NJUBQhnzfTl4_Mtq2d7cVlul9uDzras091vFy32tWkrpa970UvdVfQ
&scope=https://graph.microsoft.com/user.read+offline_access
&requested_token_use=on_behalf_of

Request to Graph API from Azure Functions

I am trying to understand how the request to the Graph API works from Azure Functions.
From the App Service of my Azure Functions, I generated the Active Directoy App, and from there, I add in the "API Permissions" to be able to do requests to the Graph API.
My doubts are the following:
1- When I access the endpoint of my AAD App (____.azurewebsites.net/.auth/me), could I use the access token that it returns to make the request to the Graph API? I have done some testing but it returns the following error:
CompactToken parsing failed with error code: 80049217
2- I have also tried to make a request to the endpoint: https://login.microsoftonline.com/[TENANT-ID]/oauth2/v2.0/token so that it should return an access token to make the request to the API of Graph. But I am getting the next error:
The request body must contain the following parameter: 'grant_type'
To do this tries, I am using Postman/Insomnia. But I am not very sure how to continue trying.
Thanks beforehand
1- When I access the endpoint of my AAD App
(____.azurewebsites.net/.auth/me), could I use the access token that
it returns to make the request to the Graph API?
Yes, you can. You need to add ["resource=https://graph.microsoft.com"] to additionalLoginParams under authsettings. Refer to this blog for more details.
2- I have also tried to make a request to the endpoint:
https://login.microsoftonline.com/[TENANT-ID]/oauth2/v2.0/token so
that it should return an access token to make the request to the API
of Graph. But I am getting the next error: The request body must
contain the following parameter: 'grant_type'
To call this endpoint, you will need some parameters, refer to this article for more details.
Another thing is that there are two kinds of API permissions, Delegated permission and Application permission. You should use Delegated permission instead of Application permission.
Reference:
Difference between Azure App Registration -‘Delegated’ and ‘Application’ Permission

Microsoft Graph API: how to get access token without browser

I would like to upload a given file to Sharepoint. I'm using the Microsoft Graph API.
The documentation follows this workflow:
1. If no token, redirect the user to the Microsoft signin page.
2. The user is then redirected to the application, with an access token
3. Use access token to have an authorization bearer
4. Do what you gotta do...
My problem is the sign-in part. I don't want my users to be redirected to the Microsoft signin page. I want my application to connect and get the access token in the background (with cURL or whatever).
How can I do that? Why is the "open in browser" necessary?
I tried to replicate the sign-in process, but all I get back is the HTML response from the signin page.
Thanks in advance.
Your application act as a single-tenant service or daemon app.
The documentation about this scenario is here : https://developer.microsoft.com/en-us/graph/docs/authorization/app_only
The application must be registered in the AzureAD directory corresponding to the Office365 tenant
A first request is made by passing the application unique identifier and secret key as registered in the directory. This request returns an access token
The access token can now be used in the Authorization header of the following request to the Microsoft Graph API.
This method (of using Client ID and Secret) works well but there are other ways which may be better suited for similar scenarios.
The one major thing which is missing in access token generated this way is a user, meaning the token only contains the identity of the OAuth application (client) which called it but is not associated with any user for the request.
This could have a couple of implications:
Since the token is not associated with a specific user you will not know who performed the operation. In your example, you would not know who uploaded the file (and other similar information may be missing).
Access token without users will not work at all for some methods. For those, you need a delegated token.
Creating a delegated token requires some effort, if you are interested you can find the details in my article:
Getting Access Token for Microsoft Graph Using OAuth REST API

Resources