Versuch, ein Token mithilfe von Introspection-Endpunkt auf IdentityServer4 zu validieren. Ich bekomme immer eine 401: Nicht autorisiert. Mein Protokoll sieht wie folgt aus:IdentityServer4 Introspection-Endpunkt-API verwendet ungültigen Hashalgorithmus
dbug: IdentityServer4.EntityFramework.Stores.ResourceStore[0]
Found MyAPI API resource in database
info: IdentityServer4.Validation.HashedSharedSecretValidator[0]
Secret: MyAPI API uses invalid hashing algorithm.
dbug: IdentityServer4.Validation.SecretValidator[0]
Secret validators could not validate secret
fail: IdentityServer4.Validation.ApiSecretValidator[0]
API validation failed.
fail: IdentityServer4.Endpoints.IntrospectionEndpoint[0]
API unauthorized to call introspection endpoint. aborting.
Meine API ist wie so konfiguriert:
new ApiResource
{
Name = "MyAPI",
DisplayName = "My API",
ApiSecrets =
{
new Secret("TopSecret".Sha256())
},
}
ich vorbei Header für Inhaltstyp als application/x-www-form-urlencoded und Zulassung als Grund XXXXXXXXXXXXXXXXX Dabei steht x für meine Base64-kodierte Auth-Zeichenfolge (myapi: TopSecret). Mein Token ist im Körper der Post
Was fehlt mir? Warum bekomme ich "MyAPI API verwendet ungültigen Hashalgorithmus"? Wenn es ungültig ist, was ist ein gültiger Hashing-Algorithmus?
Weitere Informationen: Meine Ressourcen sind in einer SQL-Datenbank enthalten, auf die über Entity Framework zugegriffen wird. Das Setup ist genau das gleiche wie in der Quickstart-Dokumentation here. Um zu dem Punkt zu kommen, an dem ich bin, musste ich meine API manuell zur ApiSecrets-Tabelle hinzufügen und ihr einen Typ (SharedSecret) und einen Wert geben, der ein Sha256-Passwort ist.
In Startup.cs meine COnfigureServices umfasst
services.AddIdentityServer()
.AddTemporarySigningCredential()
.AddInMemoryApiResources(Configurations.Scopes.GetApiResources())
.AddInMemoryClients(Configurations.Clients.GetClients())
.AddConfigurationStore(builder =>
builder.UseSqlServer(connectionString, options =>
options.MigrationsAssembly(migrationsAssembly)))
.AddOperationalStore(builder =>
builder.UseSqlServer(connectionString, options =>
options.MigrationsAssembly(migrationsAssembly)));
// include the password validation routine
services.AddTransient<IResourceOwnerPasswordValidator, Configurations.ResourceOwnerPasswordValidator>();
services.AddTransient<IProfileService, Configurations.ProfileService>();
services.AddMvc();
Unter Configure:
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
ApiSecret = "TopSecret",
AutomaticAuthenticate = true,
AutomaticChallenge = false,
ApiName = "MyAPI"
});
InitializeDatabase(app);
app.UseIdentityServer();
app.UseMvc();
Bitte beachte, dass ich die ApiSecret, AutomaticAuthenticate und AutomaticChallenge nur diesem Abschnitt hinzugefügt, nachdem ich begann ein Problem mit Anstrengung, damit es funktioniert.
In meinem Scopes.cs habe ich die folgende API beschrieben:
public static IEnumerable<ApiResource> GetApiResources()
{
return new[]
{
new ApiResource
{
Name = "MyAPI",
DisplayName = "My API",
ApiSecrets =
{
new Secret("TopSecret".Sha256()),
},
}
};
}
Für Clients.cs:
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientName = "My Client",
AlwaysSendClientClaims=true,
ClientId = "MyClient",
ClientSecrets = { new Secret("TopSecret".Sha256()) },
RequireClientSecret=false,
AllowAccessTokensViaBrowser =true,
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
AllowedScopes = { "MyAPI" },
RequireConsent = false,
AllowOfflineAccess = true,
},
, dass mehr oder weniger alles, um den Code Teil besteht. Die Datenbank, in der sich die Konfiguration befindet, scheint alle Codeänderungen außer Kraft zu setzen, die ich mache, daher bin ich mir nicht sicher, wie nützlich das alles ist. In der DB habe ich einen Datensatz in der ApiSecrets-Tabelle mit einer ApiResourceId von 1 erstellt, eine Beschreibung und ein Ablaufdatum hinzugefügt, den Typ auf "SharedSecret" gesetzt und das Secret mit verschiedenen Formaten wie Klartext, sha256 und base64 hinzugefügt.
Hier ist das vollständige Protokoll während des Anrufs. Vielleicht wird es helfen. Ich sehe, dass es einige Dinge darüber gibt, dass Träger nicht gefunden wird oder so etwas, aber ich bin mir nicht sicher, warum das so sein sollte und ob es das Ergebnis des Verfahrens beeinflusst.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 29.4277ms 401
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 POST http://localhost:5000/connect/introspect application/x-www-form-urlencoded 762
info: IdentityServer4.AccessTokenValidation.Infrastructure.NopAuthenticationMiddleware[7]
Bearer was not authenticated. Failure message: No token found.
dbug: IdentityServer4.CorsPolicyProvider[0]
CORS request made for path: /connect/introspect from origin: chrome-extension://aicmkgpgakddgnaphhhpliifpcfhicfo but rejected because invalid CORS path
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[7]
idsrv was not authenticated. Failure message: Unprotect ticket failed
dbug: IdentityServer4.Hosting.EndpointRouter[0]
Request path /connect/introspect matched to endpoint type Introspection
dbug: IdentityServer4.Hosting.EndpointRouter[0]
Mapping found for endpoint: Introspection, creating handler: IdentityServer4.Endpoints.IntrospectionEndpoint
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.IntrospectionEndpoint for /connect/introspect
dbug: IdentityServer4.Endpoints.IntrospectionEndpoint[0]
Starting introspection request.
dbug: IdentityServer4.Validation.BasicAuthenticationSecretParser[0]
Start parsing Basic Authentication secret
dbug: IdentityServer4.Validation.SecretParser[0]
Parser found secret: BasicAuthenticationSecretParser
dbug: IdentityServer4.Validation.SecretParser[0]
Secret id found: MyAPI
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (0ms) [Parameters=[@__name_0='?' (Size = 200)], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [apiResource].[Id], [apiResource].[Description], [apiResource].[DisplayName], [apiResource].[Enabled], [apiResource].[Name]
FROM [ApiResources] AS [apiResource]
WHERE [apiResource].[Name] = @__name_0
ORDER BY [apiResource].[Id]
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (0ms) [Parameters=[@__name_0='?' (Size = 200)], CommandType='Text', CommandTimeout='30']
SELECT [a3].[Id], [a3].[ApiResourceId], [a3].[Type]
FROM [ApiClaims] AS [a3]
INNER JOIN (
SELECT DISTINCT TOP(1) [apiResource].[Id]
FROM [ApiResources] AS [apiResource]
WHERE [apiResource].[Name] = @__name_0
ORDER BY [apiResource].[Id]
) AS [apiResource2] ON [a3].[ApiResourceId] = [apiResource2].[Id]
ORDER BY [apiResource2].[Id]
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (0ms) [Parameters=[@__name_0='?' (Size = 200)], CommandType='Text', CommandTimeout='30']
SELECT [a2].[Id], [a2].[ApiResourceId], [a2].[Description], [a2].[Expiration], [a2].[Type], [a2].[Value]
FROM [ApiSecrets] AS [a2]
INNER JOIN (
SELECT DISTINCT TOP(1) [apiResource].[Id]
FROM [ApiResources] AS [apiResource]
WHERE [apiResource].[Name] = @__name_0
ORDER BY [apiResource].[Id]
) AS [apiResource1] ON [a2].[ApiResourceId] = [apiResource1].[Id]
ORDER BY [apiResource1].[Id]
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (0ms) [Parameters=[@__name_0='?' (Size = 200)], CommandType='Text', CommandTimeout='30']
SELECT [a].[Id], [a].[ApiResourceId], [a].[Description], [a].[DisplayName], [a].[Emphasize], [a].[Name], [a].[Required], [a].[ShowInDiscoveryDocument]
FROM [ApiScopes] AS [a]
INNER JOIN (
SELECT DISTINCT TOP(1) [apiResource].[Id]
FROM [ApiResources] AS [apiResource]
WHERE [apiResource].[Name] = @__name_0
ORDER BY [apiResource].[Id]
) AS [apiResource0] ON [a].[ApiResourceId] = [apiResource0].[Id]
ORDER BY [apiResource0].[Id], [a].[Id]
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (0ms) [Parameters=[@__name_0='?' (Size = 200)], CommandType='Text', CommandTimeout='30']
SELECT [a0].[Id], [a0].[ApiScopeId], [a0].[Type]
FROM [ApiScopeClaims] AS [a0]
INNER JOIN (
SELECT DISTINCT [apiResource0].[Id], [a].[Id] AS [Id0]
FROM [ApiScopes] AS [a]
INNER JOIN (
SELECT DISTINCT TOP(1) [apiResource].[Id]
FROM [ApiResources] AS [apiResource]
WHERE [apiResource].[Name] = @__name_0
ORDER BY [apiResource].[Id]
) AS [apiResource0] ON [a].[ApiResourceId] = [apiResource0].[Id]
) AS [a1] ON [a0].[ApiScopeId] = [a1].[Id0]
ORDER BY [a1].[Id], [a1].[Id0]
dbug: IdentityServer4.EntityFramework.Stores.ResourceStore[0]
Found MyAPI API resource in database
info: IdentityServer4.Validation.HashedSharedSecretValidator[0]
Secret: MyAPI Secret uses invalid hashing algorithm.
info: IdentityServer4.Validation.HashedSharedSecretValidator[0]
Secret: MyAPI Secret uses invalid hashing algorithm.
dbug: IdentityServer4.Validation.SecretValidator[0]
Secret validators could not validate secret
fail: IdentityServer4.Validation.ApiSecretValidator[0]
API validation failed.
fail: IdentityServer4.Endpoints.IntrospectionEndpoint[0]
API unauthorized to call introspection endpoint. aborting.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 30.673ms 401
Vielleicht können Sie Ihre gesamte VS-Lösung veröffentlichen, so dass es für Menschen leichter zu debuggen ist. – Evk
Es ist schwer zu sagen, aber basierend auf dem Code, den Sie gepostet haben, scheint es, dass Sie Ihre API und IdentityServer in einer Anwendung verwenden. Könnte es hier eine Verwechslung geben? Auch warum mussten Sie manuell eine gehashte ApiSecret hinzufügen? Ist da ein Fehler gemacht? Wenn Sie der QS-Dokumentation 'InitializeDatabase (app);' gefolgt haben, wird Ihre Datenbank nur gefüllt, wenn sie keine Daten enthält. Dies könnte der Grund sein, warum Ihr Code sich nicht ändert. – user1336