ASP.NET Web API 和 OpenID 连接:如何从授权代码获取访问令牌
本文关键字:授权 代码 访问令牌 获取 Web NET API 连接 OpenID ASP | 更新日期: 2023-09-27 18:17:34
我尝试让OpenID Connect运行...我的Web API的用户设法获得了OpenID Connect Provider的授权代码。我应该如何将此代码传递给我的 ASP.NET Web API?如何配置 OWIN 中间件,以便可以使用授权代码获取访问令牌?
更新:SPA 使用 AJAX 与我的 Web 服务(ASP.NET Web API(进行通信。在我的网络服务中使用 OWIN 中间件。我将OpenIDConnect设置为身份验证机制。首次调用 Web 服务时,它成功地将用户重定向到 OpenID Connect 提供程序的登录页面。用户可以登录并因此获得授权码。AFAIK 此代码现在可以(由我的 Web 服务(用于访问令牌。但是,我不知道如何将此代码返回到我的 Web 服务(这是使用标头完成的吗?(,然后配置什么以获取访问令牌。我想我可以手动调用令牌端点,但我想利用 OWIN 组件。
BenV已经回答了这个问题,但还有更多需要考虑。
class partial Startup
{
public void ConfigureAuth(IAppBuilder app)
{
// ...
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = authority,
Notifications = new OpenIdConnectAuthenticationNotifications() {
AuthorizationCodeReceived = (context) => {
string authorizationCode = context.Code;
// (tricky) the authorizationCode is available here to use, but...
return Task.FromResult(0);
}
}
}
}
}
两个问题:
- 首先,
authorizationCode
会很快过期。存储它是没有意义的。 - 第二个问题是,只要 authorizationCode 没有过期并存储在会话中,
AuthorizationCodeReceived
事件就不会因任何页面重新加载而被触发。
您需要做的是调用AcquireTokenByAuthorizationCodeAsync
它将缓存它并在TokenCache.DefaultShare
中正确处理:
AuthorizationCodeReceived = (context) => {
string authorizationCode = context.Code;
AuthenticationResult tokenResult = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, new Uri(redirectUri), credential);
return Task.FromResult(0);
}
现在,在每次调用资源之前,调用AcquireTokenSilentAsync
以获取访问令牌(它将使用 TokenCache 或静默使用 refreshToken (。如果令牌已过期,它将引发AdalSilentTokenAcquisitionException
异常(调用访问代码续订过程(。
// currentUser for ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")
AuthenticationResult authResult = await context.AcquireTokenSilentAsync(resourceUri, credential, currentUser);
如果缓存了令牌,则调用AcquireTokenSilentAsync
非常快。
看起来推荐的方法是使用 AuthorizationCodeReceived
事件将身份验证代码交换为访问令牌。 维托里奥有一个博客条目,概述了整个流程。
下面是 GitHub 上此示例应用的示例,其中包含用于设置此设置的Startup.Auth.cs
代码:
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = Authority,
Notifications = new OpenIdConnectAuthenticationNotifications()
{
AuthorizationCodeReceived = (context) =>
{
var code = context.Code;
ClientCredential credential = new ClientCredential(clientId, appKey);
string tenantID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
AuthenticationContext authContext = new AuthenticationContext(string.Format("https://login.windows.net/{0}", tenantID), new EFADALTokenCache(signedInUserID));
AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceID);
return Task.FromResult(0);
},
...
}
注意:仅当授权真正发生时,才会调用一次 AuthorizationCodeReceived
事件。如果已生成并存储身份验证代码,则不会调用此事件。您必须注销或清除 Cookie 才能强制发生此事件。
这现在内置于 Microsoft.Owin 4.1.0 或更高版本中。可以使用SaveTokens
使id_token可用,然后RedeemCode
获取访问令牌并使其可用
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
ClientSecret = "redacted",
RedirectUri = postLogoutRedirectUri,
//This allows multitenant
//https://github.com/Azure-Samples/guidance-identity-management-for-multitenant-apps/blob/master/docs/03-authentication.md
TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false
},
Notifications = new OpenIdConnectAuthenticationNotifications()
{
AuthenticationFailed = (context) =>
{
return Task.FromResult(0);
}
},
SaveTokens = true,
// Required for the authorization code flow to exchange for tokens automatically
// using this means you will need to provide RedirectUri and ClientSecret
RedeemCode = true
}
);
然后,可以通过 HttpContext 对象访问令牌
var result = Request.GetOwinContext().Authentication.AuthenticateAsync("Cookies").GetAwaiter().GetResult();
string idToken = result.Properties.Dictionary["id_token"];
string accessToken = result.Properties.Dictionary["access_token"];
来源:如何使用 owin 和 Mvc 5 从 httpcontext 获取访问令牌
您需要绕过默认的 owin 验证来执行自定义授权:
new OpenIdConnectAuthenticationOptions
{
...,
TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuer = false
},
TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name", RoleClaimType = ClaimTypes.Role },
这行代码解决了我的问题。我们需要验证颁发者是否为假。