我尝试让OpenID Connect运行...我的Web API用户设法获得OpenID Connect Provider的授权码。我应该如何将此代码传递给我的ASP.NET Web API?我如何配置OWIN中间件,以便我可以使用授权码获取访问令牌?
更新: SPA使用AJAX与我的Web服务(ASP.NET Web API)进行通信。在我的Web服务中使用OWIN Middleware。我将OpenIDConnect设置为身份验证机制。首次调用Web服务时,它成功将用户重定向到OpenID Connect Provider的登录页面。用户可以登录并获得授权码。 AFAIK此代码现在可以(通过我的Web服务)用于访问令牌。但是,我不知道如何将此代码返回到我的Web服务(这是使用标头完成吗?)然后配置什么来获取访问令牌。我想我可以手动调用令牌端点,但我想利用OWIN组件。
答案 0 :(得分:11)
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
将很快过期。存储它没有任何意义。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
来获取accessToken(它将使用TokenCache或静默使用refreshToken)。如果令牌已过期,则会引发AdalSilentTokenAcquisitionException
异常(调用访问代码续订程序)。
// currentUser for ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")
AuthenticationResult authResult = await context.AcquireTokenSilentAsync(resourceUri, credential, currentUser);
如果缓存令牌,则调用AcquireTokenSilentAsync
非常快。
答案 1 :(得分:10)
看起来推荐的方法是使用AuthorizationCodeReceived
事件来交换访问令牌的身份验证码。 Vittorio has a blog entry概述了整体流程。
以下是来自Startup.Auth.cs
代码this sample app on GitHub的示例,用于设置此内容:
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
事件。如果已生成并存储了auth代码,则不会调用此事件。您必须注销或清除cookie才能强制执行此事件。
答案 2 :(得分:1)
您需要绕过默认的owin验证来执行自定义授权:
new OpenIdConnectAuthenticationOptions
{
...,
TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuer = false
},
答案 3 :(得分:0)
TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name", RoleClaimType = ClaimTypes.Role },
这行代码解决了我的问题。我们需要验证发行人是假的。
答案 4 :(得分:0)
这适用于我使用 Microsoft.AspNetCore.Authentication.OpenIdConnect 库 5.0.6。
var accessToken = await HttpContext.GetTokenAsync("access_token");
var refreshToken = await HttpContext.GetTokenAsync("refresh_token");
有关混合流的 Identity Server 4 的 documentation 中的更多信息。