2016-12-15 11 views
0

IdentityServer3によって保護されたAPIからリソースにアクセスしようとすると401エラーが発生します。IdentityServer3で保護されたAPIにアクセスするとエラー401

私は、ログインしてIdentityServer3のホストアプリケーションから静かに access_tokenはを取得するが、私は、このリソースを消費する access_tokenはを使用することはできません。

私はこのようなスタートアップクラスでIdentityServerの私のホストを設定した:私ののServiceFactoryクラスで

public void Configuration(IAppBuilder app) 
{ 
    Log.Logger = new LoggerConfiguration() 
     .WriteTo.Trace() 
     .CreateLogger(); 

    AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject; 
    JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>(); 

    // Configure IdentityServer3 
    app.Map("/identity", configuration => 
    { 
     configuration.UseIdentityServer(new IdentityServerOptions 
     { 
      SiteName = "IdentityServer3 Sample", 
      SigningCertificate = LoadCertificate(), 
      Factory = ServiceFactory.Create(), 
      RequireSsl = true, 

      CspOptions = new CspOptions 
      { 
       Enabled = true, 
       FontSrc = "fonts.googleapis.com" 
      }, 

      AuthenticationOptions = new AuthenticationOptions 
      { 
       EnablePostSignOutAutoRedirect = true, 
      } 
     }); 
    }); 
} 

、私が持っている:

public static IdentityServerServiceFactory Create() 
{ 
    var factory = new IdentityServerServiceFactory 
    { 
     ScopeStore = new Registration<IScopeStore>(
      new InMemoryScopeStore(Scopes.GetScopes())), 
     ClientStore = new Registration<IClientStore>(
      new InMemoryClientStore(Clients.GetClients())), 
     CorsPolicyService = new Registration<ICorsPolicyService>(
      new DefaultCorsPolicyService {AllowAll = true}) 
    }; 

    //factory.UseInMemoryUsers(Users.GetUsers()); 

    ConfigureServices(factory); 

    return factory; 
} 

private static void ConfigureServices(IdentityServerServiceFactory factory) 
{ 
    factory.UserService = new Registration<IUserService, UserService>(); 

    factory.Register(new Registration<BaseContext>(resolver => new BaseContext())); 

    factory.Register(new Registration<AppUserManager>(resolver => new AppUserManager(
     new UserStore<User>(resolver.Resolve<BaseContext>())))); 
} 

スコープ

を 台の
return new List<Scope> 
{ 
    StandardScopes.OpenId, 
    StandardScopes.Profile, 
    StandardScopes.OfflineAccess, 

    new Scope 
    { 
     Enabled = true, 
     Name = "roles", 
     Type = ScopeType.Identity, 
     IncludeAllClaimsForUser = true, 
     Claims = new List<ScopeClaim> 
     { 
      new ScopeClaim("role") 
     } 
    }, 

    new Scope 
    {      
     Enabled = true, 
     Name = "ro", 
     Type = ScopeType.Resource, 
     IncludeAllClaimsForUser = true, 
     Claims = new List<ScopeClaim> 
     { 
      new ScopeClaim("role") 
     } 
    } 
}; 

そしてクライアント

return new List<Client> 
{ 
    new Client 
    { 
     Enabled = true, 
     ClientName = "Hibrid Flow Client", 
     ClientId = AppIdentityConstants.ClientIdForHibridFlow, 
     Flow = Flows.Hybrid, 

     RequireConsent = false, 
     AccessTokenType = AccessTokenType.Reference, 
     UpdateAccessTokenClaimsOnRefresh = true, 

     ClientSecrets = new List<Secret> 
     { 
      new Secret(AppIdentityConstants.ClientSecret.Sha256()) 
     }, 
     AllowedScopes = new List<string> 
     { 
      Constants.StandardScopes.OpenId, 
      Constants.StandardScopes.Profile, 
      Constants.StandardScopes.Email, 
      Constants.StandardScopes.Roles, 
      Constants.StandardScopes.OfflineAccess, 
     }, 
     RedirectUris = new List<string> 
     { 
      AppIdentityConstants.IdentityAddress, 
      AppIdentityConstants.CRMAddress 
     }, 
     PostLogoutRedirectUris = new List<string> 
     { 
      AppIdentityConstants.IdentityAddress, 
      AppIdentityConstants.CRMAddress 
     }, 
     LogoutSessionRequired = true 
    }, 

    new Client 
    { 
     Enabled = true, 
     ClientName = "Resource Owner Client", 
     ClientId = AppIdentityConstants.ClientIdForResourceOwnerFlow, 
     Flow = Flows.ResourceOwner, 

     RequireConsent = false, 
     AccessTokenType = AccessTokenType.Jwt, 
     UpdateAccessTokenClaimsOnRefresh = true, 
     AccessTokenLifetime = 3600, 

     ClientSecrets = new List<Secret> 
     { 
      new Secret(AppIdentityConstants.ClientSecret.Sha256()) 
     }, 
     AllowedScopes = new List<string> 
     { 
      Constants.StandardScopes.OpenId, 
      Constants.StandardScopes.Profile, 
      Constants.StandardScopes.Email, 
      Constants.StandardScopes.Roles, 
      Constants.StandardScopes.OfflineAccess, 
      "ro" 
     }, 
     AllowAccessTokensViaBrowser = true, 
     AbsoluteRefreshTokenLifetime = 86400, 
     SlidingRefreshTokenLifetime = 43200, 
     RefreshTokenUsage = TokenUsage.OneTimeOnly, 
     RefreshTokenExpiration = TokenExpiration.Sliding 
    }, 
}; 

