本文介绍了验证 AspNet.Security.OpenIdConnect.Server (ASP.NET vNext) 颁发的令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我正在使用 Visual Studio 2015 Enterprise 和 ASP.NET vNext Beta8 来构建一个端点,该端点发出并使用 JWT 令牌.我最初是通过自己生成令牌来解决这个问题的,如 所述这里.后来@Pinpoint 的一篇有用的文章显示,AspNet.Security.OpenIdConnect.Server(又名 OIDC)可以配置为为我发放和使用令牌.

I am using Visual Studio 2015 Enterprise and ASP.NET vNext Beta8 to build an endpoint that both issues and consumes JWT tokens. I Originally approached this by generating the tokens myself, as described here.Later a helpful article by @Pinpoint revealed that AspNet.Security.OpenIdConnect.Server (a.k.a. OIDC) can be configured to issue and consume the tokens for me.

所以我按照这些说明,建立了一个端点,并从 邮递员 我收到了一个合法的令牌:

So I followed those instructions, stood up an endpoint, and by submitting an x-www-form-urlencoded post from postman I receive back a legit token:

{
  "token_type": "bearer",
  "access_token": "eyJ0eXAiO....",
  "expires_in": "3599"
}

这很棒,但也是我卡住的地方.现在,我如何注释控制器操作以使其需要此不记名令牌?

This is great but also where I get stuck. Now, how do I annotate a controller action so that it demands this bearer token?

我以为我要做的就是用[Authorize("Bearer")],添加认证方案:

I thought all I would have to do is decorate my controller method with the[Authorize("Bearer")], add an authentication scheme:

        services.AddAuthorization
        (
            options =>
            {
                options.AddPolicy
                (
                    JwtBearerDefaults.AuthenticationScheme,
                    builder =>
                    {
                        builder.
                        AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme).
                        RequireAuthenticatedUser().
                        Build();
                    }
                );
            }
        );

然后像我在前面的示例中所做的那样,使用Authorization Bearer eyJ0eXAiO...."标题调用我的控制器操作.可悲的是,所有这些方法似乎都会产生一个异常:

And then call my controller action with the "Authorization bearer eyJ0eXAiO...." header as I had done in my previous example. Sadly, all this approach seems to do though is generate an exception:

处理请求时发生未处理的异常.

SocketException: 无法建立连接,因为目标机器主动拒绝了它 127.0.0.1:50000

SocketException: No connection could be made because the target machine actively refused it 127.0.0.1:50000

WebException: 无法连接到远程服务器

WebException: Unable to connect to the remote server

HttpRequestException: 发送请求时出错.

HttpRequestException: An error occurred while sending the request.

IOException:IDX10804:无法从以下位置检索文档:'http://localhost:50000/.well-known/openid-configuration'.Microsoft.IdentityModel.Logging.LogHelper.Throw(String message, Type exceptionType, EventLevel logLevel, Exception innerException)

IOException: IDX10804: Unable to retrieve document from: 'http://localhost:50000/.well-known/openid-configuration'. Microsoft.IdentityModel.Logging.LogHelper.Throw(String message, Type exceptionType, EventLevel logLevel, Exception innerException)

InvalidOperationException: IDX10803: Unable to get configuration from: 'http://localhost:50000/.well-known/openid-configuration'.内部异常:'IDX10804:无法从以下位置检索文档:'http://localhost:50000/.well-known/openid-configuration'.'.

InvalidOperationException: IDX10803: Unable to obtain configuration from: 'http://localhost:50000/.well-known/openid-configuration'. Inner Exception: 'IDX10804: Unable to retrieve document from: 'http://localhost:50000/.well-known/openid-configuration'.'.


考虑以下步骤来重现(但请不要考虑这个生产有价值的代码):


Consider the following steps to reproduce (but please don't consider this production worthy code):

  • 按照描述应用 ASP.NET Beta8 工具 这里

打开 Visual Studio Enterprise 2015 并创建一个新的 Web API ASP.NET 5 Preview Template 项目

Open Visual Studio Enterprise 2015 and create a new Web API ASP.NET 5 Preview Template project

更改 project.json

Change project.json

{
"webroot": "wwwroot",
"版本": "1.0.0-*",

依赖":{
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-beta8",
"Microsoft.AspNet.Mvc": "6.0.0-beta8",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-beta8",
"Microsoft.AspNet.Authentication.JwtBearer": "1.0.0-beta8",
"AspNet.Security.OpenIdConnect.Server": "1.0.0-beta3",
"Microsoft.AspNet.Authentication.OpenIdConnect": "1.0.0-beta8",
"Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta4",
"Microsoft.AspNet.Diagnostics": "1.0.0-beta8"
},

命令":{
"web": "Microsoft.AspNet.Server.Kestrel"
},

框架":{
dnx451":{ }
},

排除":[
"wwwroot",
节点模块"
],
发布排除":[
".user",
"
.vspscc"
]
}

