I'm trying to call an Azure Hosted WebAPI from a site-based WebService.
The site based service is an adal-angluar SPA which must then call out to a rest API hosted in Azure.
The bearer token from AAD is successfully passed to the site based web API, and this then must get a new token on behalf of the user to call the downstream API, as per this example:
https://github.com/Azure-Samples/active-directory-dotnet-webapi-onbehalfof
The downstream API in the example is https://graph.windows.net. And this is passed into the AcquireTokenAsync call as the resourceId.
In my case, the downstream API is an Azure app that I am writing, so I have full control over it.
The problem I have is 'invalid_grant' is returned from the AcquireTokenAsync call in my site based api that is trying to get a new token on behalf of the logged in user.
The site based web app has an appid created in Azure, and attempts to get a new token as follows:
var appId = ConfigurationManager.AppSettings["ActiveDirectoryApplicationId"];
var appKey = ConfigurationManager.AppSettings["ActiveDirectoryApplicationKey"];
var aadInstance = ConfigurationManager.AppSettings["ActiveDirectoryInstance"];
var tenant = ConfigurationManager.AppSettings["ActiveDirectoryTenant"];
var onboardingResourceId = ConfigurationManager.AppSettings["OnboardingApplicationResourceId"];
var clientCredential = new ClientCredential(appId, appKey);
var bootstrapContext =
ClaimsPrincipal.Current.Identities.First().BootstrapContext as
System.IdentityModel.Tokens.BootstrapContext;
var userName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn) != null ? ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value : ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value;
var userAccessToken = bootstrapContext.Token;
var userAssertion = new UserAssertion(bootstrapContext.Token, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName);
var authority = string.Format(System.Globalization.CultureInfo.InvariantCulture, aadInstance, tenant);
var userId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
var authContext = new AuthenticationContext(authority, new TokenCache());
var result = await authContext.AcquireTokenAsync(onboardingResourceId, clientCredential, userAssertion);
var accessToken = result.AccessToken;
return accessToken;
So my questions are, what security needs to be implemented in Azure to get the token? I've read that the Application manifest of the downstream API needs to be updated to include the site based app as a "knownClientApplication". Is that correct?
What should my resourceId look like for my downstream web api?
Can I test all of this without deploying my downstream Web Api to Azure? I want to be able to debug all of this locally including the security.
Thanks.
aud
), like sohttps://onboardingResourceId.example.com/
. – evilSnobu