これはIdentityServer3のホストアプリケーションのソースコードです。

ここでAPIの設定方法を説明します。 これは私のスタートアップクラスです:

public void Configuration(IAppBuilder app) 
{ 
    JwtSecurityTokenHandler.InboundClaimTypeMap.Clear(); 

    app.UseIdentityServerBearerTokenAuthentication(
     new IdentityServerBearerTokenAuthenticationOptions 
    { 
     Authority = AppIdentityConstants.IdentityBaseAddress, 
     RequiredScopes = new[] { "ro", "offline_access" }, 
     ClientId = AppIdentityConstants.ClientIdForResourceOwnerFlow, 
     ClientSecret = AppIdentityConstants.ClientSecret, 
    }); 
} 

AppIdentityConstants.IdentityBaseAddresshttps://localhost:44342/identityです。

そして、Global.asax.csに私はこれらの構成を呼び出す:

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     // Web API configuration and services 
     config.Formatters.Remove(config.Formatters.XmlFormatter); 

     var formatters = GlobalConfiguration.Configuration.Formatters; 
     var jsonFormatter = formatters.JsonFormatter; 
     var settings = jsonFormatter.SerializerSettings; 

     #if DEBUG 
     settings.Formatting = Formatting.Indented; 
     #endif 

     settings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 

     // Web API routes 
     config.MapHttpAttributeRoutes(); 

     config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 

     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{id}", 
      defaults: new { id = RouteParameter.Optional } 
     ); 
    } 
} 

そしてAuthorizeAttributeフィルタ:

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 
</head> 
<body> 
    <script src="bower_components/jquery/dist/jquery.min.js"></script> 
    <script> 
     function done(response) { console.log(response); } 
     function always(response) { console.log("always"); } 
     function fail(response) { console.log("fail"); } 
     var custom = { 
      client_id: "ro", 
      client_secret: "client_secret", 
      scope: "ro offline_access", 
     }; 

     $(function() { 
      var settings = { 
       "async": true, 
       "crossDomain": true, 
       "url": "https://localhost:44342/identity/connect/token", 
       "method": "POST", 
       "headers": { 
        "content-type": "application/x-www-form-urlencoded", 
        "cache-control": "no-cache" 
       }, 
       "data": { 
        "client_id": custom.client_id, 
        "client_secret": custom.client_secret, 
        "scope": custom.scope, 
        "username": "[email protected]", 
        "password": "123456", 
        "grant_type": "password" 
       } 
      } 
      $.ajax(settings).done(function (response){ 
       done(response); 
       checkStatus(response.access_token); 
      }).always(always).fail(fail); 

      function checkStatus(access_token) { 
       var settings2 = { 
        "async": true, 
        "crossDomain": true, 
        "url": "https://localhost:44352/api/importer/status", 
        "method": "GET", 
        xhrFields: { 
         withCredentials: true 
        }, 
        "headers": { 
         "Authorization": "Bearer " + access_token, 
         "cache-control": "no-cache" 
        } 
       } 
       $.ajax(settings2).done(done).always(always).fail(fail); 
      } 
     }); 
    </script> 
</body> 
</html> 

public class FilterConfig 
{ 
    public static void RegisterGlobalFilters(HttpConfiguration configuration) 
    { 
     configuration.Filters.Add(new AuthorizeAttribute()); 
    } 
} 

私は次のようでしたをテストします

acess_tokenを含むアクセスデータを取得するための最初の要求は正常に実行されます。

ただし、APIに対して行われた2番目の要求は401エラーを返します。
先ほど示したように、はAPIがAuthorizeAttributeで保護されています。

どうしたのですか?

答えて

3

checkStatus関数をデバッグする場合、acessDataパラメータにはaccess_tokenプロパティがありますか?

もしそうなら、Web APIプロジェクトにMicrosoft.Owin.Host.SystemWeb NuGetパッケージをインストールしましたか?あなたがそのパッケージを紛失しているため、あなたのOWINパイプラインは実行されません。したがって、アクセストークンはIDに変換されず、要求は未認証のままであり、HTTP 401応答を説明することができます。

+0

'Microsoft.Owin.Host.SystemWeb'のインストールが成功しました。しかし、 'WWW-Authenticate→Bearer error =" insufficient_scope "というエラーが出ます。何が起こっているのか知っていますか?手伝って頂けますか? – JamesTK

+0

シンプルに、 'IdentityServerBearerTokenAuthenticationOptions'の' RequiredScopes'プロパティは配列であり、私は単一のオンラインスコープを通知していました。解決済み! – JamesTK

関連する問題