{
"webroot": "wwwroot",
"version": "1.0.0-*",

"dependencies": {
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-beta8",
"Microsoft.AspNet.Mvc": "6.0.0-beta8",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-beta8",
"Microsoft.AspNet.Authentication.JwtBearer": "1.0.0-beta8",
"AspNet.Security.OpenIdConnect.Server": "1.0.0-beta3",
"Microsoft.AspNet.Authentication.OpenIdConnect": "1.0.0-beta8",
"Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta4",
"Microsoft.AspNet.Diagnostics": "1.0.0-beta8"
},

"commands": {
"web": "Microsoft.AspNet.Server.Kestrel"
},

"frameworks": {
"dnx451": { }
},

"exclude": [
"wwwroot",
"node_modules"
],
"publishExclude": [
".user",
"
.vspscc"
]
}

如下更改 Startup.cs(这是@Pinpoint 的原始文章提供的;我已删除评论并添加了 AddAuthorization snip):

Change Startup.cs as follows (this is courtesy of @Pinpoint's original article; I have removed comments and added the AddAuthorization snip):

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthorization
        (
            options =>
            {
                options.AddPolicy
                (
                    JwtBearerDefaults.AuthenticationScheme,
                    builder =>
                    {
                        builder.
                        AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme).
                        RequireAuthenticatedUser().
                        Build();
                    }
                );
            }
        );
        services.AddAuthentication();
        services.AddCaching();
        services.AddMvc();
        services.AddOptions();
    }

    // Configure is called after ConfigureServices is called.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions<AppSettings> appSettings)
    {
        app.UseDeveloperExceptionPage();

        // Add a new middleware validating access tokens issued by the OIDC server.
        app.UseJwtBearerAuthentication(options => {
            options.AutomaticAuthentication = true;
            options.Audience = "http://localhost:50000/";
            options.Authority = "http://localhost:50000/";
            options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>
            (
                metadataAddress : options.Authority + ".well-known/openid-configuration",
                configRetriever : new OpenIdConnectConfigurationRetriever(),
                docRetriever    : new HttpDocumentRetriever { RequireHttps = false }
            );
        });

        // Add a new middleware issuing tokens.
        app.UseOpenIdConnectServer
        (
            configuration =>
            {
                configuration.Options.TokenEndpointPath= "/authorization/v1";
                configuration.Options.AllowInsecureHttp = true;
                configuration.Provider = new OpenIdConnectServerProvider {

                    OnValidateClientAuthentication = context =>
                    {
                        context.Skipped();
                        return Task.FromResult<object>(null);
                    },

                    OnGrantResourceOwnerCredentials = context =>
                    {
                        var identity = new ClaimsIdentity(OpenIdConnectDefaults.AuthenticationScheme);
                        identity.AddClaim( new Claim(ClaimTypes.NameIdentifier, "todo")  );
                        identity.AddClaim( new Claim("urn:customclaim", "value", "token id_token"));
                        context.Validated(new ClaimsPrincipal(identity));
                        return Task.FromResult<object>(null);
                    }
                };
            }
        );

        app.UseMvc();
    }
}

  • 更改 Wizarded ValuesController.cs 以指定 Authorize 属性:
  • [Route("api/[controller]")]
    public class ValuesController : Controller
    {
        // GET: api/values
        [Authorize("Bearer")]
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
    }
    

    • 运行项目,并使用 postman 获取令牌.要获取令牌,请使用 x-www-form-urlencoded POST,其中grant_type"为password",username"为任何内容,password"为任何内容,resource"为 API 端点的地址.例如,我的特定 URL 是 http://localhost:37734/authorization/v1.

      • Run the project, and acquire a token using postman. To acquire a token use x-www-form-urlencoded POST with "grant_type" of "password", "username" anything, "password" anything and "resource" the address of the API endpoint. My particular URL for example is http://localhost:37734/authorization/v1.

        复制 Base64 编码的令牌,然后使用令牌通过 邮递员.要使用令牌,请使用标头 Content-Type application/json 和 Authorization Bearer eyJ0eXAiO....(您的令牌)进行 GET.我的特定 URL 是 http://localhost:37734/api/values.

        Copy the Base64 encoded token, then use the token to call the wizarded values controller using postman. To use the token make a GET with the headers Content-Type application/json and Authorization bearer eyJ0eXAiO....(your token). My particular URL is http://localhost:37734/api/values.

        注意前面提到的异常.

        如果我在上面尝试的 [Authorize("Bearer")] 方法是错误的方法,如果有人能帮助我了解如何使用 OIDC 摄取 JWT 令牌的最佳实践,我将非常感激.

        If the [Authorize("Bearer")] approach I'm trying above is the wrong way to go I would be very appreciative if someone could help me understand best practices for how to ingest the JWT token using OIDC.

        谢谢.

        推荐答案

        options.Authority对应issuer地址(即你的OIDC服务器地址).

        options.Authority corresponds to the issuer address (i.e the address of your OIDC server).

        http://localhost:50000/ 似乎不正确,因为您稍后在问题中使用 http://localhost:37734/ .尝试修复 URL,然后再试一次.

        http://localhost:50000/ doesn't seem to be correct as you're using http://localhost:37734/ later in your question. Try fixing the URL and give it another try.

        这篇关于验证 AspNet.Security.OpenIdConnect.Server (ASP.NET vNext) 颁发的令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

        1403页,肝出来的..

09-06 15:46