ASP.NET OWIN OpenID Connect未创建用户身份验证。
ASP.NET OWIN OpenID Connect未创建用户身份验证。
我有一个ASP.NET 4.6的Web应用程序,我正在尝试使用OWIN添加OpenId Connect。
我添加了我的Owin启动类,一切似乎配置正确,但我遇到的问题是ASP身份验证/已验证的用户从未被创建。我最终陷入了一个无休止的循环中,OpenId回调页面重定向回原始页面,然后重定向到登录页面,以此类推。
这是我的启动类:
public void Configuration(IAppBuilder app) { app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); app.UseKentorOwinCookieSaver(); app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Login.aspx"), ExpireTimeSpan = TimeSpan.FromDays(7) }); app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { ClientId = _clientId, ClientSecret = _clientSecret, Authority = _authority, RedirectUri = _redirectUri, // LoginCallback PostLogoutRedirectUri = "http://localhost:60624/Logout.aspx", ResponseType = OpenIdConnectResponseType.CodeIdToken, Scope = "openid profile email", TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name" }, Notifications = new OpenIdConnectAuthenticationNotifications { AuthorizationCodeReceived = async n => { // Exchange code for access and ID tokens var tokenClient = new TokenClient($"{_authority}/as/token.oauth2", _clientId, _clientSecret); var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, _redirectUri); if (tokenResponse.IsError) { throw new Exception(tokenResponse.Error); } var userInfoClient = new UserInfoClient($"{_authority}/idp/userinfo.openid"); var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken); var claims = new List(userInfoResponse.Claims) { new Claim("id_token", tokenResponse.IdentityToken), new Claim("access_token", tokenResponse.AccessToken) }; n.AuthenticationTicket.Identity.AddClaims(claims); //// create the identity //var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationType); //System.Web.HttpContext.Current.GetOwinContext().Authentication.SignIn(new AuthenticationProperties //{ // IsPersistent = true //}, identity); } } }); }
这是Login.aspx页面:
protected void Page_Load(object sender, EventArgs e) { if (!Request.IsAuthenticated) { HttpContext.Current.GetOwinContext().Authentication.Challenge( new AuthenticationProperties { RedirectUri = Request["ReturnUrl"] ?? "Default.aspx" }, OpenIdConnectAuthenticationDefaults.AuthenticationType); } }
页面流程如下:
1)请求:http://localhost:60624/Page.aspx
响应:302 - 重定向到Login.aspx
2)请求:http://localhost:60624/Login.aspx?ReturnUrl=%2FPage.aspx
响应302 - 重定向到https://auth.myprovider.com
在响应头中设置了一些cookie:
Set-Cookie: OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=xxxxxxxxx; path=/; expires=Mon, 22-Apr-2019 14:12:00 GMT; HttpOnly
Set-Cookie: OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=yyyyyyyyy; expires=Mon, 22-Apr-2019 14:12:00 GMT; path=/; HttpOnly
3)认证提供者,登录,并将其重定向到/LoginCallback
4)请求:http://localhost:60624/LoginCallback
响应302 - 重定向到/Page.aspx
清除了在步骤2中设置的cookie。
Set-Cookie: OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT
Set-Cookie: OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=; expires=Thu, 01-Jan-1970 00:00:00 GMT; path=/
5)回到Page.aspx,用户未经身份验证;转到步骤1
我已经进行了一些调试,发现AuthorizationCodeReceived在启动时触发,并且后端成功调用了User Info端点。我尝试从该通知中调用System.Web.HttpContext.Current.GetOwinContext().Authentication.SignIn(),但似乎没有任何作用。
目前,我陷入了困境。为什么用户身份验证cookie没有被设置?这似乎应该自动发生。我应该手动创建它吗?
问题出现的原因:代码中使用了OpenID Connect身份验证,但是没有创建用户身份验证。
解决方法:在OnSecurityTokenValidated方法中创建用户身份验证,并将当前页面的请求URL存储在会话变量中,然后在启动中使用该变量设置arg.AuthenticationTicket.Properties.RedirectUri的值。
Imports System.Security.Claims
Imports System.Threading.Tasks
Imports IdentityModel
Imports IdentityModel.Client
Imports Microsoft.AspNet.Identity
Imports Microsoft.AspNet.Identity.Owin
Imports Microsoft.IdentityModel.Protocols.OpenIdConnect
Imports Microsoft.Owin
Imports Microsoft.Owin.Security
Imports Microsoft.Owin.Security.Cookies
Imports Microsoft.Owin.Security.Notifications
Imports Microsoft.Owin.Security.OAuth
Imports Microsoft.Owin.Security.OpenIdConnect
Imports Owin
Partial Public Class Startup
'...
Private Async Function OnSecurityTokenValidated(arg As SecurityTokenValidatedNotification(Of Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectMessage, OpenIdConnectAuthenticationOptions)) As Task
'...
Dim nid = New ClaimsIdentity(
DefaultAuthenticationTypes.ApplicationCookie,
ClaimTypes.GivenName,
ClaimTypes.Role)
'...
nid.AddClaim(New Claim(ClaimTypes.Role, "group1"))
arg.AuthenticationTicket = New AuthenticationTicket(nid, arg.AuthenticationTicket.Properties)
arg.AuthenticationTicket.Properties.RedirectUri = HttpContext.Current.Session("PageRedirect").ToString()
End Function
End Class
Private Sub SomePageName_Load(sender As Object, e As EventArgs) Handles Me.Load
If Not IsPostBack Then
If User.Identity.IsAuthenticated Then
Console.WriteLine(User.Identity.GetUserName())
Else
Session("PageRedirect") = Request.Url
Response.Redirect("/")
End If
End If
End Sub
以上代码中的修改将解决ASP.NET OWIN OpenID Connect未创建用户身份验证的问题。
问题的原因是没有设置RedeemCode和SaveTokens属性,解决方法是将其设置为True。另外,还需要在notifications中添加一些代码,以确保用户身份验证的正常工作。此外,还需要设置TokenValidationParameters的NameClaimType属性。
在OpenID Connect中,当使用代码流进行身份验证时,我们需要设置RedeemCode和SaveTokens属性为True。这样做的好处是,它可以确保我们能够成功地获取和保存访问令牌和刷新令牌。
不仅如此,我们还需要在notifications中添加一些代码,以确保用户身份验证的正常工作。具体来说,我们需要在SecurityTokenValidated事件中使用以下代码:
SecurityTokenValidated = (context) => { var ctx = context.OwinContext; var applicationCookieIdentity = new ClaimsIdentity(context.AuthenticationTicket.Identity, null, DefaultAuthenticationTypes.ApplicationCookie, null, null); ctx.Authentication.SignIn(applicationCookieIdentity); return Task.FromResult(0); },
这段代码的作用是,在用户身份验证成功后,将用户身份信息添加到应用程序的Cookie中。这样,我们就可以在后续的请求中使用User.Identity.Name来获取用户的姓名信息。
最后,还需要设置TokenValidationParameters的NameClaimType属性为"name",这样才能自动填充User.Identity.Name。
通过以上的设置和代码添加,我们可以解决ASP.NET OWIN OpenID Connect不创建用户身份验证的问题,并确保用户身份验证的正常工作。