2

I've created an API (Azure API App) and have enabled authentication/authtorization using Azure Active Directory (from the APP API . The app service is registered in AAD and everything looks good so far.

I've followed the steps in the the post below to generate a token, but the token does not seem to work.

var authContext = new AuthenticationContext("https://login.microsoftonline.com/<guid>/oauth2/authorize");
var credential = new ClientCredential("<clientId>", "<secret_from_aad>");
var result = (AuthenticationResult)authContext.AcquireTokenAsync("http://<api>.azurewebsites.net", credential).Result;
var token = result.AccessToken;

https://msdn.microsoft.com/en-us/library/azure/mt428036.aspx

The raw request looks like this:

GET https://<api>.azurewebsites.net/rest/v1/crm/surveys/all HTTP/1.1
Host: <api>.azurewebsites.net
Connection: close
Accept-Encoding: gzip,deflate
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJ<rest-of-token...>
Host: <api>.azurewebsites.net
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

The response is

HTTP/1.1 401 Unauthorized
Content-Length: 58
Content-Type: text/html
Server: Microsoft-IIS/8.0
WWW-Authenticate: Bearer realm="<api>.azurewebsites.net"
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=dd32cab21d0ca9541343a77c51d355d0781c0e0a4147a2166ecb955fe9d94a60;Path=/;Domain=<api>.azurewebsites.net
Date: Fri, 11 Nov 2016 11:20:49 GMT
Connection: close

You do not have permission to view this directory or page.

I've struggled for a while finding a way of generating a token without displaying a sign-in page and I'm not sure this is the best way (simple though...).

The system consuming the API must be able to generate a token programatically and send with the request.

I created a dummy AAD, a dummy App Service etc and put together this code sample:

class Program
    {
        static void Main(string[] args)
        {
            string response = HttpRequest();
            Console.ReadLine();
        }

        public static string HttpRequest()
        {
            string serviceURI = "https://apiappdemo.azurewebsites.net/api/values/";

            //Get the access token
            string token = GetToken();

            HttpWebRequest request = System.Net.WebRequest.Create(serviceURI) as System.Net.HttpWebRequest;
            request.KeepAlive = true;
            request.Method = "GET";
            request.ContentLength = 0;
            request.ContentType = "application/json";
            request.Headers.Add("Authorization", String.Format("Bearer {0}", token));

            using (HttpWebResponse httpResponse = request.GetResponse() as System.Net.HttpWebResponse) //Failing here... 401
            {
                using (StreamReader reader = new System.IO.StreamReader(httpResponse.GetResponseStream()))
                {
                    return reader.ReadToEnd();
                }
            }
        }

        public static string GetToken()
        {
            var authContext = new AuthenticationContext("https://login.microsoftonline.com/b37d6c4c-012f-450c-81c7-406b6b584348/oauth2/authorize");
            var credential = new ClientCredential("7ed0dccb-ade7-4a5e-b286-32b66eb929d1", "1bVIoJyMHsbuYsfuJ7or6krbKvWw3kpKfp69jsQuilw=");
            var result = (AuthenticationResult)authContext.AcquireTokenAsync("https://apiappdemo.azurewebsites.net", credential).Result;
            return result.AccessToken;
        }
    }

Any ideas what might be wrong?

Regards, Mike

Mike
  • 145
  • 2
  • 10

2 Answers2

3

To make the token works for the app service which protected by Azure AD, we need to use the Advanced managed mode( refer here).

We would use two apps reigster in the Azure AD, first is used to protect the app service. And second is used as client to request the resrouce. And we need to specify the allowed token audiences which is the app id URI(first app) for the app. Here is an figure for your reference: enter image description here

Then we can use the second app as client to accquire the token for the app configed for the app service. And make sure that the resrouce you sepcified in AcquireTokenAsync method is the audience config in preview setting.

Fei Xue
  • 14,369
  • 1
  • 19
  • 27
  • Not sure I follow you here, why would I need two apps and what would the other app actually be? – Mike Nov 14 '16 at 08:44
  • There are two concepts in Azure. First is the resource which need to be protected. Second is the client which need to access the protected resource. The first app represents the resource when you config it using the authentication/authorization feature for the app service. Then second app represents the client you used its client id, client secret and first app's app id URI(which will be issued as the `aud` claim in the token) to acquire the token for the first app. – Fei Xue Nov 14 '16 at 10:14
0

Replace this line:

authContext.AcquireTokenAsync("https://apiappdemo.azurewebsites.net"
                                   ,credential).Result; 

with:

authContext.AcquireTokenAsync("7ed0dccb-ade7-4a5e-b286-32b66eb929d1"
                                  ,credential).Result; 

Use your client id as resource id

pirho
  • 11,565
  • 12
  • 43
  • 70
upzone
  • 9
  • 1
  • 1
    While this may answer the question, it is better to explain the essential parts of the answer and possibly what was the problem with OPs code. – pirho Dec 11 '17 at 08:46