OpenIdDict 3.0 在控制器中接受 ID 令牌而不是访问令牌
OpenIdDict 3.0 Accepting Id Token instead of Access Token in Controllers
我正在使用 OpenIdDict 3.0 来托管我的身份服务器。我能够获得访问令牌和 ID 令牌,但是当我在授权中使用访问令牌时,我的控制器以某种方式返回 401 header,但当我使用 ID 令牌时成功通过了身份验证。
我在之前的项目中使用过 OpenIdDict 2.0,效果很好。
以下是我的Start.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
#region Database
var connectionString = Environment.GetEnvironmentVariable("CONNECTION_STRING");
#if DEBUG
connectionString = Configuration.GetConnectionString("DefaultConnection");
#endif
services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseMySql(connectionString);
// Register the entity sets needed by OpenIddict.
// Note: use the generic overload if you need
// to replace the default OpenIddict entities.
options.UseOpenIddict();
});
#endregion
#region Authentication
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = Configuration["Jwt:Authority"];
options.Audience = Configuration["Jwt:Audience"];
options.RequireHttpsMetadata = bool.TryParse(Configuration["Jwt:Https"], out bool isHttps) && isHttps;
});
// Configure Identity to use the same JWT claims as OpenIddict instead
// of the legacy WS-Federation claims it uses by default (ClaimTypes),
// which saves you from doing the mapping in your authorization controller.
services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.UserNameClaimType = ClaimTypes.Name;
options.ClaimsIdentity.UserIdClaimType = JwtRegisteredClaimNames.Sub;
options.ClaimsIdentity.RoleClaimType = ClaimTypes.Role;
});
services.AddOpenIddict()
// Register the OpenIddict core components.
.AddCore(options =>
{
// Configure OpenIddict to use the Entity Framework Core stores and models.
// Note: call ReplaceDefaultEntities() to replace the default entities.
options.UseEntityFrameworkCore()
.UseDbContext<ApplicationDbContext>();
})
// Register the OpenIddict server components.
.AddServer(options =>
{
// Enable the token endpoint.
// Enable the client credentials flow.
options
.SetTokenEndpointUris("/Account/Token")
.AllowPasswordFlow()
.SetAccessTokenLifetime(TimeSpan.FromHours(1))
.AllowRefreshTokenFlow()
.SetRefreshTokenLifetime(TimeSpan.FromDays(7));
// Register the signing and encryption credentials.
options
.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
options.RegisterClaims();
// Register the ASP.NET Core host and configure the ASP.NET Core options.
options
.UseAspNetCore()
.EnableTokenEndpointPassthrough();
})
// Register the OpenIddict validation components.
.AddValidation(options =>
{
// Import the configuration from the local OpenIddict server instance.
options.UseLocalServer();
// Register the ASP.NET Core host.
options.UseAspNetCore();
});
#endregion
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseMyPcBuilderOpenIdDict().Wait();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
您的配置无效:您正在注册 JWT 处理程序和 OpenIddict 验证处理程序。
与 JWT 处理程序不同,OpenIddict 验证处理程序可以导入用于保护服务器颁发的访问令牌的加密密钥(感谢 UseLocalServer()
)。由于 JWT 处理程序没有等效方法,因此它无法解密您的访问令牌。
OpenIddict 验证处理程序还附带内置 typ
令牌类型验证,以确保身份令牌永远不会被 API 端点接受。这不是 JWT 处理程序所做的事情。
将 JwtBearerDefaults.AuthenticationScheme
替换为 OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme
,事情就会正常进行。
我正在使用 OpenIdDict 3.0 来托管我的身份服务器。我能够获得访问令牌和 ID 令牌,但是当我在授权中使用访问令牌时,我的控制器以某种方式返回 401 header,但当我使用 ID 令牌时成功通过了身份验证。
我在之前的项目中使用过 OpenIdDict 2.0,效果很好。
以下是我的Start.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
#region Database
var connectionString = Environment.GetEnvironmentVariable("CONNECTION_STRING");
#if DEBUG
connectionString = Configuration.GetConnectionString("DefaultConnection");
#endif
services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseMySql(connectionString);
// Register the entity sets needed by OpenIddict.
// Note: use the generic overload if you need
// to replace the default OpenIddict entities.
options.UseOpenIddict();
});
#endregion
#region Authentication
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = Configuration["Jwt:Authority"];
options.Audience = Configuration["Jwt:Audience"];
options.RequireHttpsMetadata = bool.TryParse(Configuration["Jwt:Https"], out bool isHttps) && isHttps;
});
// Configure Identity to use the same JWT claims as OpenIddict instead
// of the legacy WS-Federation claims it uses by default (ClaimTypes),
// which saves you from doing the mapping in your authorization controller.
services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.UserNameClaimType = ClaimTypes.Name;
options.ClaimsIdentity.UserIdClaimType = JwtRegisteredClaimNames.Sub;
options.ClaimsIdentity.RoleClaimType = ClaimTypes.Role;
});
services.AddOpenIddict()
// Register the OpenIddict core components.
.AddCore(options =>
{
// Configure OpenIddict to use the Entity Framework Core stores and models.
// Note: call ReplaceDefaultEntities() to replace the default entities.
options.UseEntityFrameworkCore()
.UseDbContext<ApplicationDbContext>();
})
// Register the OpenIddict server components.
.AddServer(options =>
{
// Enable the token endpoint.
// Enable the client credentials flow.
options
.SetTokenEndpointUris("/Account/Token")
.AllowPasswordFlow()
.SetAccessTokenLifetime(TimeSpan.FromHours(1))
.AllowRefreshTokenFlow()
.SetRefreshTokenLifetime(TimeSpan.FromDays(7));
// Register the signing and encryption credentials.
options
.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
options.RegisterClaims();
// Register the ASP.NET Core host and configure the ASP.NET Core options.
options
.UseAspNetCore()
.EnableTokenEndpointPassthrough();
})
// Register the OpenIddict validation components.
.AddValidation(options =>
{
// Import the configuration from the local OpenIddict server instance.
options.UseLocalServer();
// Register the ASP.NET Core host.
options.UseAspNetCore();
});
#endregion
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseMyPcBuilderOpenIdDict().Wait();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
您的配置无效:您正在注册 JWT 处理程序和 OpenIddict 验证处理程序。
与 JWT 处理程序不同,OpenIddict 验证处理程序可以导入用于保护服务器颁发的访问令牌的加密密钥(感谢 UseLocalServer()
)。由于 JWT 处理程序没有等效方法,因此它无法解密您的访问令牌。
OpenIddict 验证处理程序还附带内置 typ
令牌类型验证,以确保身份令牌永远不会被 API 端点接受。这不是 JWT 处理程序所做的事情。
将 JwtBearerDefaults.AuthenticationScheme
替换为 OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme
,事情就会正常进行。