Reputation: 4526
Let's say I have configured two 'applications' in Azure AD. One is a Web API called 'A' and another is a native windows application called 'B'. The user downloads 'B' from the Windows Store and logs into Azure AD using their Office 365 credentials. Works great. They get an token.
Can I use that token and attach it to REST API calls to the API application 'A'?
EDIT: So I've made what I will call some progress. I am able to acquire a token for the Web API but I am still getting 'unauthorized' and it is currently giving me an interactive login in order to acquire the token for the Web API.
Here is more detail about my configuration:
Now for the code.
When I authenticate my UWP app I am doing this:
static string clientId = "{123}";
static string authority = "https://login.windows.net/{tenant_id}";
static string uri = string.Format("ms-appx-web://Microsoft.AAD.BrokerPlugin/{0}", WebAuthenticationBroker.GetCurrentApplicationCallbackUri().Host.ToUpper());
private AuthenticationContext authContext = new AuthenticationContext(authority);
private async void AttemptLogin()
{
WebAccountProvider wap = await WebAuthenticationCoreManager.FindAccountProviderAsync("https://login.microsoft.com", authority);
WebTokenRequest wtr = new WebTokenRequest(wap, string.Empty, clientId);
wtr.Properties.Add("resource", "https://graph.windows.net");
// there is no recorded user. let's start a sign in flow without imposing a specific account.
WebTokenRequestResult wtrr = await WebAuthenticationCoreManager.RequestTokenAsync(wtr);
if (wtrr.ResponseStatus == WebTokenRequestStatus.Success)
{
userAccount = wtrr.ResponseData[0].WebAccount;
token = wtrr.ResponseData[0].Token;
}
if (userAccount != null)
{
OnUserSignedIn();
}
else
{
// we got bigger fish to fry!
}
}
private void OnUserSignedIn()
{
var redirectUri = new Uri(uri);
AuthenticationResult authResult = await authContext.AcquireTokenAsync("https://api.foo.com", clientId, redirectUri);
// just some junk code to call the Web API
var accountId = ApiClientHelper.AccountIdentifier;
var client = ApiClientHelper.GetClient();
client.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authResult.AccessTokenType, authResult.AccessToken);
try
{
var allCustomers = await client.Customers.GetAllWithOperationResponseAsync(accountId);
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
So the funny thing is when I obtain the token for 'https://graph.windows.net' inside the AttemptLogin method and when I obtain the token for 'https://api.foo.com' the token string value is IDENTICAL.
The status code I get back is 'Unauthorized'.
Upvotes: 2
Views: 3397
Reputation: 9153
It doesn't work. For the ID_TOKEN, the aud
claim, that is the App ID
or Client ID
, should be matched.
Identifies the intended recipient of the token. In id_tokens, the audience is your app's Application ID, assigned to your app in the Azure portal. This value should be validated. The token should be rejected if it fails to match your app's Application ID.
ref: https://learn.microsoft.com/en-us/azure/active-directory/develop/id-tokens#payload-claims
Upvotes: 0
Reputation: 4526
I figured out why it wasn't working. First, I was using the authentication through the azure portal rather than setting up owin in my app. Second, I was missing a critical nuget package that is super critical but not easy to know what's wrong. Microsoft.owin.host.systemweb is required for the startup.cs code to execute. Without it you only get unauthorized messages and no other explanation.
Upvotes: 0
Reputation: 7394
If you are a native app, there is no such a thing as "logging in". The operation you perform is always requesting a token for some resource. In the process of acquiring such a token, the end user will likely have to perform a sign in - but from the application point of view, the operation is the acquisition of a token. Hence: if in your token acquisition operation you ask for a token for your API, you'll get the user to go through the sign in gesture AND you will get a token for your API. Even if you initially get a token for a different API - the refresh token you get together with the first access token has the capability of obtaining access tokens for all the APIs that your native client is registered to request access to, hence you can get a new token for your API without any extra user interaction.
Upvotes: 0