У меня есть API, защищенный Azure AD, к которому я пытаюсь получить доступ из приложения MVC.Это приложение MVC использует IdentityServer4 в качестве IDP, а Azure AD настроен в качестве внешнего поставщика.Я не могу вызвать API с токеном доступа, полученным из Azure AD.
Вот мои настройки.Грубый эскиз, чтобы показать, что я делаю
Конфигурация Azure
- API настроен как приложение в Azure AD (для простоты, скажем, appId: API)
- IdentityServer настроен как приложение с идентификатором токена и включенным токеном доступа.Добавлены разрешения для API (скажем, appId: IDSRV)
IdentityServer4 Configuration:
Startup.cs - ConfigureServices
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetUsers());
services.AddAuthentication()
.AddOpenIdConnect("oidc", "Azure AD", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.Authority = "https://login.microsoftonline.com/tenant.onmicrosoft.com/";
options.ClientId = "IDSRV";
options.Resource = "API"; //Identity server uses scopes but Azure AD expects this as a Resource. Not sure if this is the right way
options.ClientSecret = "secret from azure";
options.ResponseType = "code id_token";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
Я использую в памяти клиентов для тестирования
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedGrantTypes = GrantTypes.Hybrid,
RedirectUris = { "http://localhost:49341/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:49341/signout-callback-oidc" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"API" //assume this is the appId from Azure
}
}
};
}
Конфигурация ресурсов API: я думаю, это используется только на экране согласия
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("API","Test API")
};
}
Конфигурация веб-клиента: (Это клиент для Identiserver4 и ему необходим доступ к API)
Startup.cs - ConfigureServices
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.SaveTokens = true;
options.ResponseType = "code id_token";
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("API");
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.Resource = "b03d4318-278d-40fc-b6b3-3cf47a0e6f4d";//I guess this is actually irrelevant.
});
При аутентификации нет ошибок, но я получаю несанкционированную ошибку, если пытаюсь получить доступ к API с полученным доступом.
Мне удалось настроить другой тестовый клиент напрямую с помощью Azure Ad и получить доступAPI, использующий полученный токен.
Теперь у меня есть два вопроса:
- Что-то не так с этой конфигурацией?
- Как динамически добавить Resource / Scopeот клиента к исходящему запросу Azure в IdentitySerвер?