【问题标题】:Dissecting ASP.NET MVC Identity for OAuth Bearer Authentication剖析 OAuth Bearer 身份验证的 ASP.NET MVC 身份
【发布时间】:2016-09-29 11:37:39
【问题描述】:

我正在学习如何使用 Asp.Net MVC Identity 2.0。

我有这段代码适用于 OAuth Bearer

    [HttpGet]
    [ActionName("Authenticate")]
    [AllowAnonymous]
    public String Authenticate(string user, string password)
    {
        if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(password))
        {
            return "Failed";
        }

        var userIdentity = UserManager.FindAsync(user, password).Result;
        if (userIdentity != null)
        {
            if (User.Identity.IsAuthenticated)
            {
                return "Already authenticated!";
            }

            var identity = new ClaimsIdentity(Startup.OAuthBearerOptions.AuthenticationType);
            identity.AddClaim(new Claim(ClaimTypes.Name, user));
            identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userIdentity.Id));

            AuthenticationTicket ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
            var currentUtc = new SystemClock().UtcNow;
            ticket.Properties.IssuedUtc = currentUtc;
            ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(1));

            string AccessToken = Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);
            return AccessToken;
        }
        return "Failed in the end";
    }

这是 Startup.Auth.cs 的代码

    //This will used the HTTP header Authorization: "Bearer 1234123412341234asdfasdfasdfasdf"
    OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
    app.UseOAuthBearerAuthentication(OAuthBearerOptions);

我查看了 ClaimsIdentity 和 AuthenticationTicket 的源代码,但没有看到票证是如何为身份注册的。

我的问题是这张票是如何在 Owin 管道中注册的?

如果可能,我的目标是撤销这张票。

提前致谢。

【问题讨论】:

    标签: asp.net-mvc asp.net-web-api2 asp.net-identity-2 owin-middleware


    【解决方案1】:

    首先,这是 Taiseer Joudeh 的 great tutorial on ASP.NET Identity 2

    这是将承载令牌处理添加到 OWIN 应用程序管道的行。

    app.UseOAuthBearerAuthentication(OAuthBearerOptions);
    

    另外,您是否自己编写了授权提供程序?我的启动代码看起来更像这样:

    app.CreatePerOwinContext(ApplicationDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
    
    PublicClientId = "self";
    OAuthServerOptions = new OAuthAuthorizationServerOptions
    {
        AllowInsecureHttp = true,
        TokenEndpointPath = new PathString("/Token"),
        AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(1440),     //TODO: change to smaller value in production, 15 minutes maybe
        Provider = new SimpleAuthorizationServerProvider(PublicClientId),
        RefreshTokenProvider = new SimpleRefreshTokenProvider()
    };
    
    app.UseOAuthAuthorizationServer(OAuthServerOptions);
    
    OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
    app.UseOAuthBearerAuthentication(OAuthBearerOptions);
    

    我的 SimpleAuthorizationServerProvider 然后有一个像这样的 Grant 方法:

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin") ?? "*";
    
        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
    
        var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
    
        ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
    
        if (user == null)
        {
            context.SetError("invalid_grant", "The user name or password is incorrect.");
            return;
        }
    
        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()));
        identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
        identity.AddClaim(new Claim("sub", context.UserName));
    
        foreach (var role in userManager.GetRoles(user.Id))
        {
            identity.AddClaim(new Claim(ClaimTypes.Role, role));
        }
    
        var props = new AuthenticationProperties(new Dictionary<string, string>
        {
            {"as:client_id", context.ClientId ?? string.Empty}
        });
    
        var ticket = new AuthenticationTicket(identity, props);
        context.Validated(ticket);
    }
    

    几乎所有这些都是基于上面提到的教程。希望对您有所帮助。

    更新 根据 Taiseer on this page,没有标准的方式来撤销令牌。

    撤销经过身份验证的用户的访问权限:一旦用户获得长期访问令牌,他将能够访问服务器资源 只要他的访问令牌没有过期,就没有标准的办法 撤销访问令牌,除非授权服务器实现 自定义逻辑,强制您将生成的访问令牌存储在 数据库并对每个请求进行数据库检查。但随着刷新 令牌,系统管理员可以通过简单地删除 从数据库中刷新令牌标识符,以便一旦系统请求 使用已删除的刷新令牌的新访问令牌,授权 服务器将拒绝此请求,因为刷新令牌不再 可用(我们将对此进行详细介绍)。

    但是,here is an interesting approach 可能会满足您的需求。它只需要一些自定义实现。

    【讨论】:

    • 感谢您的回复。是的,我研究过Taiseer 的教程,非常好。我发布的代码也同样有效。我想知道是否有任何方法可以撤销机票?
    • @superfly71 我已经更新了帖子。我认为你需要实现刷新令牌来完成你想要的。
    • 我实际上采用了您提供的链接中提到的黑名单方法。我只是希望有更好的方法。无论如何,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2010-09-24
    • 2015-02-02
    • 2016-05-30
    • 1970-01-01
    • 1970-01-01
    • 2017-12-10
    • 1970-01-01
    • 2015-11-04
    相关资源
    最近更新 更多