2017-02-27 13 views
5

IdentityServer4のイントロスペクションエンドポイントを使用してトークンを検証しようとしています。私は401:Unauthorizedを得続けます。私のログには、次のようになります。基本xxxxxxxxxxxxxxxxxとしてIdentityServer4イントロスペクションエンドポイントAPIが無効なハッシュアルゴリズムを使用しています

new ApiResource 
       { 
        Name = "MyAPI", 
        DisplayName = "My API", 
        ApiSecrets = 
        { 
         new Secret("TopSecret".Sha256()) 
        }, 
       } 
アプリケーション/ x-www-form-urlencodedで私はコンテンツタイプのヘッダを渡している

と承認:

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. 

私のAPIは、そのように設定されていますここで、xはBase64でエンコードされた認証文字列(myapi:TopSecret)です。私のトークンは投稿の本体にあります

私は何が欠けていますか?なぜMyAPI APIは無効なハッシュアルゴリズムを使用していますか?無効な場合は、有効なハッシュアルゴリズムは何ですか?

追加情報:私のリソースは、Entity Frameworkを介してアクセスするSQLデータベースに含まれています。具体的には、設定はhereのクイックスタートドキュメントとまったく同じです。ポイントに到達するには、APIをApiSecretsテーブルに手動で追加し、Sha256パスワードであるType(SharedSecret)とValueを与えなければなりませんでした。

Startup.csで

私COnfigureServicesは、

設定の下で
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(); 

:私は、私は問題を抱え始めた後にのみ、このセクションにApiSecret、AutomaticAuthenticateとAutomaticChallengeを追加

app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions 
     { 
      Authority = "http://localhost:5000", 
      RequireHttpsMetadata = false, 
      ApiSecret = "TopSecret", 
      AutomaticAuthenticate = true, 
      AutomaticChallenge = false, 

      ApiName = "MyAPI" 
     }); 

     InitializeDatabase(app); 

     app.UseIdentityServer(); 

     app.UseMvc(); 

注意それを働かせる努力。私Scopes.csで

は、私は、次のAPIは、概説されています:

public static IEnumerable<ApiResource> GetApiResources() 
    { 
     return new[] 
     { 
      new ApiResource 
      { 
       Name = "MyAPI", 
       DisplayName = "My API", 
       ApiSecrets = 
       { 
        new Secret("TopSecret".Sha256()), 
       }, 

      } 
     };    
    } 

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, 

     }, 

を。設定が格納されているデータベースは、私が行ったコード変更を無効にしているようです。データベースではApiSecretsテーブルにApiResourceIdが1のレコードを作成し、説明と有効期限を追加し、タイプを "SharedSecret"に設定し、プレーンテキスト、sha256、base64などのさまざまなフォーマットを使用してシークレットを追加しました。

ここでは、通話中のログがすべて表示されます。多分それが助けになるでしょう。私はベアラーが見つからないか何かがあることを知っていますが、私はそれがどうなるのか、それが手続きの結果に影響するかどうかはわかりません。

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 
+0

おそらく、VSソリューション全体を公開して、人々がより簡単にデバッグできるようにすることができます。 – Evk

+0

あなたが伝えたコードに基づいて、あなたはAPIとIdentityServerを1つのアプリケーションで使用しているようです。ここにはミックスがありますか? なぜ、ハッシュされたApiSecretを手動で追加しなければならなかったのですか?そこに間違いがありましたか? QSのドキュメントに従うならば、 'InitializeDatabase(app);'はデータが入っていない場合にのみあなたのデータベースにデータを取り込みます。これはあなたのコードの変更が有効にならない原因かもしれません。 – user1336

答えて

5

コードとデータベース設定の細部を少しでも見ずに少し難しいです。また、実際にイントロスペクションエンドポイントを呼び出すコードは表示されません。 C#やJavascript、Postmanでやっていますか?

とにかく、ここに私のレビュー...

Startup.cs

ConfigureServices方法がよさそうです。 ResourceOwnerパスワードバリデーターサービスを追加することは、上記の問題に対しては不要です。イントロスペクションエンドポイントにアクセスするには、ResourceOwnerパスワードではなく、ApiSecretが必要です。無関係の理由であなたがそこにいると思っています。そうでなければ、それを取り出してください。

app.UseIdentityServerAuthenticationは、認証サーバー(IdentityServer4を使用)として機能するだけでなく、認証サーバー(それ自体)のWebアプリケーションをコールするWebアプリケーションを使用していることを意味します。この場合)、着信トークンを検証します。

app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions 
{ 
    Authority = "https://localhost:44388", 
    RequireHttpsMetadata = false, 
    ApiName = "MyAPI" 
    //ApiSecret = "TopSecret" not necessary to know the api secret for normal validation 
    //AutomaticAuthenticate = true, not necessary 
    //AutomaticChallenge = false not necessary 
}); 

app.UseMvcWithDefaultRoute()とすることもできます。

アピインメモリ構成

正しくnew ApiResource("name", "display")コンストラクタ意志のセットアップにデータベースを使用しました。上記のようにオブジェクトイニシャライザの構文を使用しても構いません。真上、IdentityServerツーリングは、各ApiResourceに1つApiScopeを自動生成しますnew ApiResourcesに指定されていませんスコープがないので、https://github.com/IdentityServer/IdentityServer4/issues/836

