restsingle-sign-onwin-universal-appazure-active-directoryazure-api-apps

Can I use a token issued to one application with another application in Azure AD SSO?


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'.


Solution

  • 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.