В демонстрационной настройке веб-сайта «клиент» с потоком авторизации кода Я получаю 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.