Я использую приложение Blazor Server для аутентификации через Identity Server 4 с доступом к asp. net core 3.1 API. Локально у меня есть настройка, использующая Identity Server на порту 5000, API на 5001 и мое приложение Blazor на 5002.
На наших тестовых серверах мы разместили все три в IIS (Blazor на одном сервере, API и Identity Server по другому). Я получаю 401 Unauthorized при доступе к тегированному контроллеру Authorize Я могу войти в систему и знаю, что API все еще доступен, поскольку не все контроллеры должны авторизоваться, и эти данные поступают. Кроме того, я знаю, что есть токен, поскольку однажды я напечатал его на странице.
Что может быть причиной того, что API больше не принимает токен, сгенерированный Identity Server, в нашей тестовой среде?
Вот мои примеры кода, с радостью добавлю больше, если необходимо:
Авторизованный контроллер
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Route("api/[controller]")]
[ApiController]
public class Controller : ControllerBase
Ресурсы API
public static IEnumerable<ApiResource> Apis =>
new ApiResource[]
{
new ApiResource("Api", "MyApi")
};
Клиентский набор- up
public static IEnumerable<Client> Clients =>
new List<Client>
{
//Client
new Client
{
ClientId = "Client",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
// where to redirect to after login
RedirectUris = { "http://location:5002/signin-oidc" },
// where to redirect to after logout
PostLogoutRedirectUris = { "http://location:5002/signout-callback-oidc" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.OfflineAccess,
"Api"
},
AllowOfflineAccess = true
}
};
Конфигурация API
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = AuthUrl; // IS loc
options.Audience = "Api";
});
Конфигурация клиента
services.AddSingleton<IDiscoveryCache>(sp =>
{
var factory = sp.GetRequiredService<IHttpClientFactory>();
return new DiscoveryCache(
AuthUrl,
() => factory.CreateClient());
});
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.Authority = AuthUrl;
options.ClientId = ClientID;
options.ClientSecret = ClientSecret;
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
// part 3
options.Scope.Add("openid");
options.Scope.Add("offline_access");
options.Scope.Add("Api");
options.RequireHttpsMetadata = false;
});
Вот как я использовал учетные данные для подписи
// not recommended for production - you need to store your key material somewhere secure
if (Environment.IsDevelopment())
{
builder.AddDeveloperSigningCredential();
}
else
{
X509Certificate2 cert = null;
using (var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
certStore.Open(OpenFlags.ReadOnly);
var certCollection = certStore.Certificates.Find(
X509FindType.FindByThumbprint,
"76588d12094bc26991faf9e3eaaa241d973fe72f", // Change this with the thumbprint of your certificate
false);
if (certCollection.Count > 0)
{
cert = certCollection[0];
}
}
builder.AddSigningCredential(cert);
}
I Я использовал самозаверяющий сертификат, сгенерированный через openssl, и я также проверил это в среде разработчиков, не используя .developerssigningcredentials.