Как вы передаете JWT в сервис? - PullRequest
0 голосов
/ 21 марта 2019

В демонстрационной настройке веб-сайта «клиент» с потоком авторизации кода Я получаю JWT, подтверждающий личность моего пользователя, когда он успешно входит в систему от моего собственного локального поставщика удостоверений (IdentityServer4). Это сохраняется в виде файла 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. Когда я делаю запросы к своим нижестоящим веб-службам, я хочу передать этот JWT, чтобы они могли (независимо) проверять подлинность пользователя, а также независимо запрашивать, должен ли этот пользователь иметь разрешение на выполнение определенного действия API. Я также хочу, чтобы мои веб-службы принимали клиентские полномочия для аутентификации между компьютерами в тех случаях, когда это необходимо.

С помощью identityserver4 и .NET Core, как мне это сделать? Как я могу сделать мою аннотацию [Authorize] внутри моего веб-сервиса, чтобы различать два потока и изящно обрабатывать это? В моем демонстрационном веб-сервисе у меня нормально работает клиентский грант:

.AddIdentityServerAuthentication("token", options =>
                {
                    options.Authority = "https://localhost:5005";
                    options.RequireHttpsMetadata = false;

                    options.ApiName = "SomeAPI";
                    options.ApiSecret = "secret";
                });

1) Как я могу добавить в свой сервис второй метод аутентификации, который читает JWT с моего клиента? Это так же просто, как AddJwtBearer () при запуске? 2) Как в моем «клиенте» как я могу перехватить и отправить (чтобы сохранить) JWT моего авторизованного пользователя в другие службы?

Я думал, что это не сработает, а только для того, чтобы показать попытку того, что я имею в виду, с моего «клиентского» веб-сайта в контроллере [Authorize], который я пытался установить на моем клиенте

[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 из моего сервиса.

UPDATE

Получив некоторую помощь от 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.

1 Ответ

1 голос
/ 21 марта 2019

Похоже, ты испортил разные вещи. В вашем API .AddIdentityServerAuthentication() это просто декоратор over AddJwtBearer(), поэтому для вашего случая (с внешним вызовом метода, защищенного [Authorize]) он уже работает. Я полагаю, вы всегда используете JWT и добавляете секрет, чтобы иметь возможность запрашивать новый токен непосредственно из API, а не для проверки ссылочного токена? В этом случае вам нужно задействовать TokenClient .

В вашем клиенте вам просто нужно вызвать SetBearerToken(apiAccessToken) в вашем HttpClient экземпляре, а не отправлять cookie , но вы должны сначала запросить и сохранить этот токен. Эта свежая статья содержит ссылку на рабочий пример

...