简体   繁体   中英

Azure Active Directory Graph API - access token for signed in user

Azure Active Directory Graph Api allows you to perform operations on the signed in user.

https://msdn.microsoft.com/en-us/library/azure/ad/graph/api/signed-in-user-operations

I don't know how to obtain an access token for Graph API on behalf of the signed in user.

I can obtain an access token for my web application, but this is not on behalf of a particular user:

var authContext = new AuthenticationContext(authorityString);
var result = await authContext.AcquireTokenAsync
             (
                "https://graph.windows.net",
                 clientCredential  // Application ID, application secret
             );
string accessToken = result.Token;

Also, when the user logs on I am given an Authorization Code (via the AuthorizationCodeReceived notification). I can convert this Authorization Code to an access token. This might be an access token for the user, but it is not recognized by Graph Api. (Come to think of it, I don't know what this access token is good for...)

var authContext = new AuthenticationContext(authorityString);
var result = await authContext.AcquireTokenByAuthorizationCodeAsync
             (
                  authorizationCode,
                  redirectUri, // eg http://localhost:56950/
                  clientCredential // Application ID, application secret
             );
string accessToken = result.AccessToken;

Using the first access token, I can run queries on my Active Directory tenant. For example, the call https://graph.windows.net/thisisnotmydomain.onmicrosoft.com/users?api-version=1.6 gives me a list of users.

But if try the URL: https://graph.windows.net/me?api-version=1.6 , I get this result:

   {
     "odata.error": {
                       "code": "Request_ResourceNotFound",
                      "message": {
                                   "lang": "en",
                                   "value": "Resource not found for the segment 'me'."
                                  }
                    }
  }

Which makes sense, as I never specified the user. If I use the access token obtained by AcquireTokenByAuthorizactionCodeAsync I receive an error message "Access Token missing or malformed." Clearly, this is not a graph API access token.

How do I get an access token for Graph API which works for the signed in user?

What you have done there is client credentials grant flow. It is used by apps to access APIs not on behalf of users, but the app itself. So if your app has rights to read data from the API without user context, this is what you would use for that.

However, to make calls in a user context, you need to do something differently.

If this is a web app, you would probably use authorization code grant flow, in which the user's browser gets redirected to Azure AD. After giving consent to your app, they get forwarded back to your app with an authorization code. You can then exchange this code for an access token using the code and your client id and secret. Here is a sample app that does that: https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-openidconnect , focus especially here: https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-openidconnect/blob/master/TodoListWebApp/App_Start/Startup.Auth.cs .

If this is a native app, you will have to pop up a browser to do authentication. This is automated by ADAL, so you don't need to do much. Here is a sample UWP app for that: https://github.com/Azure-Samples/active-directory-dotnet-windows-store . Focus especially here: https://github.com/Azure-Samples/active-directory-dotnet-windows-store/blob/master/TodoListClient/MainPage.xaml.cs#L108 . There is also a sample WPF app here: https://github.com/Azure-Samples/active-directory-dotnet-native-desktop . What the WPF app does can also be applied to console apps, winforms apps etc.

You can find all the samples here: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-code-samples .

Feel free to ask in a comment if you have more questions :)

PS Another choice would be the password grant flow, in which you send a username, password, client id and secret to Azure AD to get an access token. There are numerous problems that can come up with this approach so I don't recommend it. If you can use the ones where you present the login screen to the user in a browser window, use them.


The problem with the second call with the authorization code was that it didn't specify a resource URI. Making the call like this fixed the problem:

var result = await authContext.AcquireTokenByAuthorizationCodeAsync
         (
              authorizationCode,
              redirectUri, // eg http://localhost:56950/
              clientCredential, // Application ID, application secret
              "https://graph.windows.net/"
         );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM