2016-11-26 6 views
0

thisチュートリアルに従って、私のSPA用の簡単なOAuthサーバを作成しています。 OAuthプロバイダからJWTの罰金を請求することができます。しかし、JWTを承認ヘッダー(このように:Authorization Bearer <token>)に送ると、私はいつも401 "この要求に対して承認が拒否されました"というメッセージが表示されます。ASP.NET JWTベアラ認証でリクエストコンテキストでユーザが変更されない

コードを実行すると、要求コンテキスト内のユーザーがJWTの所有者ではなく匿名のWindows認証ユーザーに設定されていることがわかります。

app.UseWebAPI()コールをOAuth設定の後に置くと言っている人がたくさんいますが、私はstartup.csにWebAPIを登録していません。私はすべきですか?私は現在、私のコードのどこにでもapp.UseWebAPI()を持っていません(そして、APIは許可なしでうまくいきます)。

public partial class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
      ConfigureOAuth(app); 
     } 
    } 

public partial class Startup 
    { 
     /// <summary> 
     /// OAuth configuration 
     /// </summary> 
     /// <param name="app"></param> 
     public void ConfigureOAuth(IAppBuilder app) 
     { 
      // Unique identifier for the entity issuing the token 
      var issuer = ConfigurationManager.AppSettings["issuer"]; 
      // Private key used to secure the token 
      var secret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["secret"]); 

      // Enable JWT authentication 
      app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions 
      { 
       AuthenticationMode = AuthenticationMode.Active, 
       AllowedAudiences = new[] { "Any" }, 
       IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[] 
       { 
        new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret) 
       } 
      }); 

      // Create authentication endponit 
      app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions 
      { 
       AllowInsecureHttp = true, 
       TokenEndpointPath = new PathString("/api/login/"), 
       AccessTokenExpireTimeSpan = TimeSpan.FromHours(1), 
       Provider = new CustomOAuthProvider(), 
       AccessTokenFormat = new CustomJwtFormat(issuer) 
      }); 
     } 
    } 

はここに私のCustomOAuthProviderクラスです:ここで

は私startup.csだ

public class CustomOAuthProvider : OAuthAuthorizationServerProvider 
    { 
     IMessengerRepository repo; 

     public CustomOAuthProvider() : base() 
     { 
      repo = new MessengerRepository(); 
     } 

     public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
     { 
      // Enable CORS 
      context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); 

      // Check against the repository to see if the login details are correct 
      var user = repo.Authenticate(context.UserName, context.Password); 

      // If the login details are incorrect, return an error 
      if (user == null) 
      { 
       context.SetError("invalid_grant", "The username or password is incorrect"); 
       context.Rejected(); 
       return Task.FromResult<object>(null); 
      } 

      // Otherwise, return a JWT 
      var ticket = new AuthenticationTicket(SetClaimsIdentity(context, user), new AuthenticationProperties()); 
      context.Validated(ticket); 

      return Task.FromResult<object>(null); 
     } 

     public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 
     { 
      // Because the audience is not validated, the request is validated straight away without any checks 
      context.Validated(); 
      return Task.FromResult<object>(null); 
     } 

     /// <summary> 
     /// Create a ClaimsIdentity based on their username and role 
     /// </summary> 
     /// <param name="context"></param> 
     /// <param name="user"></param> 
     /// <returns></returns> 
     public static ClaimsIdentity SetClaimsIdentity(OAuthGrantResourceOwnerCredentialsContext context, UserDto user) 
     { 
      var identity = new ClaimsIdentity("JWT"); 

      // Add claims for the user themselves 
      identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); 
      identity.AddClaim(new Claim("sub", context.UserName)); 
      // Add claim for the user's role 
      identity.AddClaim(new Claim(ClaimTypes.Role, user.UserRole.RoleName.TrimEnd(' '))); 

      return identity; 
     } 
    } 

と私のCustomJwtFormatクラス:

public class CustomJwtFormat : ISecureDataFormat<AuthenticationTicket> 
    { 
     // Private key for encoding token 
     private static readonly byte[] secret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["secret"]); 
     // Entity issuing the token 
     private readonly string issuer; 

     public CustomJwtFormat(string issuer) 
     { 
      this.issuer = issuer; 
     } 

     public string Protect(AuthenticationTicket data) 
     { 
      if (data == null) 
       throw new ArgumentNullException(nameof(data)); 

      var signingKey = new HmacSigningCredentials(secret); 
      var issued = data.Properties.IssuedUtc; 
      var expires = data.Properties.ExpiresUtc; 

      return new JwtSecurityTokenHandler().WriteToken(new JwtSecurityToken(issuer, null, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey)); 
     } 

     public AuthenticationTicket Unprotect(string protectedText) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

答えて

1

アイザック、

あなたimplementatio nは良く見えますが、audience idには小さな問題があります。

authorizationCustomJwtFormatには、聴衆IDとしてnullを指定します。 authenticationの場合はAnyと指定します。 これが401 Unauthorizedを取得する理由です。

JwtSecurityTokenを以下のように変更しても動作します。

return new JwtSecurityTokenHandler().WriteToken(new JwtSecurityToken(issuer, "Any", data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey)); 
関連する問題