为什么Identity Server4 Logout无法正常工作? (没有MS身份证明)

时间:2018-06-12 14:47:51

标签: identityserver4

我正在尝试使用IdentityServer4实现我自己的OAuth服务器,到目前为止除了注销外一切正常。

使用Microsoft Identity,因为我已经拥有一个WebApi的现有WebApp,它正在处理与用户相关的CRUD操作。因此,我使用现有数据库来获取用户并验证其用户名和PW。如果验证成功,我的验证方法将返回“AuthenticatedUser”类型的对象(这是我制作的UtilityClass)。

编辑我的客户端是一个Xamarin应用程序,并使用IdentityModel.OidcClient2进行登录。我正在使用UWP平台 Edit 进行测试,该平台使用WebAuthenticationBroker进行登录/注销调用。

我使用的代码是QuickStart UI示例中的代码,只需稍加修改即可验证现有数据库中的用户: 编辑现在我明确地创建了Claims,ClaimsIdentity,并尽可能地添加了CookieAuthenticationDefaults.AuthenticationScheme。

//my method for user validation
AuthenticatedUser user = await _userService.ValidateCredentials(model.Username, model.Password);

//rest of login code from quickstart ui
if (user != null) 
{ 
    await _events.RaiseAsync(new UserLoginSuccessEvent(user.FirstName, user.Id.ToString(), user.FirstName));

    // only set explicit expiration here if user chooses "remember me". 
    // otherwise we rely upon expiration configured in cookie middleware.
    AuthenticationProperties props = null;
    if (AccountOptions.AllowRememberLogin && model.RememberLogin)
    {
        props = new AuthenticationProperties
         {
        IsPersistent = true,
        ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
        };
    };

    //things we know about the user that we wish to store on the cookie
    var claims = new List<Claim>
    {
        new Claim(JwtClaimTypes.Role, user.RoleId.ToString()),
        new Claim(JwtClaimTypes.Name, user.FirstName + " " + user.LastName),
        new Claim(JwtClaimTypes.Subject, user.Id.ToString())
    };        

    var userIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

    ClaimsPrincipal principal = new ClaimsPrincipal(userIdentity);

    //set the cookie using the SignInAsync method
    await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, props);
    // issue authentication cookie with subject ID and username
    await HttpContext.SignInAsync(user.Id.ToString(), user.FirstName, props);

    //....

到目前为止,这似乎运作良好。当登录失败时,我无法访问受保护的Api,如果登录成功,我会获得一个带有我请求的声明的AccessToken,并且我可以按预期访问受保护的Api方法。

当我调用注销端点(通过对端点的HTTP请求完成,提供id_token_hint作为查询参数)时,由于某种原因,用户未经过身份验证 - 因此我的用户永远不会通过调用HttpContext.SignOutAsync来注销( )。

        if (User?.Identity.IsAuthenticated == true) //always evaluates to false?! why?
        {
            // delete local authentication cookie
            await HttpContext.SignOutAsync();

            // raise the logout event
            await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName()));
        }

编辑使用WebAuthenticationBroker而不是简单的HTTP请求来调用注销端点后,控制台会记录“XamarinApp”已注销的状态。即使从未调用过HttpContext.SignOutAsync()这是什么意思?我怀疑这是好的,但是应用程序表现得像我想要的那样,例如我可以用新用户登录。

[16:43:12 Debug] IdentityServer4.Hosting.EndpointRouter
Request path /connect/endsession matched to endpoint type Endsession

[16:43:12 Debug] IdentityServer4.Hosting.EndpointRouter
Endpoint enabled: Endsession, successfully created handler: IdentityServer4.Endpoints.EndSessionEndpoint

[16:43:12 Information] IdentityServer4.Hosting.IdentityServerMiddleware
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.EndSessionEndpoint for /connect/endsession

[16:43:12 Debug] IdentityServer4.Endpoints.EndSessionEndpoint
Processing signout request for anonymous

[16:43:12 Debug] IdentityServer4.Validation.EndSessionRequestValidator
Start end session request validation

[16:43:12 Debug] IdentityServer4.Validation.TokenValidator
Start identity token validation

[16:43:12 Debug] IdentityServer4.EntityFramework.Stores.ClientStore
xamarinApp found in database: True

