Oauth 2.0 OpenID连接服务器与ASOS、.NET核心管道
通过实现资源所有者密码凭据授予,我已经开始使用带有ASOS的OpenID Connect服务器。然而,当我使用postman测试它时,我得到了一般的500内部服务器错误 这是我的代码,供您调试之用。我感谢你的反馈 谢谢 -比鲁克 这是我的Oauth 2.0 OpenID连接服务器与ASOS、.NET核心管道,oauth-2.0,asp.net-core,openid-connect,aspnet-contrib,Oauth 2.0,Asp.net Core,Openid Connect,Aspnet Contrib,通过实现资源所有者密码凭据授予,我已经开始使用带有ASOS的OpenID Connect服务器。然而,当我使用postman测试它时,我得到了一般的500内部服务器错误 这是我的代码,供您调试之用。我感谢你的反馈 谢谢 -比鲁克 这是我的Startup.cs public void ConfigureServices(IServiceCollection services) { // Add framework services. service
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddAuthentication(options => {
options.SignInScheme = "ServerCookie";
});
services.AddApplicationInsightsTelemetry(Configuration);
services.AddMvc();
services.AddSession(options => {
options.IdleTimeout = TimeSpan.FromMinutes(30);
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, LoggerFactory loggerFactory)
{
app.UseOAuthValidation();
app.UseOpenIdConnectServer(options => {
// Create your own authorization provider by subclassing
// the OpenIdConnectServerProvider base class.
options.Provider = new AuthorizationProvider();
// Enable the authorization and token endpoints.
// options.AuthorizationEndpointPath = "/connect/authorize";
options.TokenEndpointPath = "/connect/token";
// During development, you can set AllowInsecureHttp
// to true to disable the HTTPS requirement.
options.ApplicationCanDisplayErrors = true;
options.AllowInsecureHttp = true;
// Note: uncomment this line to issue JWT tokens.
// options.AccessTokenHandler = new JwtSecurityTokenHandler();
});
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseApplicationInsightsRequestTelemetry();
app.UseApplicationInsightsExceptionTelemetry();
app.UseMvc();
}
这是我的AuthorizationProvider.cs
public sealed class AuthorizationProvider : OpenIdConnectServerProvider
{
public Task<User> GetUser()
{
return Task.Run(()=> new User { UserName = "biruk60", Password = "adminUser123" });
}
// Implement OnValidateAuthorizationRequest to support interactive flows (code/implicit/hybrid).
public override Task ValidateTokenRequest(ValidateTokenRequestContext context)
{
// Reject the token request that don't use grant_type=password or grant_type=refresh_token.
if (!context.Request.IsPasswordGrantType() && !context.Request.IsRefreshTokenGrantType())
{
context.Reject(
error: OpenIdConnectConstants.Errors.UnsupportedGrantType,
description: "Only resource owner password credentials and refresh token " +
"are accepted by this authorization server");
return Task.FromResult(0);
}
// Since there's only one application and since it's a public client
// (i.e a client that cannot keep its credentials private), call Skip()
// to inform the server the request should be accepted without
// enforcing client authentication.
context.Skip();
return Task.FromResult(0);
}
public override async Task HandleTokenRequest(HandleTokenRequestContext context)
{
//// Resolve ASP.NET Core Identity's user manager from the DI container.
//var manager = context.HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>();
// Only handle grant_type=password requests and let ASOS
// process grant_type=refresh_token requests automatically.
if (context.Request.IsPasswordGrantType())
{
// var user = await manager.FindByNameAsync(context.Request.Username);
var user = await GetUser();//new { userName = "briuk60@gmail.com", password = "adminUser123" };
if (user == null)
{
context.Reject(
error: OpenIdConnectConstants.Errors.InvalidGrant,
description: "Invalid credentials.");
return;
}
if (user != null && (user.Password == context.Request.Password))
{
var identity = new ClaimsIdentity(context.Options.AuthenticationScheme);
// Note: the name identifier is always included in both identity and
// access tokens, even if an explicit destination is not specified.
// identity.AddClaim(ClaimTypes.NameIdentifier, await manager.GetUserId(user));
// When adding custom claims, you MUST specify one or more destinations.
// Read "part 7" for more information about custom claims and scopes.
identity.AddClaim("username", "biruk60",
OpenIdConnectConstants.Destinations.AccessToken,
OpenIdConnectConstants.Destinations.IdentityToken);
// Create a new authentication ticket holding the user identity.
var ticket = new AuthenticationTicket(
new ClaimsPrincipal(identity),
new AuthenticationProperties(),
context.Options.AuthenticationScheme);
// Set the list of scopes granted to the client application.
ticket.SetScopes(
/* openid: */ OpenIdConnectConstants.Scopes.OpenId,
/* email: */ OpenIdConnectConstants.Scopes.Email,
/* profile: */ OpenIdConnectConstants.Scopes.Profile);
// Set the resource servers the access token should be issued for.
// ticket.SetResources("resource_server");
context.Validate(ticket);
}
}
}
}
公共密封类授权提供程序:OpenIdConnectServerProvider
{
公共任务GetUser()
{
返回Task.Run(()=>新用户{UserName=“biruk60”,Password=“adminUser123”});
}
//实现OnValidateAuthorizationRequest以支持交互流(代码/隐式/混合)。
公共覆盖任务ValidateTokenRequest(ValidateTokenRequestContext上下文)
{
//拒绝不使用grant\u type=password或grant\u type=refresh\u令牌的令牌请求。
如果(!context.Request.IsPasswordGrantType()&&!context.Request.IsRefreshTokenGrantType())
{
上下文。拒绝(
错误:OpenIdConnectConstants.Errors.UnsupportedGrantType,
描述:“仅资源所有者密码凭据和刷新令牌”+
“已被此授权服务器接受”);
返回Task.FromResult(0);
}
//因为只有一个应用程序,而且它是一个公共客户端
//(即无法将其凭据保持为私有的客户端),调用Skip()
//若要通知服务器,应接受请求,而无需
//强制客户端身份验证。
context.Skip();
返回Task.FromResult(0);
}
公共重写异步任务HandleTokenRequest(HandleTokenRequestContext)
{
////从DI容器解析ASP.NET核心标识的用户管理器。
//var manager=context.HttpContext.RequestServices.GetRequiredService();
//仅处理授权类型=密码请求,并允许ASO
//处理授权\类型=自动刷新\令牌请求。
if(context.Request.IsPasswordGrantType())
{
//var user=await manager.FindByNameAsync(context.Request.Username);
var user=await GetUser();//新建{userName=”briuk60@gmail.com,password=“adminUser123”};
if(user==null)
{
上下文。拒绝(
错误:OpenIdConnectConstants.Errors.InvalidGrant,
说明:“无效凭据。”);
返回;
}
if(user!=null&(user.Password==context.Request.Password))
{
var identity=newclaimsidentity(context.Options.AuthenticationScheme);
//注意:名称标识符始终包含在标识和
//访问令牌,即使未指定显式目标。
//AddClaim(ClaimTypes.NameIdentifier,wait manager.GetUserId(user));
//添加自定义声明时,必须指定一个或多个目标。
//有关自定义声明和范围的更多信息,请阅读“第7部分”。
identity.AddClaim(“用户名”,“biruk60”,
OpenIdConnectConstants.Destinations.AccessToken,
OpenIdConnectConstants.Destinations.IdentityToken);
//创建包含用户标识的新身份验证票证。
var票证=新的身份验证票证(
新索赔人(身份),
新建AuthenticationProperties(),
context.Options.AuthenticationScheme);
//设置授予客户端应用程序的作用域列表。
检票镜(
/*openid://OpenIdConnectConstants.Scopes.openid,
/*电子邮件:*/OpenIdConnectConstants.Scopes.email,
/*概要文件:*/OpenIdConnectConstants.Scopes.profile);
//设置应为其颁发访问令牌的资源服务器。
//ticket.SetResources(“资源_服务器”);
验证(票证);
}
}
}
}
我做错了什么。我可以将其置于调试模式,并在没有任何错误的情况下逐步执行它。fiddler和postman中只有500个内部服务器错误。以下是您可能看到的异常: System.InvalidOperationException:找不到生成“sub”声明的唯一标识符:请确保添加“ClaimTypes.NameIdentifier”声明
添加一个
ClaimTypes.NameIdentifier
claim,它应该可以工作。就是这样。谢谢凯文@基兰:恐怕你的问题与这个问题完全无关。您可能应该联系Microsoft,询问他们是否可以为您构建一个小样本。