如何从Angular2触发的WebApi1中调用受保护的WebApi2并获取Bearer Token
在WebApi1中调用受保护的WebApi2:获取Bearer令牌的方案
首先,你的场景是典型的用户上下文下的服务间调用——用户已通过Angular应用完成认证,WebApi1需要代表该用户调用另一个受保护的WebApi2。下面分两种常见场景给出具体实现方案:
方案1:直接转发Angular传来的访问令牌(简单场景)
如果你的WebApi1的访问令牌本身已经包含了访问WebApi2所需的权限(即令牌的scope字段包含WebApi2的授权范围),那么最直接的方式就是转发这个令牌给WebApi2。
实现步骤:
- 从WebApi1的请求中提取令牌
当Angular调用WebApi1时,会在请求头里带上Authorization: Bearer {token}(通常你已经用Angular的HttpInterceptor自动添加了这个头)。在WebApi1中,你可以直接从请求上下文获取这个令牌:// 以ASP.NET Core为例 var accessToken = await HttpContext.GetTokenAsync("access_token"); - 用转发的令牌调用WebApi2
把提取到的令牌添加到调用WebApi2的请求头中:using var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var response = await client.GetAsync("https://your-webapi2-url/api/your-resource");
注意事项:
- 这个方案仅适用于原令牌已被授权访问WebApi2的情况,否则WebApi2会返回
403 Forbidden。 - 确保原令牌的
aud(受众)包含WebApi2的标识,或者身份提供者支持令牌的多受众访问。
方案2:使用On-Behalf-Of(OBO)流获取专用令牌(推荐场景)
如果WebApi1的令牌没有访问WebApi2的权限,或者你希望遵循最小权限原则(不给WebApi1过度授权),那么应该使用OBO流——让WebApi1拿着用户的原令牌,向身份提供者请求一个专门用于访问WebApi2的新令牌。
实现步骤:
提前配置身份提供者
- 在你的身份提供者(比如IdentityServer4、Azure AD等)中,为WebApi1注册一个客户端(机密客户端,因为服务间调用需要信任)。
- 给WebApi1授予“代表用户访问WebApi2”的权限(即添加WebApi2的scope到WebApi1的授权列表中)。
在WebApi1中发起OBO令牌请求
先提取Angular传来的原令牌,然后向身份提供者的令牌端点请求新令牌:// 先安装IdentityModel包(用于简化OAuth2操作) using IdentityModel.Client; // 1. 获取身份提供者的元数据 var client = new HttpClient(); var disco = await client.GetDiscoveryDocumentAsync("https://your-identity-provider-url"); if (disco.IsError) throw new Exception($"Discovery failed: {disco.Error}"); // 2. 提取Angular传来的原令牌 var originalToken = await HttpContext.GetTokenAsync("access_token"); // 3. 发起OBO令牌请求 var tokenResponse = await client.RequestTokenAsync(new TokenRequest { Address = disco.TokenEndpoint, GrantType = "urn:ietf:params:oauth:grant-type:jwt-bearer", ClientId = "webapi1-client-id", // 你在身份提供者注册的WebApi1客户端ID ClientSecret = "webapi1-client-secret", // 客户端密钥(机密客户端必填) Parameters = { { "token", originalToken }, // 用户的原访问令牌 { "scope", "webapi2-required-scope" }, // WebApi2需要的权限范围 { "resource", "webapi2-audience" } // 如果是Azure AD,需要指定WebApi2的受众标识 } }); if (tokenResponse.IsError) throw new Exception($"Token request failed: {tokenResponse.Error}"); // 4. 使用新令牌调用WebApi2 using var webApi2Client = new HttpClient(); webApi2Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenResponse.AccessToken); var response = await webApi2Client.GetAsync("https://your-webapi2-url/api/your-resource");
注意事项:
- OBO流是专门为“服务代表用户调用其他服务”设计的,安全性更高,权限更可控。
- 确保原令牌是访问令牌(不是ID令牌),因为ID令牌不能用于OBO流。
- 身份提供者需要支持OBO流(主流的OAuth2/OIDC实现都支持,比如IdentityServer4、Azure AD、Okta等)。
额外提示
- 不管用哪种方案,WebApi1都要先验证原令牌的有效性(比如签名是否合法、是否过期、受众是否正确),避免使用伪造的令牌。在ASP.NET Core中,只要你正确配置了JWT认证中间件,这个验证会自动完成。
- Angular中存储在
localStorage的令牌,一定要通过HttpInterceptor自动添加到所有对WebApi1的请求头中,确保WebApi1能拿到令牌。
内容的提问来源于stack exchange,提问作者Mukil Deepthi
相关产品推荐
相关产品推荐