[16:43:12 Debug] IdentityServer4.Validation.TokenValidator
Client found: xamarinApp / Xamarin App

[16:43:12 Debug] IdentityServer4.Validation.TokenValidator
Calling into custom token validator: IdentityServer4.Validation.DefaultCustomTokenValidator

[16:43:12 Debug] IdentityServer4.Validation.TokenValidator
Token validation success
{
  //Token details omitted here for the sake of simplicity. 
  }
}

[16:43:12 Information] IdentityServer4.Validation.EndSessionRequestValidator
End session request validation success
{
  "ClientId": "xamarinApp",
  "ClientName": "Xamarin App",
  "SubjectId": "unknown",
  "PostLogOutUri": "xamarinformsclients://callback",
  "Raw": {
    "id_token_hint": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjA3RjlGQ0VFRTVCMzM4ODkzODZCNjc2MTZCRjZCOTFEMUEwRkRBQjAiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJCX244N3VXek9JazRhMmRoYV9hNUhSb1AyckEifQ.eyJuYmYiOjE1Mjg5MDA5ODYsImV4cCI6MTUyODkwMTI4NiwiaXNzIjoiaHR0cHM6Ly9sYXB0b3AtMW0waW4zMW46NDQzODciLCJhdWQiOiJ4YW1hcmluQXBwIiwibm9uY2UiOiI4YjZjZWRkMDFhMjQ0ZDJmOWY3ZGM4NzZmM2NmZGYwNiIsImlhdCI6MTUyODkwMDk4NiwiYXRfaGFzaCI6IkZualBtd2hiZTNmOVRITjEzM0NSZWciLCJzaWQiOiJkMmJlZTgyYzg0YWY2NGI5ZDUyYmZlNmExNmU1MTNmZiIsInN1YiI6IjI4IiwiYXV0aF90aW1lIjoxNTI4OTAwOTgzLCJpZHAiOiJsb2NhbCIsInVzZXJfaWQiOiIyOCIsInJvbGVfaWQiOiI0IiwibmFtZSI6IlRpbGwgU2F1YmVybWFubiIsImZhbWlseV9uYW1lIjoiU2F1YmVybWFubiIsImFtciI6WyJwd2QiXX0.ZjwL8nuq-WD3D-pXruZtE_I5TyNNO_ZMabz2JiKVnTaTnITwGV5CIJcLcWSpBCOyaSFXKUicAtROeWLReuk_LWoUTKXcX7lyv5VP9-ItBNA13EwgsbhQX7BgS2lbE9fQU7OgGARJcpvPKaT9FabFtEZsNYW9sNeBo-6CUPkYtVH_rjRyLihFi2NlZlkHBc7_oPE0hsjf61QIwyGZEhVXvDXkP_Q9t_Bfr3_QrUF6MfyhzLs0KcMwbtlWUxYw51J8phz7RPUXbbiZ1tG9Ay4DNy8RZbzfI-uFAbrqH7waLo_f5JO15eYc-xICl22ZS_4lW0_MlzP_rq46PnGOwNBqlg",
    "post_logout_redirect_uri": "xamarinformsclients://callback"
  }
} 

编辑据我所知,这可能与我的Xamarin客户端和Cookie有关。我找到了有关如何配置MVC客户端,IDSVR4和Cookie中间件的教程,但没有关于本机应用程序,IDSVR4和Cookie中间件的任何内容。

IDSVR4(或特别是注销)应该如何与非MVC客户端和IdentityModel.OidcClient一起使用?

1 个答案:

答案 0 :(得分:0)

最后我找到了原因。在QuickstartUI示例中,仅当用户选择“记住我”选项时,类“ AccountConteroller.cs”才设置Explicit Expiration。我删除了if条件,并最终正确存储了身份验证Cookie,注销后我的用户不再为null,一切都很好。

class AccountController
...

AuthenticationProperties props = null;
//ALWAYS SET EXPLICIT EXPIRATION, SO COOKIE CAN BE DELETED WHEN LOGGING OUT
//if (AccountOptions.AllowRememberLogin && model.RememberLogin)
//{
    props = new AuthenticationProperties
    {
        IsPersistent = true,
        ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
    };

//};