public static IEnumerable<ApiResource> GetApiResources() 
{ 
    return new List<ApiResource> 
    { 
     // this will incorrectly leave out the ApiScope record in the database, but will create the ApiResoure and ApiSecret records 
     new ApiResource 
     { 
      Name = "MyAPI", 
      DisplayName = "My API", 
      ApiSecrets = 
      { 
       new Secret("TopSecret".Sha256()), 
      } 
     }, 
     // this will correctly create the ApiResource, ApiScope, and ApiSecret records in the database. 
     new ApiResource("MyAPI2", "My API2") 
     { 
      ApiSecrets = 
      { 
       new Secret("TopSecret2".Sha256()) 
      } 
     } 
    }; 
} 

FYI:これはGitHubのに報告された問題です。この場合ApiScoreはApiResourceと同じ名前になります。 ApiResourceには少なくとも1つのApiScopeが必要です。多くを持つことができます。 ApiScopesはClientScopesテーブルのClientに関連しています。

クライアントのインメモリの設定は

コメントを見る

public static IEnumerable<Client> GetClients() 
{ 
    return new List<Client> 
    { 
     new Client 
     { 
      ClientName = "My Client", 
      AlwaysSendClientClaims = true, 
      ClientId = "MyClient", 
      // changed the secret to make clear this is unrelated to the Api secret 
      ClientSecrets = { new Secret("TopSecretClientSecret".Sha256()) }, 
      // RequireClientSecret might as well be true if you are giving this client a secret 
      RequireClientSecret = true, 
      AllowAccessTokensViaBrowser = true, 
      AllowedGrantTypes = GrantTypes.HybridAndClientCredentials, 
      // Added MyAPI2 from my example above 
      AllowedScopes = { "MyAPI", "MyAPI2" }, 
      RequireConsent = false, 
      AllowOfflineAccess = true 
     } 
    }; 
} 

次のコードは、WEBAPIコントローラからである

イントロスペクションのエンドポイントを呼び出します。 (IdentityServerの権限とApiResourceはこのディスカッションで同じWebアプリケーションでホストされていることを忘れないでください)。この方法への要求は、クライアントによって行われる。

このメソッドの内部では、アクセス権限トークンを検証/復号化するために、権限のイントロスペクションエンドポイントを呼び出すことができます。この例では、これを行うWebアプリケーションをapp.UseIdentityServerAuthenticationに設定しているため、これは不要です。イントロスペクションエンドポイントは、Reference tokensに使用されるか、またはWebアプリケーション自体がaccess_tokenを検証できない場合に使用されます。ここで

[Route("api/[controller]/[action]")] 
[Produces("application/json")] 
public class DataController : Controller 
{ 
    [HttpGet] 
    [Authorize] 
    public async Task<IEnumerable<String>> Secure() 
    { 
     var accessToken = await HttpContext.Authentication.GetTokenAsync("access_token"); 

     var introspectionClient = new IntrospectionClient("https://localhost:44388/connect/introspect", "MyAPI", "TopSecret"); 

     var response = await introspectionClient.SendAsync(new IntrospectionRequest { Token = accessToken }); 

     var isActive = response.IsActive; 
     var claims = response.Claims; 

     return new[] { "secure1", "secure2", $"isActive: {isActive}", JsonConvert.SerializeObject(claims) }; 
    } 
} 

データベースが原因前述のオブジェクト初期化の問題にApiScopeが欠落しているので、ApiScope「MyAPI」のIntrospectionClientを使用して401を与えるだろう。

最後に一つ

別の可能性のある問題は、手動でデータベースエディタでハッシュされたApiSecretを追加することができないテキストが正しく復号化する作る奇妙なコピー/貼り付けの問題につながる可能性があることです。私は、これは問題の底に得るのを助けるか、少なくとも新しい思考を刺激することを願って

https://github.com/travisjs/AspNetCore-IdentityServer-Instrospection

は、完全なソリューションを参照してください。

+0

これは今までのところ最も簡潔な答えです。残念ながら私はあなたのソリューションをロードすることができません。なぜなら私はVS2015を使用することに徹底的に追い込まれており、あなたのソリューションは新しい2017ベータを使用しているようです。それはさておき、あなたのコードのいくつかを動かすことができました。私は間違ったアプローチをしていたように見えます。自分のフレーズを適応させるために、あなたは自分の考えをいくつか刺激しました。大変感謝しています! – Rafe

+0

@危険なええ、私はマシンを再構築してVS 2015をインストールしないことに決めました。すべてのコードをVS 2015プロジェクトにドロップした場合、project.jsonだけが実際の違いです。 –

+0

Thanks @ travis.js。私はあなたにこの恩恵を授与しています。このプロジェクトに関連する問題について私が直接あなたに電子メールを送っても問題ないかと疑問に思っていましたか? – Rafe

0

(myapi:TopSecret)。私のトークンは、イントロスペクションのエンドポイントがscope:apisecret、ないname:apisecretを使用して基本認証を必要とする記事の本文に

です。

+0

私はそれを間違ってタイプしました、それは実際にMyAPIです:TopSecret MyAPIはスコープです。 – Rafe

関連する問題