在使用code authorization flow的演示“客户端”网站中,当用户成功从我自己的本地身份提供者(IdentityServer4)登录时,我收到一个JWT声明用户的身份。它将存储为如下所示的Cookie(用...缩写):
ai_user = kFgLY | 2018-12-11T15:40:11.940Z; AMCV_700CFDC5570CBFE67F000101%40AdobeOrg = 2121618341%7CMCIDTS%7 ... ywuxL1PHcA
客户端站点的配置如下:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "cookie";
options.DefaultSignInScheme = "cookie";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("cookie")
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "https://localhost:5005";
options.RequireHttpsMetadata = false;
options.RemoteAuthenticationTimeout = TimeSpan.FromMinutes(15);
options.ClientId = "test_pkce_client";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.ResponseMode = "form_post";
options.CallbackPath = "/signin-test";
options.GetClaimsFromUserInfoEndpoint = true;
options.Events.OnRedirectToIdentityProvider = context => HandleRedirectToIDP(context);
options.Events.OnAuthorizationCodeReceived = context => HandleCodeReceived(context);
});
但是,当用户进行身份验证时,我想捕获该JWT。当我向下游Web服务发出请求时,我希望传递该JWT,以便它们可以(独立)验证用户的身份验证,还可以独立查询该用户是否应有权执行给定的API操作。我还希望我的Web服务在必要时接受client credentials grant进行机器对机器的身份验证。
使用identityserver4和.NET Core,我该如何完成?如何使我的Web服务中的[Authorize]批注区分这两个流并妥善处理?在我的演示Web服务中,我的客户端凭据授予工作正常:
.AddIdentityServerAuthentication("token", options =>
{
options.Authority = "https://localhost:5005";
options.RequireHttpsMetadata = false;
options.ApiName = "SomeAPI";
options.ApiSecret = "secret";
});
1)在我的服务中,如何添加从客户端读取JWT的第二种身份验证方法?就像启动中的 AddJwtBearer()一样简单吗? 2)在我的“客户端”中,我如何捕获并发送(以保留)授权用户的JWT到其他服务?
我认为这是行不通的,只是为了展示我的意思,这是从我在客户端上尝试过的[授权]控制器中的“客户端”网站上进行的尝试
[Authorize]
public IActionResult SecurePage()
{
var client = new System.Net.Http.HttpClient();
client.BaseAddress = new System.Uri("https://localhost:3721/");
client.DefaultRequestHeaders.Add("Cookie", Request.Headers["Cookie"].First());
var apiTask = client.GetAsync("Test");
apiTask.Wait();
string response = apiTask.Result.Content.ReadAsStringAsync().Result;
这显然是我提供的401。
在得到d_f的帮助之后,我将上面的伪劣想法翻译为:
[Authorize]
public async Task<IActionResult> SecurePage()
{
string accessToken = await HttpContext.GetTokenAsync("cookie", "access_token");
string idToken = await HttpContext.GetTokenAsync("cookie", "id_token");
var client = new System.Net.Http.HttpClient();
client.BaseAddress = new System.Uri("https://localhost:3721/");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var apiTask = client.GetAsync("Test");
apiTask.Wait();
string response = apiTask.Result.Content.ReadAsStringAsync().Result;
诀窍是将用户的accessToken视为客户端凭据授予令牌。另外,请确保客户端启动中的AddOpenIdConnect为 options.SaveTokens = true; ,并且确保您的ResponseType为 options.ResponseType =“ code id_token”; ,这将允许使用API具有 .AddIdentityServerAuthentication(“ token”,options => 来读取您的请求并根据IDP对其进行身份验证。
答案 0 :(得分:1)
看起来,您搞砸了不同的事情。在.AddIdentityServerAuthentication()
上的 API AddJwtBearer()
is just a decorator中,因此对于您的情况(通过外部调用受[Authorize]
保护的方法),它已经可以工作了。我猜您总是使用JWT并添加了一个秘密,以便能够直接从API请求新令牌,而不是用于参考令牌验证?在这种情况下,您需要参与TokenClient。
在您的客户中,您只需要在SetBearerToken(apiAccessToken)
实例上调用HttpClient
,而不是发送Cookie,但是您必须先请求并保留该令牌。 This fresh article包含指向working example