ASP.NET 5 OAuth 持有者令牌身份验证

Posted

技术标签:

【中文标题】ASP.NET 5 OAuth 持有者令牌身份验证【英文标题】:ASP.NET 5 OAuth bearer token authentication 【发布时间】:2015-06-04 07:34:39 【问题描述】:

我正在尝试在 ASP.NET 5 中实现 OAuth 不记名令牌身份验证,并且正在努力寻找如何做到这一点的示例,因为 OWIN 的内容在 ASP.NET 5 中发生了变化。

例如 IApplicationBuilder.UseOAuthAuthorizationServer()IApplicationBuilder。 UseOAuthBearerAuthentication() 要么不再存在,要么我缺少参考?

任何指针将不胜感激。

【问题讨论】:

【参考方案1】:

这里真正的关键是令牌生成。我已经设法使用默认的 Microsoft.AspNet.Security.OAuthBearer 包构建了一个,但这并不容易。

// Injected from the constructor; this is why we configured the options above rather 
// than simply passing them to the UseOAuthBearerAuthentication()
private readonly OAuthBearerAuthenticationOptions bearerOptions;

// In your /Token action...
var handler = bearerOptions.SecurityTokenValidators.OfType<System.IdentityModel.Tokens.JwtSecurityTokenHandler>()
    .First();
// The identity here is the ClaimsIdentity you want to authenticate the user as.
// You can get this using the SignInManager if you're using Identity.
var securityToken = handler.CreateToken(
    issuer: bearerOptions.TokenValidationParameters.ValidIssuer, 
    audience: bearerOptions.TokenValidationParameters.ValidAudience, 
    subject: identity);
var token = handler.WriteToken(securityToken);
// The var token is your bearer token

这里详细介绍了我的完整解决方案:Token Based Authentication in ASP.Net 5 (vNext)。

【讨论】:

【参考方案2】:

我做到了,但是将 Thinktecture 的身份服务器 v 3 设置为我的令牌提供者,但我认为如果您有另一个令牌提供者,它将是相同的流程....

(更新:我添加了一个带有代码的 github 存储库:here)

这是我的启动课程:(Identityserver v3 也可以在 Vnext 上运行,但稍作调整)。请注意,我在同一个 Web 应用程序中有服务器和 Web API。如果你有两个不同的 web 项目也可以,但这里是为了演示......

public class Startup

    // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    
        services.AddMvc();
    

    public void Configure(IApplicationBuilder app)
    
        app.Map("/core", core =>
        
            var factory = InMemoryFactory.Create(
                                    users: Users.Get(),
                                    clients: Clients.Get(),
                                    scopes: Scopes.Get());

            var idsrvOptions = new IdentityServerOptions
            
                IssuerUri = "https://idsrv3.com",
                SiteName = "test vnext Identity server",
                Factory = factory,
                SigningCertificate = Certificate.Get(),
                RequireSsl = false,

                CorsPolicy = CorsPolicy.AllowAll,

                AuthenticationOptions = new AuthenticationOptions
                
                
            ;

            core.UseIdentityServer(idsrvOptions);
        );

        app.Map("/api", api =>
        

            api.UseOAuthBearerAuthentication(options => 
                options.Authority = Constants.AuthorizationUrl;
                options.MetadataAddress = Constants.AuthorizationUrl + "/.well-known/openid-configuration";
                options.TokenValidationParameters.ValidAudience = "https://idsrv3.com/resources"; 
            );

            api.UseMvc();

        );

    

从这里您可以看到我的 IdentityServerV3 映射到“/core”,并且在同一个 Web 应用程序项目(可能是另一个)中,我有一个使用 MVC 的 Web api。下面是控制器:

  [Authorize]
[Route("[controller]")]
public class Test : Controller

    [HttpGet]
    public JsonResult Get()
    
        return Json(new
        
            message = "You See this then it's ok auth is  :" + User.Identity.IsAuthenticated,
        );
    

我已经在我的身份服务器中配置了一个客户端:

  new Client
            
                 //Resource Owner Flow Client (our web UI)
                ClientName = "WebUI",
                Enabled = true,

                ClientId = "IdentityWebUI",
                ClientSecrets = new List<ClientSecret>
                
                    new ClientSecret("secret".Sha256())
                ,

                Flow = Flows.ResourceOwner,
                AccessTokenType = AccessTokenType.Jwt,
                AccessTokenLifetime = 3600

            

这里是用户(使用的 InMemory 用户):

 return new List<InMemoryUser>
        
            new InMemoryUser
            
                Username = "testUser",
                Password = "testPwd",
                Subject = "I am the Subject"
            

        ;

在提琴手中,我发出以下 POST 以获取不记名令牌:

    POST : http://localhost:4357/core/connect/token

    User-Agent: Fiddler
    Host: localhost:4357
    Content-Length: 67
    Content-Type: application/x-www-form-urlencoded
    Authorization: Basic SWRlbnRpdHlXZWJVSTpzZWNyZXQ=

    grant_type=password&username=testUser&password=testPwd&scope=openid

在响应中你会得到一个 Access_token

