在 Azure 中调用 Web api 时不记名令牌不起作用
Bearer token not working when calling web api in Azure
我在从 Azure 中的 Web 应用程序获取 API 应用程序调用时遇到问题。这是事物的结构 -
- Asp.Net 受 Azure AD 身份验证保护的核心 1.1 Web 应用程序 - 运行 在本地使用 Kestrel
Web 应用程序的 StartUp.cs 具有以下用于将令牌获取到 Web 的代码 api
app.UseCookieAuthentication();
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
ClientId = ClientId, //Client Id of my current web app
ClientSecret = ClientSecret, //ClientSecret of my current web app
Authority = "https://login.microsoftonline.com/tenantguid", CallbackPath = Configuration[Constants.ApplicationProxyCallbackPath],
ResponseType = OpenIdConnectResponseType.CodeIdToken,
Events = new OpenIdConnectEvents
{
OnAuthorizationCodeReceived = OnAuthorizationCodeReceived,
OnRemoteFailure = OnAuthenticationFailed
}
});
对于 OnAuthorizationCodeReceived 方法,这是我的代码
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context)
{
string userObjectId = (context.Ticket.Principal.FindFirst(Constants.ClaimsSchemaUri))?.Value;
ClientCredential clientCred = new ClientCredential(ClientId, ClientSecret);
AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectId, context.HttpContext.Session));
AuthenticationResult authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(
context.ProtocolMessage.Code,
new Uri(context.Properties.Items[OpenIdConnectDefaults.RedirectUriForCodePropertiesKey]),
clientCred,
WebAPIClientId);
}
使用上面的代码我可以成功获取不记名令牌。
Controller class 我调用 WebApi
Task<string> results = null;
string resultSet = String.Empty;
AuthenticationResult authResult = null;
string userObjectID = (currentUser.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier"))?.Value;
AuthenticationContext authContext = new AuthenticationContext(Startup.Authority, new NaiveSessionCache(userObjectID, current.Session));
ClientCredential credential = new ClientCredential(Startup.ClientId, Startup.ClientSecret);
authResult = await authContext.AcquireTokenSilentAsync(Startup.SearchAPIClientId, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
//var callerIdentity = currentUser.Identity as WindowsIdentity;
HttpClientHandler handler = null;
//Setup async action
Action action = () => {
handler = new HttpClientHandler() { AllowAutoRedirect = true };
//Setup for windows authentication
var client = new HttpClient(handler);
//Add common http headers
client.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate");
client.DefaultRequestHeaders.Add("Accept-Language", "en-US,en;q=0.8");
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
results = client.GetStringAsync("https://myapi.azurewebsites.net/api/search/");
};
action.Invoke();
resultSet = await results as string;
对 API 的调用被重定向到 login.microsftonline.com,这意味着我的令牌不被理解。
- Web API 使用代码中的 OpenIdConnect 包通过 Azure 身份验证进行保护,就像上面的 Web 应用程序代码一样。
我看了几个相关的帖子,但没有任何效果。
更新 1 - 更新 Web API 以使用 JWTBearer 身份验证
现在,我在 Web App 中获取的不记名令牌能够成功地向 Web API 验证我的身份。
我的网站 API 预计会调用另一个自定义 API,该自定义 API 也受 Azure AD 身份验证保护。我正在寻找相同的令牌,但为了启动我在为其他自定义 API 使用获取令牌时遇到问题。它在没有任何消息的情况下抛出 Internal Server 500。有什么想法吗?
更新 2 - 详细错误
在尝试为第三个 api 获取令牌时,出现以下异常 -
"AADSTS50105: Application 'source client id guid' is not assigned to a role for the application 'target client id guid'."
问题已解决,这是我必须做的。
API 应用程序身份验证更改
- 将身份验证方案更改为通过 JWTBearer
- 这让我可以接受来自 Web 应用程序的不记名令牌,现在 Web 应用程序可以根据需要进行应用程序身份验证Api
API 应用程序代码更改
- 由于 API 应用程序正在调用另一个下游 API 应用程序,我不得不使用 AcquireTokenAsync 传递以下详细信息 - ClientId、ClienCredentials 和先前从 Web 应用程序收到的访问令牌。此令牌用于构造 UserAssertion
通过上述更改,从 Web 应用程序调用 --> API 应用程序 --> 下游 API 应用程序工作正常。
我在从 Azure 中的 Web 应用程序获取 API 应用程序调用时遇到问题。这是事物的结构 -
- Asp.Net 受 Azure AD 身份验证保护的核心 1.1 Web 应用程序 - 运行 在本地使用 Kestrel
StartUp.cs 具有以下用于将令牌获取到 Web 的代码 api
app.UseCookieAuthentication();
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
ClientId = ClientId, //Client Id of my current web app
ClientSecret = ClientSecret, //ClientSecret of my current web app
Authority = "https://login.microsoftonline.com/tenantguid", CallbackPath = Configuration[Constants.ApplicationProxyCallbackPath],
ResponseType = OpenIdConnectResponseType.CodeIdToken,
Events = new OpenIdConnectEvents
{
OnAuthorizationCodeReceived = OnAuthorizationCodeReceived,
OnRemoteFailure = OnAuthenticationFailed
}
});
对于 OnAuthorizationCodeReceived 方法,这是我的代码
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context)
{
string userObjectId = (context.Ticket.Principal.FindFirst(Constants.ClaimsSchemaUri))?.Value;
ClientCredential clientCred = new ClientCredential(ClientId, ClientSecret);
AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectId, context.HttpContext.Session));
AuthenticationResult authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(
context.ProtocolMessage.Code,
new Uri(context.Properties.Items[OpenIdConnectDefaults.RedirectUriForCodePropertiesKey]),
clientCred,
WebAPIClientId);
}
使用上面的代码我可以成功获取不记名令牌。
Controller class 我调用 WebApi
Task<string> results = null; string resultSet = String.Empty; AuthenticationResult authResult = null; string userObjectID = (currentUser.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier"))?.Value; AuthenticationContext authContext = new AuthenticationContext(Startup.Authority, new NaiveSessionCache(userObjectID, current.Session)); ClientCredential credential = new ClientCredential(Startup.ClientId, Startup.ClientSecret); authResult = await authContext.AcquireTokenSilentAsync(Startup.SearchAPIClientId, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId)); //var callerIdentity = currentUser.Identity as WindowsIdentity; HttpClientHandler handler = null; //Setup async action Action action = () => { handler = new HttpClientHandler() { AllowAutoRedirect = true }; //Setup for windows authentication var client = new HttpClient(handler); //Add common http headers client.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"); client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate"); client.DefaultRequestHeaders.Add("Accept-Language", "en-US,en;q=0.8"); client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken); results = client.GetStringAsync("https://myapi.azurewebsites.net/api/search/"); }; action.Invoke(); resultSet = await results as string;
对 API 的调用被重定向到 login.microsftonline.com,这意味着我的令牌不被理解。
- Web API 使用代码中的 OpenIdConnect 包通过 Azure 身份验证进行保护,就像上面的 Web 应用程序代码一样。
我看了几个相关的帖子,但没有任何效果。
更新 1 - 更新 Web API 以使用 JWTBearer 身份验证 现在,我在 Web App 中获取的不记名令牌能够成功地向 Web API 验证我的身份。
我的网站 API 预计会调用另一个自定义 API,该自定义 API 也受 Azure AD 身份验证保护。我正在寻找相同的令牌,但为了启动我在为其他自定义 API 使用获取令牌时遇到问题。它在没有任何消息的情况下抛出 Internal Server 500。有什么想法吗?
更新 2 - 详细错误 在尝试为第三个 api 获取令牌时,出现以下异常 - "AADSTS50105: Application 'source client id guid' is not assigned to a role for the application 'target client id guid'."
问题已解决,这是我必须做的。
API 应用程序身份验证更改
- 将身份验证方案更改为通过 JWTBearer
- 这让我可以接受来自 Web 应用程序的不记名令牌,现在 Web 应用程序可以根据需要进行应用程序身份验证Api
API 应用程序代码更改
- 由于 API 应用程序正在调用另一个下游 API 应用程序,我不得不使用 AcquireTokenAsync 传递以下详细信息 - ClientId、ClienCredentials 和先前从 Web 应用程序收到的访问令牌。此令牌用于构造 UserAssertion
通过上述更改,从 Web 应用程序调用 --> API 应用程序 --> 下游 API 应用程序工作正常。