问题
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
回答1:
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:
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.
回答2:
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
来源:https://stackoverflow.com/questions/40545783/azure-api-apps-access-token-adal-not-working