ASP.NET OWIN OpenID Connect未创建用户身份验证。

13 浏览
0 Comments

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没有被设置?这似乎应该自动发生。我应该手动创建它吗?

0
0 Comments

问题出现的原因:代码中使用了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未创建用户身份验证的问题。

0
0 Comments

在我的情况下,在启动文件的Notifications中我不需要添加任何内容。我遗漏了这一点:

app.UseCookieAuthentication(new CookieAuthenticationOptions() 
{
    CookieManager = new SystemWebCookieManager()
});

Katana中存在一个bug,阻止了cookie正确保存,所以在经过三天的寻找后,添加这一行代码解决了我的问题!

0
0 Comments

问题的原因是没有设置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不创建用户身份验证的问题,并确保用户身份验证的正常工作。

0