IdentityServer4 Hybrid模式下多OpenIDConnect实例访问API问题
我之前也折腾过IdentityServer4 Hybrid模式扩展API的场景,给你梳理下完整的配置步骤,确保你的新.NET Core 2 Web API能被现有客户端正常访问:
首先得让IdentityServer识别这个新API是受保护的资源,同时授权现有Hybrid客户端访问它:
注册新的ApiResource
在IdentityServer的配置类(一般是Config.cs)里,给GetApiResources()方法添加新的API资源:
public static IEnumerable<ApiResource> GetApiResources() { return new List<ApiResource> { // 保留原有的API资源 new ApiResource("api1", "原有业务API"), // 新增你的.NET Core 2 Web API资源 new ApiResource("new_api", "新的后台服务API") { // 按需添加需要传递给API的用户声明,比如姓名、邮箱 UserClaims = { JwtClaimTypes.Name, JwtClaimTypes.Email } } }; }
授权客户端访问新API
同样在Config.cs的GetClients()方法里,给你的Hybrid客户端添加新API的访问权限:
public static IEnumerable<Client> GetClients() { return new List<Client> { new Client { ClientId = "hybrid_client", // 你的客户端ID,保持和现有配置一致 ClientName = "Hybrid模式客户端", AllowedGrantTypes = GrantTypes.Hybrid, ClientSecrets = { new Secret("your_client_secret".Sha256()) }, // 保留原有的回调、退出地址配置 RedirectUris = { "https://your-client-domain/signin-oidc" }, PostLogoutRedirectUris = { "https://your-client-domain/signout-callback-oidc" }, AllowedScopes = new List<string> { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile, "api1", "new_api" // 新增这个Scope,允许客户端访问新API }, AllowOfflineAccess = true, // 如果需要刷新令牌,保持开启 RequirePkce = false // Hybrid模式下通常关闭Pkce } }; }
让新API信任你的IdentityServer,并验证请求中的令牌:
添加认证服务
在新API的Startup.cs的ConfigureServices方法中,配置JWT认证:
public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); // 添加Bearer认证 services.AddAuthentication("Bearer") .AddJwtBearer("Bearer", options => { options.Authority = "https://your-identityserver-domain"; // 你的IdentityServer地址 options.RequireHttpsMetadata = true; // 生产环境必须设为true options.Audience = "new_api"; // 必须和之前注册的ApiResource名称完全一致 }); }
启用认证中间件
在Configure方法中,把认证中间件放在UseMvc之前:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseHttpsRedirection(); app.UseAuthentication(); // 启用认证,必须在UseMvc之前 app.UseMvc(); }
保护API接口
在需要保护的控制器或方法上添加[Authorize]特性:
[Authorize] [Route("api/[controller]")] [ApiController] public class DataController : ControllerBase { // 你的API业务方法 [HttpGet] public IActionResult Get() { return Ok(new { message = "新API的受保护数据" }); } }
你的客户端是Angular+.NET Core的组合,需要确保客户端能获取到新API的访问令牌,并在调用时携带:
更新客户端的OpenIdConnect配置
在客户端的Startup.cs中,给OpenIdConnect配置添加新的Scope,并开启令牌保存:
services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie() .AddOpenIdConnect(options => { options.Authority = Configuration["IdentityServer:Authority"]; options.ClientId = Configuration["IdentityServer:ClientId"]; options.ClientSecret = Configuration["IdentityServer:ClientSecret"]; options.ResponseType = "code id_token"; // Hybrid模式的标准响应类型 // 添加需要的Scope options.Scope.Add("openid"); options.Scope.Add("profile"); options.Scope.Add("api1"); options.Scope.Add("new_api"); // 新增新API的Scope options.Scope.Add("offline_access"); // 允许获取刷新令牌 options.SaveTokens = true; // 将令牌保存到Cookie,方便后续获取 });
调用新API的示例代码
在客户端的后端(比如API控制器)中,获取令牌并调用新API:
private async Task<string> GetNewApiAccessToken() { // 从Cookie中获取访问令牌 var accessToken = await HttpContext.GetTokenAsync("access_token"); // 如果有多个API,可指定Scope获取对应令牌:await HttpContext.GetTokenAsync("access_token", "new_api") return accessToken; } public async Task<IActionResult> FetchNewApiData() { var token = await GetNewApiAccessToken(); using var httpClient = new HttpClient(); httpClient.SetBearerToken(token); var response = await httpClient.GetAsync("https://your-new-api-domain/api/data"); if (response.IsSuccessStatusCode) { var data = await response.Content.ReadAsStringAsync(); return Ok(data); } return BadRequest("调用新API失败"); }
如果是Angular前端直接调用新API,可通过oidc-client库从客户端直接管理令牌,在请求头中添加Authorization: Bearer {token}即可。
按以下顺序启动服务,验证是否正常工作:
- 启动IdentityServer
- 启动新的.NET Core 2 Web API
- 启动Hybrid客户端
登录客户端后尝试访问新API,可通过https://your-identityserver-domain/.well-known/openid-configuration查看Discovery文档,确认new_apiScope已存在;用jwt.io解析令牌,确认aud字段包含new_api。
内容的提问来源于stack exchange,提问作者Tzvi Gregory Kaidanov

