【问题标题】:How do you pass JWT to service?你如何将 JWT 传递给服务?
【发布时间】:2019-08-12 09:18:01
【问题描述】:

在使用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]'d 控制器中我尝试在我的客户端上尝试的努力

[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 进行身份验证。

【问题讨论】:

    标签: c# asp.net-core oauth identityserver4 openid-connect


    【解决方案1】:

    看起来,你搞砸了不同的事情。在您的 API .AddIdentityServerAuthentication() is just a decorator 超过 AddJwtBearer() 中,因此对于您的情况(外部调用受 [Authorize] 保护的方法),它已经可以工作了。我猜你总是使用 JWT 并添加一个秘密,以便能够直接从 API 请求新令牌,而不是用于参考令牌验证?在这种情况下,您需要使用 TokenClient

    在您的 客户端 中,您只需在您的 HttpClient 实例上调用 SetBearerToken(apiAccessToken),而不是发送 cookie,但是您必须首先请求并保留该令牌。 This fresh article 包含指向 working example 的链接

    【讨论】:

    • 谢谢。这有很大帮助。我将根据您的链接使用我发现的内容更新我的答案。
    猜你喜欢
    • 1970-01-01
    • 2019-03-06
    • 2017-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-25
    • 1970-01-01
    • 2018-03-17
    相关资源
    最近更新 更多