我已经从帖子中了解了有关如何实施AspNet.Security.OpenIdConnect.Server的所有信息。
精确定位,你听到了吗? ;)
我设法将令牌发放和令牌消费分开。我不会显示" auth服务器端"因为我认为该部分已经完成,但我将展示如何在自定义AuthorizationProvider中构建身份验证票证:
public sealed class AuthorizationProvider : OpenIdConnectServerProvider
{
// The other overrides are not show. I've relaxed them to always validate.
public override async Task GrantResourceOwnerCredentials(GrantResourceOwnerCredentialsContext context)
{
// I'm using Microsoft.AspNet.Identity to validate user/password.
// So, let's say that I already have MyUser user from
//UserManager<MyUser> UM:
var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);
//identity.AddClaims(await UM.GetClaimsAsync(user));
identity.AddClaim(ClaimTypes.Name, user.UserName);
(await UM.GetRolesAsync(user)).ToList().ForEach(role => {
identity.AddClaim(ClaimTypes.Role, role);
});
var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity),
new AuthenticationProperties(),
context.Options.AuthenticationScheme);
// Some new stuff, per my latest research
ticket.SetResources(new[] { "my_resource_server" });
ticket.SetAudiences(new[] { "my_resource_server" });
ticket.SetScopes(new[] { "defaultscope" });
context.Validated(ticket);
}
}
在auth服务器上启动:
using System;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Data.Entity;
using Microsoft.Extensions.DependencyInjection;
using MyAuthServer.Providers;
namespace My.AuthServer
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication();
services.AddCaching();
services.AddMvc();
string connectionString = "there is actually one";
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<MyDbContext>(options => {
options.UseSqlServer(connectionString).UseRowNumberForPaging();
});
services.AddIdentity<User, Role>()
.AddEntityFrameworkStores<MyDbContext>().AddDefaultTokenProviders();
}
public void Configure(IApplicationBuilder app)
{
app.UseIISPlatformHandler();
app.UseOpenIdConnectServer(options => {
options.ApplicationCanDisplayErrors = true;
options.AllowInsecureHttp = true;
options.Provider = new AuthorizationProvider();
options.TokenEndpointPath = "/token";
options.AccessTokenLifetime = new TimeSpan(1, 0, 0, 0);
options.Issuer = new Uri("http://localhost:60556/");
});
app.UseMvc();
app.UseWelcomePage();
}
public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}
}
果然,当我收到此HTTP请求时,我确实获得了访问令牌,但我不确定该访问令牌是否具有资源服务器所需的所有数据。
POST /token HTTP/1.1
Host: localhost:60556
Content-Type: application/x-www-form-urlencoded
username=admin&password=pw&grant_type=password
现在,在资源服务器端,我使用JWT承载认证。在创业时,我得到了:
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Data.Entity;
using Microsoft.Extensions.DependencyInjection;
namespace MyResourceServer
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
string connectionString = "there is actually one";
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<MyDbContext>(options => {
options.UseSqlServer(connectionString).UseRowNumberForPaging();
});
services.AddIdentity<User, Role>()
.AddEntityFrameworkStores<MyDbContext>().AddDefaultTokenProviders();
}
public void Configure(IApplicationBuilder app)
{
app.UseIISPlatformHandler();
app.UseMvc();
app.UseWelcomePage();
app.UseJwtBearerAuthentication(options => {
options.Audience = "my_resource_server";
options.Authority = "http://localhost:60556/";
options.AutomaticAuthenticate = true;
options.RequireHttpsMetadata = false;
});
}
public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}
}
当我向资源服务器发出此HTTP请求时,我收到401 Unauthorized:
GET /api/user/myroles HTTP/1.1
Host: localhost:64539
Authorization: Bearer eyJhbGciOiJS...
Content-Type: application/json;charset=utf-8
拥有/api/user/myroles
路线的控制器使用没有参数的普通[Authorize]
进行修饰。
我觉得我在auth和资源服务器上都缺少某些东西,但不知道它们是什么。
提出问题的其他问题&#34;如何验证AspNet.Security.OpenIdConnect.Server发布的令牌&#34;没有答案。我很感激你的帮助。
另外,我注意到样本提供程序中已经注释了OAuth Introspection,并且已经读过很快就不会支持Jwt的地方了。我无法找到给我OAuth Instrospection的依赖。
更新我已经从每个auth和资源服务器中包含了我的两个startup.cs。是否有任何错误会导致资源服务器始终为每个请求返回401?
在整个努力过程中,我没有真正触及过的一件事就是签约。它似乎在auth服务器上为JWT生成签名,但资源服务器(我猜)不知道签名密钥。回到OWIN项目,我不得不创建一个机器密钥并放在两台服务器上。
答案 0 :(得分:3)
修改:中间件实例的顺序不正确:the JWT bearer middleware must be registered before MVC:
app.UseIISPlatformHandler();
app.UseJwtBearerAuthentication(options => {
options.Audience = "my_resource_server";
options.Authority = "http://localhost:60556/";
options.AutomaticAuthenticate = true;
options.RequireHttpsMetadata = false;
});
app.UseMvc();
app.UseWelcomePage();
果然,当我收到此HTTP请求时,我确实获得了访问令牌,但我不确定该访问令牌是否具有资源服务器所需的所有数据。
您的授权服务器和资源服务器配置看起来很好,但您没有设置&#34;目的地&#34;在添加您的声明时(不要忘记为避免泄露机密数据,AspNet.Security.OpenIdConnect.Server
拒绝序列化不明确指定目的地的声明):
var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);
identity.AddClaim(ClaimTypes.Name, user.UserName, destination: "id_token token");
(await UM.GetRolesAsync(user)).ToList().ForEach(role => {
identity.AddClaim(ClaimTypes.Role, role, destination: "id_token token");
});
另外,我注意到样本提供程序中已经注释了OAuth Introspection,并且已经读过很快就不会支持Jwt的地方了。我无法找到给我OAuth Instrospection的依赖。
从下一个测试版开始(ASOS beta5,编写此答案时还没有在NuGet.org上),我们将停止使用JWT作为访问令牌的默认格式,但当然,JWT仍将支持OTB
标记现在默认不透明,您必须使用新的validation middleware(受Katana&#39; OAuthBearerAuthenticationMiddleware
启发)或新标准introspection middleware,实现OAuth2 introspection RFC:
app.UseOAuthValidation();
// Alternatively, you can also use the introspection middleware.
// Using it is recommended if your resource server is in a
// different application/separated from the authorization server.
//
// app.UseOAuthIntrospection(options => {
// options.AutomaticAuthenticate = true;
// options.AutomaticChallenge = true;
// options.Authority = "http://localhost:54540/";
// options.Audience = "resource_server";
// options.ClientId = "resource_server";
// options.ClientSecret = "875sqd4s5d748z78z7ds1ff8zz8814ff88ed8ea4z4zzd";
// });
您可以在此处找到有关这两个中间件的更多信息:https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/issues/185