如何修复OpenIddict 4.4.0中“远程授权服务器不可用或配置无效”错误
问题描述
- 环境:OpenIddict 4.4.0,部署授权服务器与资源服务器两个应用,通过Swagger测试
- 核心现象:资源服务器Swagger可成功完成授权并获取
access token,但使用该token访问受保护资源时触发异常:www-authenticate: Bearer error="server_error",error_description="The remote authorization server is currently unavailable or returned an invalid configuration.",error_uri="https://documentation.openiddict.com/errors/ID2170" - 降级测试:将OpenIddict版本降至4.0.0后,资源服务器启动时报错:
但Swagger仍可正常打开并获取tokenError description: An error occurred while communicating with the remote HTTP server. Error URI: https://documentation.openiddict.com/errors/ID2136
配置代码
资源服务器配置
using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using OpenIddict.Validation.AspNetCore; using Microsoft.IdentityModel.Logging; var builder = WebApplication.CreateBuilder(args); IdentityModelEventSource.ShowPII = true; builder.Services.AddControllers(); builder.Services.AddOpenIddict() .AddValidation(options => { options.SetIssuer("https://localhost:7200/"); options.AddAudiences("resource_server_1"); options.AddEncryptionKey(new SymmetricSecurityKey( Convert.FromBase64String("DRjd/GnduI3Efzen9V9BvbNUfc/VKgXltV7Kbk9sMkY="))); options.UseSystemNetHttp(); options.UseAspNetCore(); }); builder.Services.AddAuthentication(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme); builder.Services.AddAuthorization(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, Flows = new OpenApiOAuthFlows { AuthorizationCode = new OpenApiOAuthFlow { AuthorizationUrl = new Uri("https://localhost:7200/connect/authorize"), TokenUrl = new Uri("https://localhost:7200/connect/token"), Scopes = new Dictionary<string, string> { { "api1", "resource server scope" } } }, } }); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } }, Array.Empty<string>() } }); }); var app = builder.Build(); app.UseSwagger(); app.UseSwaggerUI(c => { c.OAuthClientId("web-client"); c.OAuthClientSecret("901564A5-E7FE-42CB-B10D-61EF6A8F3654"); }); app.UseHttpsRedirection(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
授权服务器配置
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using OidcAuthorizationServer; using static OpenIddict.Abstractions.OpenIddictConstants; var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext<ApplicationDbContext>(options => { options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")); options.UseOpenIddict<Guid>(); }); builder.Services.AddOpenIddict() .AddCore(options => { options .UseEntityFrameworkCore() .UseDbContext<ApplicationDbContext>() .ReplaceDefaultEntities<Guid>(); }) .AddServer(options => { options.SetAuthorizationEndpointUris("connect/authorize") .SetLogoutEndpointUris("connect/logout") .SetTokenEndpointUris("connect/token"); options.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles); options.AllowAuthorizationCodeFlow(); options.AddEncryptionKey(new SymmetricSecurityKey( Convert.FromBase64String("DRjd/GnduI3Efzen9V9BvbNUfc/VKgXltV7Kbk9sMkY="))); options.AddDevelopmentEncryptionCertificate() .AddDevelopmentSigningCertificate(); options.UseAspNetCore() .EnableAuthorizationEndpointPassthrough() .EnableLogoutEndpointPassthrough() .EnableTokenEndpointPassthrough(); }); builder.Services.AddTransient<AuthorizationService>(); builder.Services.AddControllers(); builder.Services.AddRazorPages(); // FIXME спецификация определяет способ аутентификации владельца ресурсов, поэтому использование COOKIE не обязательно builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(c => { c.LoginPath = "/Authenticate"; }); builder.Services.AddTransient<ClientsSeeder>(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddCors(options => { options.AddDefaultPolicy(policy => { policy.WithOrigins("https://localhost:7201") .AllowAnyHeader(); }); }); var app = builder.Build(); using (var scope = app.Services.CreateScope()) { var seeder = scope.ServiceProvider.GetRequiredService<ClientsSeeder>(); seeder.AddClients().GetAwaiter().GetResult(); seeder.AddScopes().GetAwaiter().GetResult(); } if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.MapRazorPages(); app.Run();
排查与解决方案
1. 修复授权服务器元数据端点缺失问题
ID2170/ID2136的核心原因是授权服务器未启用OpenID Connect元数据端点,导致资源服务器无法获取验证所需的配置信息(如签名密钥、端点地址等)。需在授权服务器的AddServer配置中添加:
.AddServer(options => { // 原有端点配置... options.EnableDiscoveryEndpoint(); // 新增:启用元数据端点,路径默认为/.well-known/openid-configuration })
添加后,可直接访问https://localhost:7200/.well-known/openid-configuration验证是否返回合法的JSON配置。
2. 修正资源服务器认证配置
确保资源服务器的认证中间件默认方案正确绑定到OpenIddict验证:
builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme; });
3. 调整CORS策略(开发环境)
授权服务器的CORS需允许资源服务器发起元数据请求,可放宽策略:
builder.Services.AddCors(options => { options.AddDefaultPolicy(policy => { policy.WithOrigins("https://localhost:7201") .AllowAnyHeader() .AllowAnyMethod(); }); });
4. 版本兼容注意事项
- 4.4.0版本对元数据端点的依赖更强,缺失会直接导致token验证失败
- 4.0.0版本启动时的ID2136报错,本质也是元数据端点不可用,修复后即可消除
内容的提问来源于stack exchange,提问作者Alexander
相关产品推荐
相关产品推荐

