2017-08-23 16 views
2

ClaimsPrincipalを使用してログインし、.netコア2.0でJWTを取得しようとしています。私の現在のコードでは、私はSignInAsync関数の結果からエラーを取得: が「No IAuthenticationSignInHandlerは、スキームのためのログイン処理するように設定されています。ベアラ」:AuthenticateAsyncを使用したJWTトークンの生成

[Route("Login/{username}")] 
public async Task<IActionResult> Login(string username) 
{ 
    var userClaims = new List<Claim> 
    { 
     new Claim(ClaimTypes.Name, username) 
    }; 
    var principal = new ClaimsPrincipal(new ClaimsIdentity(userClaims)); 
    var sign = HttpContext.SignInAsync(principal); 
    await sign; 
    var res = await HttpContext.AuthenticateAsync(); 
    var token = await HttpContext.GetTokenAsync("access_token"); 
    return Json(token); 
} 
ここ

は、私が現在使用しているコントローラであり、

ログイン部分がテストされ、クッキーでうまく機能しています。私は私のstartup.csでJwtBearerDefaults.AuthenticationSchemeで次のコードを使用する場合しかし:

services.AddAuthentication(config => { 
    config.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; 
    config.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 
}) 
.AddJwtBearer(config => 
{ 
    config.TokenValidationParameters = Token.tokenValidationParameters; 
    config.RequireHttpsMetadata = false; 
    config.SaveToken = true; 
}); 

私はSignInAsync関数の結果からエラーを取得: 「いいえIAuthenticationSignInHandlerは、スキームのためにログイン処理するように設定されていますベアラー」

マイトークンクラスは、私は(JWT on .NET Core 2.0で)オンラインで見つけると、以下のように定義されたコードの助けを借りて作成されました:私はのlookinからそれを正しく理解していれば

public static class Token 
{ 

    public static TokenValidationParameters tokenValidationParameters { 
     get 
     { 

      return new TokenValidationParameters 
      { 
       ValidateIssuerSigningKey = true, 
       IssuerSigningKey = GetSignInKey(), 
       ValidateIssuer = true, 
       ValidIssuer = GetIssuer(), 
       ValidateAudience = true, 
       ValidAudience = GetAudience(), 
       ValidateLifetime = true, 
       ClockSkew = TimeSpan.Zero 
      }; 
     } 
    } 

    static private SymmetricSecurityKey GetSignInKey() 
    { 
     const string secretKey = "very_long_very_secret_secret"; 
     var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey)); 

     return signingKey; 
    } 

    static private string GetIssuer() 
    { 
     return "issuer"; 
    } 

    static private string GetAudience() 
    { 
     return "audience"; 
    } 

} 

答えて

1

符号付きトークンは、JwtSecurityTokenHandlerを使用して作成できます。

var handler = new JwtSecurityTokenHandler(); 
var jwt = handler.CreateJwtSecurityToken(new SecurityTokenDescriptor 
{ 
    Expires = DateTime.UtcNow.Add(Expiary), 
    Subject = new ClaimsIdentity(claims, "local"), 
    SigningCredentials = new SigningCredentials(SigningKey, SecurityAlgorithms.HmacSha256) 
}); 
return handler.WriteToken(jwt); 
3

gをJwtBearerHandlerのソースコードに追加すると、IAuthenticationSignInHandlerが実装されないため、このエラーが発生します。 SignInAsyncへの呼び出しは、例えばCookieAuthenticationHandlerが行う認証情報などの認証情報を保持するように設計されています。しかし、JWTの場合、トークンを格納するためのよく知られた単一の場所が存在しないため、SignInAsyncをまったく呼び出す必要はありません。その代わりに、トークンをつかんでブラウザに戻してください。あなたがリダイレクトしていると仮定すると、それをクエリ文字列に入れておくことができます。ブラウザアプリケーションがSPA(つまりAngularベース)で、AJAX呼び出しのトークンが必要な場合は、SPAにトークンを格納し、すべてのAPIリクエストとともにトークンを送信する必要があります。 https://medium.com/beautiful-angular/angular-2-and-jwt-authentication-d30c21a2f24f

JwtBearerHandlerは、ベアラを持つ認証ヘッダーが見つかることを期待しています。そのため、AJAXコールがトークンをクエリに配置している場合JwtBearerEvents.OnMessageReceived実装を提供する必要があります。これは、クエリ文字列からトークンを取り出し、ヘッダに配置します。

+0

クライアントからトークンを送信して戻す必要はありますか? IAuthenticationSignInHandlerを実装する方法を知っていますか? –

+0

トークンは、ログイン直後にサーバーからクライアントに一度だけ戻されます。トークンには、署名されたユーザーIDが含まれます。サーバーはステートレスです。したがって、ブラウザクライアントは各API呼び出しでトークンをサーバーに送信する必要があります。つまり、AJAX呼び出しにベアラー表記を含む認証ヘッダーを含める必要があります。 – iTolik

+1

ユーザーはクライアントに名前/パスワードを入力すると、サーバーに渡され、検証されます。すべてがチェックアウトされた場合、トークン(JWT形式で、サーバーによって署名されているため、サーバーは後でそれを検証できます)が生成されて返されます。クライアントはトークンを格納し、さらなるAPIコールでそれを使用します。それが流れです。 ログインアクションで、JTWをすでに生成しているようです。あなたがする必要があるのは、それを返すだけだからです。リダイレクトを行っている場合はクエリ文字列に、レスポンスヘッダーに入れることができます。ログインがAJAXの場合はJSONとしてアタッチできます。 – iTolik

関連する問題