Accessing Microsoft Graph api after authenticating into my own application - azure

I have my own application, call it appA, that I registered with Azure Active Directory. I authenticate users into appA using the authorization code grant process outlined here: https://learn.microsoft.com/en-us/azure/active-directory/develop/v1-protocols-oauth-code#request-an-authorization-code. I specify the resource the Jwt to be good for as appA during this process. After a user enters credentials, I get an authorization code, then use that code to get a Jwt and a refresh token good for appA.
Once users are authenticated into my application, I want to inspect the groups they are in for role based access control. The groups are not returned in the token because each user has more than 5 groups.
This forces me to make an additional call to the graph Api to get groups for a certain user. But, in order to do this, I need to use the refresh token and specify the https://graph.microsoft.com as the resource to the token refresh endpoint. The token I am returned is now good to make requests against the graph Api.
My question is: how can I make the call inside appA to get the token good for the graph api? It seems like I will have to juggle multiple Jwts at the same time and I am having a hard time conceptualizing how this will work.

how can I make the call inside appA to get the token good for the
graph api?
You could directly request the token for the MS graph API, which just needs to change the resource value for MS graph API (https://graph.microsoft.com) in the OAuth 2.0 code grant flow.
In the Request an authorization code
https://login.microsoftonline.com/{tenant}/oauth2/authorize?
client_id=<client-id-value>
&response_type=code
&redirect_uri=<redirect-uri-value>
&response_mode=query
&resource=https://graph.microsoft.com
&state=12345
The response like this:
In the Use the authorization code to request an access token
POST /{tenant}/oauth2/token HTTP/1.1
Host: https://login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&client_id=<client-id-value>
&code=<code-value>
&redirect_uri=<redirect-uri-value>
&resource=https://graph.microsoft.com
&client_secret=<key-value>
The response like this:
Then you could use the access_token to make requests against the MS graph API.

Related

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

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

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

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

Is OAuth 2.0 just for authorizing applications and not users?

When I first heard of OAuth was in ASP.NET Web API applications and I've used it as means of authorizing users to access resources on a RESTful API. By the time I felt I was using it right, but right now I think I got the idea wrong and this is the subject of this question.
At the time, I used OAuth in the following way: on the API there was a token endpoint to issue tokens. I created a login page in a SPA and posted the username and password to the token endpoint with a grant type password and the token that came back I started sending with each request.
When the request had the Authorization: Bearer [token] header with a token issued with some username on the login page I understood the request was being done "with the user logged in" and so I could authorize access to resources.
Studying OAuth deeper my conclusion is that my usage of OAuth was completely mistaken.
My understanding now is that OAuth is just for authorizing applications and not users. In that case when we make a request with the Authorization: Bearer [token] header we are saying identifiying to the resource server that the client making the request has been authorized to access the resource, but we are not saying anything about the user?
In that case, with OAuth we just can say what resources client applications can access but we have no information to decide whether the user is allowed or not to the resource? Because of that my initial usage is truly wrong right?
OAuth 2.0 can be used for authorizing a client (an application) to call an API. This authorization is done via an authorization grant.
The grant is given by the resource owner in the case of authorization code, implicit and resource owner password grant through authentication of the user with the authorization server and clicking accept on a consent screen.
The first two grant flows are interactive and require an agent that understands HTTP (redirection) responses.
Most authorization servers also support the client credentials grant. In this case, there's no user involved and a pre-registered client (application) uses its own client-id and secret to authenticate with the authorization server.
Which grant flow to use depends on the type of client you use and who owns the resource the client needs to access. I describe the differences in my answer here.

OpenID Connect - Implicit Flow with Javascript app using JWT to authenticate with a REST API

I am developing a Javascript app + REST API.
I want users to authenticate with the app (and underlying REST API) via an OpenID Connect Provider for SSO purposes.
Using the Implicit flow I can get an ID token (JWT) identifying the user to my javascript app. I was hoping that I could then send this JWT in the Authorize header in requests to my REST API to authenticate the user. However, the problem with this approach is that the 'aud' field of the JWT won't be for the REST API server, it would be for the javascript app.
Does this mean Implicit flow is not suitable for my use case, or am I missing something?
Implicit Flow is designed for untrusted clients (such as JavaScript) to obtain identity and also (optionally) access tokens.
With OpenID Connect your authentication request must contain id_token in the response_type parameter, but it can also include token in the parameter too. See 3.2.2.1 in the spec (http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthRequest)
e.g.
GET /authorize?
response_type=id_token%20token
&client_id=s6BhdRkqt3
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&scope=openid%20profile
&state=af0ifjsldkj
&nonce=n-0S6_WzA2Mj HTTP/1.1
Host: server.example.com
id_token means that you will get back the ID token which you have mentioned. The token means that it will also return you an access token, which is what you would use for accessing your REST api.

Resources