Я попытался найти, но, к удивлению, не могу найти ответ на свой вопрос.
Я занимаюсь разработкой веб-приложения, которое будет иметь интерфейс интерфейса через Angular с несколькими API-интерфейсами для нисходящего потока. Как ниже:
[API - A Client] -> [API - A] -> [API - B]
Я использую IdentityServer4 для аутентификации / авторизации. У некоторых пользователей будет определенное утверждение, давайте назовем его «Foo», и это утверждение будет правильно передано с сервера аутентификации в API A (с использованием неявного потока) при взаимодействии с API A через клиент SPA.
Однако я не могу передать это утверждение из API A в API B, который использует учетные данные клиента. Из того, что я прочитал / изучил, это похоже на правильное поведение, поскольку его поток клиентских учетных данных.
Итак, мой вопрос, как я могу передать претензию пользователя ("Foo") вниз по течению к API второго уровня (API-B)? мне нужно использовать другой поток? Должен ли API-A вручную передавать его по запросу в API-B?
Я впервые использую IdentityServer / OpenID connect / OAuth, я открыт для изменений.
IdentityServer4 Config
public class Config
{
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("API-B", "API B")
{
UserClaims = { "Foo" }
},
new ApiResource("API-A", "API A")
{
ApiSecrets = {new Secret("Secret") },
UserClaims = { "Foo", },
}
};
}
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientName = "API-A Client",
ClientId = "API-A_client",
AllowedGrantTypes = GrantTypes.Implicit,
RedirectUris = { "http://localhost:7900/swagger/oauth2-redirect.html" },
PostLogoutRedirectUris = { "http://localhost:7900/" },
RequireConsent = false,
AllowAccessTokensViaBrowser = true,
AllowedScopes = new List<string>(){
"API-A",
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
},
new Client
{
ClientName = "API-A Backend",
ClientId = "API-A_backend",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets = {new Secret("Secret".Sha256()) },
AllowedScopes = new List<string>()
{
"API-B",
"custom_resource",
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
},
AlwaysIncludeUserClaimsInIdToken = true,
AlwaysSendClientClaims = true,
}
};
}
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResource("custom_resource", new [] { "Foo" }),
};
}
}
API A Auth Config
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:6900";
options.ApiName = "API-A";
options.RequireHttpsMetadata = false; // dev only!
});
services.AddTransient<AccessTokenDelegatingHandler>((service) => new AccessTokenDelegatingHandler(tokenEndpoint: $"http://localhost:6900/connect/token", clientId: "API-A", clientSecret: "Secret", scope: "API-B"));
services.AddHttpClient<ApiBHttpClient>(client =>
{
client.BaseAddress = new Uri(Configuration["ApiBUri"]);
client.DefaultRequestHeaders.Add("Accept", "application/json");
})
.AddHttpMessageHandler<AccessTokenDelegatingHandler>();
API B Auth Config
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:6900";
options.ApiName = "API-B"; // required audience of access tokens
options.RequireHttpsMetadata = false; // dev only!
options.ApiSecret = "Secret";
});
Результат выше - API-A правильно получает доступ к «Foo» через IdentityClaims, а API-B - нет (хотя вызов успешен).
Любая помощь приветствуется!