"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSIsImtpZCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSJ9.eyJjbGllbnRfaWQiOiJJZGVudGl0eVdlYlVJIiwic2NvcGUiOiJvcGVuaWQiLCJzdWIiOiJJIGFtIHRoZSBTdWJqZWN0IiwiYW1yIjoicGFzc3dvcmQiLCJhdXRoX3RpbWUiOjE0MjgzOTQ3MzAsImlkcCI6Imlkc3J2IiwiaXNzIjoiaHR0cHM6Ly9pZHNydjMuY29tIiwiYXVkIjoiaHR0cHM6Ly9pZHNydjMuY29tL3Jlc291cmNlcyIsImV4cCI6MTQyODM5ODMzMCwibmJmIjoxNDI4Mzk0NzMwfQ.cbB4YrRXaaRDNw8BjeI4Q1DvXN28xmJScMJBGWCM_zSLcH1i63cQVTmR8X86rGP5VrR0Ly4-EmWZ8911Vh4jc4Ua0Kgz2n7RbmQ6VqQX5Z_lM3F8EIgD81kpUn0v3hhSFW06aJ2Lo1XOZG_re84xGgqre-H4dC0XZR6IQMEAQ9Q5dOXBh8V1NxyLSh0PzyrRRmOnEndoaY4uaIFtbp9j7KnXxQ3ZdGmaYAO96xuhHfO1DbgRdw6fYyf4nnC795yhnwDh1QZGxPsFaysJSA_3-cjmw-29m-Ga0hD1ALfVE7R57iNLxkB6dyEuz1UFJhJyibRDW9sNspo2gQFZZGxMKQ","expires_in":3600,"token_type":"Bearer"

然后我使用那个 access_token 来调用我的 web api

这是提琴手(在作曲家窗格中)

    GET http://localhost:4357/api/Test

    User-Agent: Fiddler
    Host: localhost:4357
    Content-Length: 0
    Content-Type: application/x-www-form-urlencoded
    Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSIsImtpZCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSJ9.eyJjbGllbnRfaWQiOiJJZGVudGl0eVdlYlVJIiwic2NvcGUiOiJvcGVuaWQiLCJzdWIiOiJJIGFtIHRoZSBTdWJqZWN0IiwiYW1yIjoicGFzc3dvcmQiLCJhdXRoX3RpbWUiOjE0MjgzOTQ3MzAsImlkcCI6Imlkc3J2IiwiaXNzIjoiaHR0cHM6Ly9pZHNydjMuY29tIiwiYXVkIjoiaHR0cHM6Ly9pZHNydjMuY29tL3Jlc291cmNlcyIsImV4cCI6MTQyODM5ODMzMCwibmJmIjoxNDI4Mzk0NzMwfQ.cbB4YrRXaaRDNw8BjeI4Q1DvXN28xmJScMJBGWCM_zSLcH1i63cQVTmR8X86rGP5VrR0Ly4-EmWZ8911Vh4jc4Ua0Kgz2n7RbmQ6VqQX5Z_lM3F8EIgD81kpUn0v3hhSFW06aJ2Lo1XOZG_re84xGgqre-H4dC0XZR6IQMEAQ9Q5dOXBh8V1NxyLSh0PzyrRRmOnEndoaY4uaIFtbp9j7KnXxQ3ZdGmaYAO96xuhHfO1DbgRdw6fYyf4nnC795yhnwDh1QZGxPsFaysJSA_3-cjmw-29m-Ga0hD1ALfVE7R57iNLxkB6dyEuz1UFJhJyibRDW9sNspo2gQFZZGxMKQ

然后我仍然在提琴手中得到响应:

您可以通过以下link 获得更多信息,但它与 vnext 无关。我将在此创建一个帖子,因为我需要一个 angularJS 应用程序来进行身份验证和使用隐式流而不是资源所有者流...与 Visual Studio 2015 预览

【讨论】:

我有兴趣阅读您关于 AngularJS、Oauth 隐式流和 VS 2015 的帖子。这是在某处发布的吗? “Identityserver v3 也可以在 Vnext 上运行,但需要稍作调整”。请您提供更多信息,因为我似乎无法解决依赖关系 @MRainzo 在此处查看实现 Identity Server 3 的示例 ASP.NET 5 项目:github.com/IdentityServer/IdentityServer3.Samples/tree/master/… 在您的 POST 请求中,Authorization: Basic SWRlbnRpdHlXZWJVSTpzZWNyZXQ= 是什么 - 它从何而来? ` 这只是用户密码编码的基本身份验证:用户名:base64 编码的密码。你可以用提琴手做到这一点。检查它的文档。【参考方案3】:

我不确定 UseOAuthAuthorizationServer 在哪里,但是对于 UseOAuthBearerAuthentication,请尝试添加 Microsoft.AspNet.Security.OAuthBearer NuGet 包,然后在您的启动配置方法中添加:

app.UseOAuthBearerAuthentication(options =>
            
                options.Audience = your audience;
                options.Authority = your authority); //or whatever options you need

【讨论】:

仅供参考,作为 Katana 一部分的 OAuth2 授权服务器不会移植到 ASP.NET 5:***.com/questions/29055477/…

以上是关于ASP.NET 5 OAuth 持有者令牌身份验证的主要内容,如果未能解决你的问题,请参考以下文章

ASP.net core web api:使用 Facebook/Google OAuth 访问令牌进行身份验证

.NET Web API 2 OWIN 持有者令牌身份验证

ASP.NET 5 (vNext) 中的身份验证

web api - asp.net 身份令牌即使对于后续请求也会过期

Aurelia 的 Oauth2 托管在 asp .net 核心中

SignalR - 使用访问令牌进行身份验证