2016-10-29 6 views
0

私は、IdentityServer3が組み込まれたAsp.NET MVC/WebAPIプロジェクトを持っています。JavascriptとWeb APIを接続してIdentityServer3で保護する

MVCとWebAPIの両方をIdentityServerで保護します。ですから、MVCコントローラとAPIコントローラの両方でAuthorize属性を使用しました。

私のテストページ(保護されている)にサーフィンすると、私はIdentityServerログインページにリダイレクトされます。私は自分のユーザー名とパスワードを入力し、認証されてリダイレクトされます。 ページ上に、私の保護されたAPIに、承認ヘッダ内のアクセストークンを使って、JavaScriptからGETをトリガーするボタンがあります。しかしここでは401 Unauthorizedで失敗します。 Razorでページにレンダリングすることで、javascriptへのアクセストークンを取得しました。

私は、IdentityServerに1クライアントがあり、ハイブリッドフローに設定されています。 MVCはクッキーを使用し、APIはベアラトークンを使用します。 API HttpConfigurationでSuppressDefaultHostAuthenticationを設定しました。私はその行を削除する場合はすべてが動作しますが、私はしたくないAPIのためのクッキーを使用します。

証明書の問題の可能性を避けるため、現在はHTTPとRequireSsl = falseのみを使用しています。

私はこれを動作させるために数日間試しましたが、私はどこにもいません。 私はこれをデバッグして401の原因になることさえ知りません。

これまでのところ、私はヘルプを検索するときにGoogleが提案するすべてのページを認識しています。

これはどのようなものか、どのようにこれをデバッグするのですか?

は、ここに私のStartup.cs

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

     // MVC client 

     string authBaseAddress = "http://localhost:50319/identity"; 
     string tokenEndpoint = authBaseAddress + "/connect/token"; 
     string userInfoEndpoint = authBaseAddress + "/connect/userinfo"; 

     string redirectUri = "http://localhost:50319/"; 

     app.UseCookieAuthentication(new CookieAuthenticationOptions 
     { 
      AuthenticationType = "Cookies" 
     }); 

     app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
     { 
      ClientId = "hybrid_clients", 
      Authority = authBaseAddress, 
      RedirectUri = redirectUri, 

      ResponseType = "code id_token token", 

      Scope = "openid profile roles sampleApi offline_access", 

      TokenValidationParameters = new TokenValidationParameters 
      { 
       NameClaimType = "name", 
       RoleClaimType = "role" 
      }, 

      SignInAsAuthenticationType = "Cookies", 

      Notifications = new OpenIdConnectAuthenticationNotifications 
      { 
       AuthorizationCodeReceived = async n => 
       { 
        // use the code to get the access and refresh token 
        var tokenClient = new TokenClient(
         tokenEndpoint, 
         "hybrid_clients", 
         "secret"); 

        var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri); 

        if (tokenResponse.IsError) 
        { 
         throw new Exception(tokenResponse.Error); 
        } 

        // use the access token to retrieve claims from userinfo 
        var userInfoClient = new UserInfoClient(
         new Uri(userInfoEndpoint), 
         tokenResponse.AccessToken); 

        var userInfoResponse = await userInfoClient.GetAsync(); 

        // create new identity 
        var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType); 
        id.AddClaims(userInfoResponse.GetClaimsIdentity().Claims); 

        id.AddClaim(new Claim("access_token", tokenResponse.AccessToken)); 
        id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString())); 
        id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken)); 
        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken)); 
        id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value)); 

        n.AuthenticationTicket = new AuthenticationTicket(
         new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"), 
         n.AuthenticationTicket.Properties); 
       }, 

       // Attach the id_token for the logout roundtrip to IdentityServer 
       RedirectToIdentityProvider = n => 
       { 
        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest) 
        { 
         var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token"); 

         if (idTokenHint != null) 
         { 
          n.ProtocolMessage.IdTokenHint = idTokenHint.Value; 
         } 
        } 

        return Task.FromResult(0); 
       } 
      } 
     }); 

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

     // web api 

     app.Map("/api", a => 
     { 
      var config = new HttpConfiguration(); 

      a.UseCors(CorsOptions.AllowAll); 

      a.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions 
      { 
       //AuthenticationMode = AuthenticationMode.Active, 
       Authority = authBaseAddress, 
       RequiredScopes = new[] { "sampleApi" }, 
       DelayLoadMetadata = true 
      }); 

      config.SuppressDefaultHostAuthentication(); 
      config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); 

      config.MapHttpAttributeRoutes(); 

      a.UseWebApi(config); 
     }); 

     // Identity server 

     app.Map("/identity", idsrvApp => 
     { 
      idsrvApp.UseCors(CorsOptions.AllowAll); 

      idsrvApp.UseIdentityServer(new IdentityServerOptions 
      { 
       SiteName = "Embedded IdentityServer", 
       SigningCertificate = LoadCertificate(), 

       Factory = new IdentityServerServiceFactory() 
          .UseInMemoryUsers(Users.Get()) 
          .UseInMemoryClients(Clients.Get()) 
          .UseInMemoryScopes(Scopes.Get()), 

       AuthenticationOptions = new IdentityServer3.Core.Configuration.AuthenticationOptions() 
       { 
        EnablePostSignOutAutoRedirect = true // Automatically redirects back to the client on signout 
       }, 

       RequireSsl = false, 

      }); 
     }); 

    } 

    X509Certificate2 LoadCertificate() 
    { 
     return new X509Certificate2(
      string.Format(@"{0}\bin\idsrv3test.pfx", AppDomain.CurrentDomain.BaseDirectory), "idsrv3test"); 
    } 
} 

