asp.net - 验证 AspNet.Security.OpenIdConnect.Server (ASP.NET vNext) 颁发的 token

标签 asp.net jwt openid-connect aspnet-contrib

我正在使用 Visual Studio 2015 Enterprise 和 ASP.NET vNext Beta8 来构建一个既发布又使用 JWT token 的端点。我最初是通过自己生成 token 来解决这个问题的,如 here 所述.
后来有帮助article @Pinpoint 透露,可以将 AspNet.Security.OpenIdConnect.Server(又名 OIDC)配置为为我发放和使用 token 。

所以我按照这些说明,建立了一个端点,并从 postman 提交了一个 x-www-form-urlencoded 帖子。我收到了一个合法的 token :

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

这很棒,但也是我卡住的地方。现在,我如何注释 Controller 操作以使其需要此不记名 token ?

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

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

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

An unhandled exception occurred while processing the request.

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

WebException: Unable to connect to the remote server

HttpRequestException: An error occurred while sending the request.

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 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'.'.



考虑以下步骤来重现(但请不要考虑这个生产值(value)的代码):
  • 应用 ASP.NET Beta8 工具,如 here 所述
  • 打开 Visual Studio Enterprise 2015 并创建一个新的 Web API ASP.NET 5 预览模板项目
  • 更改 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”
    },

    “命令”:{
    “网络”:“Microsoft.AspNet.Server.Kestrel”
    },

    “构架”: {
    “dnx451”:{}
    },

    “排除”: [
    "wwwroot",
    “节点模块”
    ],
    “发布排除”:[
    " .user",
    "
    .vspscc"
    ]
    }
  • 更改 Startup.cs 如下(这是@Pinpoint 的原始文章提供的;我删除了评论并添加了 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 获取 token .要获取 token ,请使用 x-www-form-urlencoded POST,其中“grant_type”为“password”,“username”为任何内容,“password”为任何内容,“resource”为 API 端点的地址。例如,我的特定 URL 是 http://localhost:37734/authorization/v1 .
  • 复制 Base64 编码的 token ,然后使用 token 调用向导值 Controller ,使用 postman .要使用 token ,请使用 header Content-Type application/json 和 Authorization Bearer eyJ0eXAiO....(您的 token )进行 GET。我的特定 URL 是 http://localhost:37734/api/values .
  • 观察前面提到的异常。

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

    谢谢你。

    最佳答案

    options.Authority对应于发行者地址(即您的 OIDC 服务器的地址)。
    http://localhost:50000/您使用 http://localhost:37734/ 时似乎不正确稍后在您的问题中。尝试修复 URL,然后再试一次。

    关于asp.net - 验证 AspNet.Security.OpenIdConnect.Server (ASP.NET vNext) 颁发的 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33401936/

    相关文章:

    asp.net - SignalR - 离开所有组

    c# - 将数据库中的所有详细信息存储到一个文件中,然后下载该文件

    authentication - cookie 与 JWT 有何不同?为什么它们被认为比 JWT 更差?

    mobile - 移动应用程序如何获得对其 API 的长期访问权限?

    angular - OpenID 连接 : Implicit or Auth Code flow for SPAs?

    asp.net - asp .net 如何处理并发用户请求?

    asp.net - .Net 和 Ruby on Rails - 使用情况

    jwt - 使用 fusion auth JWT populate lambda 是否可以添加租户 ID 作为声明?

    encryption - 加密 JWT 有效负载

    oauth-2.0 - [OAuth][Keycloak] invalid_grant session 在尝试使用 refresh_token 时未激活