Reputation: 754
I'm building an API which is called by a SPA (angular). The user is authenticated using Azure AD and the API uses AzureAdBearer for its authentication.
public void ConfigureServices(IServiceCollection services)
{
[...]
services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
.AddAzureADBearer(options => Configuration.Bind("AzureActiveDirectory", options));
[...]
}
I need to call Graph API and would like to do it on behalf of the connected user.
I have seen this question: Accessing MS Graph from API on behalf of user currently signed in to separate web client which really looks like the solution I try to implement.
I try to replicate this proposed solution here: https://joonasw.net/view/azure-ad-on-behalf-of-aspnet-core
As I understand it I need to configure the JwtBearer settings, but how can I call the .AddJwtBearer
if I already have .AddAzureADBearer
.
AddAzureADBearer itself calls the AddJwtBearer (cf. here)
I created a secret in the app registration of my API and used it to implement a IAuthenticationProvider
to get the token on behalf of the user, but I get an error AADSTS65001.
I guess this is because I'm missing the AddJwtBearer configuration to save the user's token in cache, but I'm not really sure.
I don't really understand the solution proposed on the question here.
UPDATE
Thanks to Tony Ju's answer I have been able to authenticate. But when I call graph api I get Authorization_RequestDenied Insufficient privileges to complete the operation.
I don't know why but can't manage to configure Fiddler properly to capture the request to Azure AD. I enabled ADAL logs and got this
[Information][False]: 2020-01-09T09:11:12.1104926Z: AdalLoggerBase.cs: ADAL PCL.CoreCLR with assembly version '5.2.4.0', file version '5.2.4.0' and informational version '5.2.4' is running...
[Information][True]: 2020-01-09T09:11:12.1183853Z: AdalLoggerBase.cs: === Token Acquisition started:
Authority: https://login.microsoftonline.com/d6397071-8e3e-45d2-a2d6-36698acf0fea/
Resource: https://graph.microsoft.com
ClientId: [...]
CacheType: Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache (0 items)
Authentication Target: User
[Verbose][False]: 2020-01-09T09:11:12.1395851Z: AdalLoggerBase.cs: Username provided in user assertion - False
[Verbose][False]: 2020-01-09T09:11:12.5277838Z: AdalLoggerBase.cs: Loading from cache.
[Verbose][False]: 2020-01-09T09:11:12.5395969Z: AdalLoggerBase.cs: Looking up cache for a token...
[Information][False]: 2020-01-09T09:11:12.5467711Z: AdalLoggerBase.cs: No matching token was found in the cache
[Information][False]: 2020-01-09T09:11:12.5706903Z: AdalLoggerBase.cs: No matching token was found in the cache
[Verbose][False]: 2020-01-09T09:11:12.5736362Z: AdalLoggerBase.cs: Looking up cache for a token...
[Information][False]: 2020-01-09T09:11:12.5764248Z: AdalLoggerBase.cs: No matching token was found in the cache
[Verbose][False]: 2020-01-09T09:11:12.5804061Z: AdalLoggerBase.cs: Either a token was not found or an exception was thrown.
[Verbose][False]: 2020-01-09T09:11:12.5844932Z: AdalLoggerBase.cs: Cannot invoke the broker directly, may require install ...
[Verbose][False]: 2020-01-09T09:11:12.5891021Z: AdalLoggerBase.cs: Check and AcquireToken using broker
[Verbose][False]: 2020-01-09T09:11:12.5919785Z: AdalLoggerBase.cs: Broker invocation is NOT required
[Verbose][False]: 2020-01-09T09:11:12.9510499Z: AdalLoggerBase.cs: Storing token in the cache...
[Verbose][False]: 2020-01-09T09:11:12.9583491Z: AdalLoggerBase.cs: An item was stored in the cache
[Information][True]: 2020-01-09T09:11:12.9917987Z: AdalLoggerBase.cs: === Token Acquisition finished successfully. An access token was returned: Expiration Time: 09/01/2020 10:10:54 +00:00Access Token Hash: GtaeLmKsVSj82umwxVcgghW3/X/N2hKhaxyb7XBbBU0=
User id: 3b224748-42c5-406d-a0c0-e9c9f5238361
I used this code to get the token:
var userAssertion = new UserAssertion(token, "urn:ietf:params:oauth:grant-type:jwt-bearer", user.upn);
var authContext = new AuthenticationContext(_aadOptions.Authority);
var clientCredential = new ClientCredential(_aadOptions.ClientId, _aadOptions.ClientSecret);
var result = await authContext.AcquireTokenAsync("https://graph.microsoft.com", clientCredential, userAssertion);
I tried to rewrite it for MSAL instead of ADAL but didn't success. Should the scope needed for the graph api request should be in the initial user login or do we expand the scope in the on-behalf-of user request token ?
Upvotes: 0
Views: 1494
Reputation: 27578
I guess this is because I'm missing the AddJwtBearer configuration to save the user's token in cache, but I'm not really sure.
You can simply set breakpoint in IAuthenticationProvider
to confirm whether it gives token via string token = await httpContext.GetTokenAsync("access_token");
. I think it should be there , if there is no access token , you can try below ways :
Override the JwtBearerOptions :
services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
.AddAzureADBearer(options => Configuration.Bind("AzureAd", options));
services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options =>
{
options.SaveToken = true;
options.Events = new JwtBearerEvents
{
OnMessageReceived = async (ctx) =>
{
Console.WriteLine(ctx.Token);
},
OnTokenValidated = async (ctx) =>
{
Console.WriteLine("BreakPoint");
},
};
});
Directly use AddJwtBearer
extension .
If using Azure AD v1.0 , you can click here for how to config the On-Behalf-Of flow applications include how to configure known client applications . Compare the request your application sent with the document shows . If using Azure AD v2.0 , you can check this document .
Upvotes: 1
Reputation: 15629
Please check the permissions of your web api permissions. Go to App registrations->find your web api app->permissions.
If you have permissions which need admin consent, you need to grant admin consent for your tenant.
If you don't have any permissions which need admin consent, try to grant user consent by sending a request like the following example
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=cbc32712-****-4532-802d-303998a6e712
&response_type=code
&redirect_uri=http://localhost
&response_mode=query
&scope=https://graph.microsoft.com
&state=12345
Upvotes: 1