私のクライアント

new Client 
      { 
       Enabled = true, 
       ClientName = "Hybrid Clients", 
       ClientId = "hybrid_clients", 
       Flow = Flows.Hybrid, 

       //AllowAccessTokensViaBrowser = false, 

       RedirectUris = new List<string> 
       { 
        "http://localhost:50319/" 
       }, 
       PostLogoutRedirectUris = new List<string> 
       { 
        "http://localhost:50319/" 
       }, 

       AllowedScopes = new List<string> 
       { 
        "openid", 
        "profile", 
        "email", 
        "roles", 
        "address", 
        "all_claims", 
        "sampleApi", 
        "offline_access" 
       }, 

       ClientSecrets = new List<Secret> 
       { 
        new Secret("secret".Sha256()) 
       }, 

       AccessTokenType = AccessTokenType.Reference, 
       LogoutSessionRequired = true 

      }, 

マイスコープ

public static class Scopes 
{ 
    public static IEnumerable<Scope> Get() 
    { 
     var scopes = new List<Scope> 
     { 
      StandardScopes.OpenId, 
      StandardScopes.Profile, 
      StandardScopes.Email, 
      StandardScopes.Address, 
      StandardScopes.OfflineAccess, 
      StandardScopes.RolesAlwaysInclude, 
      StandardScopes.AllClaims, 

      new Scope 
      { 
       Enabled = true, 
       Name = "roles", 
       Type = ScopeType.Identity, 
       Claims = new List<ScopeClaim> 
       { 
        new ScopeClaim("role") 
       } 
      }, 
      new Scope 
      { 
       Enabled = true, 
       DisplayName = "Sample API", 
       Name = "sampleApi", 
       Description = "Access to a sample API", 
       Type = ScopeType.Resource 
      } 
     }; 

     return scopes; 
    } 
} 

マイAPI

[Authorize] 
public class SecuredApiController : ApiController 
{ 
    public IHttpActionResult Get() 
    { 
     var user = User as ClaimsPrincipal; 
     var claims = from c in user.Claims 
        select new 
        { 
         type = c.Type, 
         value = c.Value 
        }; 

     return Json(claims); 
    } 
} 
ですAPI用の刀ログ
function ClientAppViewModel(accessToken) { 
    var self = this; 

    self.accessToken = accessToken; 

    self.apiResult = ko.observable('empty'); 

    self.callApi = function() { 
     console.log('CallApi'); 
     var xhr = new XMLHttpRequest(); 
     xhr.open("GET", "http://localhost:50319/api/SecuredApi"); 
     xhr.onload = function() { 
      self.apiResult(JSON.stringify(JSON.parse(xhr.response), null, 2)); 
     }; 
     xhr.setRequestHeader("Authorization", "Bearer " + self.accessToken); 
     xhr.send(); 
    } 
} 

答えて

0

SecuredApi

を呼び出して、私のかみそりビューの

パート

<button data-bind="click:callApi">Call API</button> 
<span data-bind="text:apiResult"></span> 

<script> 
    $(function() { 
     ko.myViewModel = new ClientAppViewModel('@ViewData["access_token"]'); 
     ko.applyBindings(ko.myViewModel); 
    }); 
</script> 

私のJavaScript(KnockoutJSは)何をしたいです。これらを使用すると、私はすでにカタナログを有効にしているが、残念ながら何もそれに書き込まれません

+0

Katana Documentationを参照してください)APIは401

を返して、なぜあなたはMicrosoft.Owinログのソースを使用して、これらにアクセスすることができます表示されます私は401を取得するとき。私は別の問題を調査したときに私はそこに他の情報を得たので、私はログの仕事を知っている。 – Decept

+0

次に、あなたのAPIに401が出現しているコードを質問に入れる必要があるかもしれないと思います。私は、IdentityServerベアラトークンミドルウェアを使用していて、ログをカタログに出力していると仮定します。 –

+0

時間を割いていただきありがとうございます。私は私の質問にすべてのコードを追加しました。はい、私はIdentityServerベアラトークンミドルウェアを使用しています – Decept

関連する問題