2017-01-24 4 views
6

ASP.NET Core Web APIプロジェクトの認証メカニズムに使用しようとしています。このプロジェクトにMVCの部分がなく、クッキー認証が使用されていないとします。 this guideに基づいてコードを作成しました。UseJwtBearerAuthenticationにUser.Identity.Nameが設定されていません

ログインが正常に機能し、[Authorize]属性で保護されますが、User.Identity.Namenullです。これをどうすれば解決できますか?

マイコード:あなたの主張で

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
{ 
    var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions)); 
    var tokenValidationParameters = new TokenValidationParameters 
    { 
     ValidateIssuer = true, 
     ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)], 

     ValidateAudience = true, 
     ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)], 

     ValidateIssuerSigningKey = true, 
     IssuerSigningKey = _signingKey, 

     RequireExpirationTime = true, 
     ValidateLifetime = true, 

     ClockSkew = TimeSpan.Zero 
    }; 

    app.UseJwtBearerAuthentication(new JwtBearerOptions 
    { 
     AutomaticAuthenticate = true, 
     AutomaticChallenge = true, 
     TokenValidationParameters = tokenValidationParameters, 
     AuthenticationScheme = JwtBearerDefaults.AuthenticationScheme 
    }); 

    app.UseMvc(routes => 
    { 
     routes.MapRoute(
      name: "default", 
      template: "{controller=Home}/{action=Index}/{id?}"); 
    }); 
} 

[HttpPost] 
    [AllowAnonymous] 
    [Route("Login")] 
    public async Task<IActionResult> Login([FromForm] ApplicationUser applicationUser) 
    { 
     //assume user/pass are checked and are ok 

     _logger.LogInformation(1, "API User logged in."); 
     var user = await _userManager.FindByNameAsync(applicationUser.UserName); 
     var roles = await _userManager.GetRolesAsync(user); 

     var claims = new List<Claim> 
     { 
      new Claim(JwtRegisteredClaimNames.Sub, applicationUser.UserName), 
      new Claim(ClaimTypes.NameIdentifier, applicationUser.UserName), 
      new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()), 
      new Claim(JwtRegisteredClaimNames.Iat, 
        ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), 
        ClaimValueTypes.Integer64), 
        new Claim("Claim", "Value") 
     }; 

     if (roles != null) 
      foreach (var role in roles) 
       claims.Add(new Claim("role", role)); 

     // Create the JWT security token and encode it. 
     var jwt = new JwtSecurityToken(
      issuer: _jwtOptions.Issuer, 
      audience: _jwtOptions.Audience, 
      claims: claims, 
      notBefore: _jwtOptions.NotBefore, 
      expires: _jwtOptions.Expiration, 
      signingCredentials: _jwtOptions.SigningCredentials); 

     var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt); 

     // Serialize and return the response 
     var response = new 
     { 
      access_token = encodedJwt, 
      expires_in = (int)_jwtOptions.ValidFor.TotalSeconds 
     }; 

     var json = JsonConvert.SerializeObject(response, _serializerSettings); 
     return new OkObjectResult(json); 
    } 

答えて

8

(第2のコードスニペット)私はこれだけ見ることができます:

new Claim(ClaimTypes.NameIdentifier, applicationUser.UserName), 

をいますが、これを追加する必要があります。

new Claim(ClaimTypes.Name, applicationUser.UserName), 

User.Identity.Nameにはユーザー名が含まれている必要があります。

+0

これで解決しました。非常に簡単です!ありがとう@jps。 –

+0

あなたが歓迎して、それが解決されて聞いてうれしい。 – jps

+0

私はあなたを愛しています、@ jps。あなたは私の日を笑った –

2

もう1つの方法はJwtRegisteredClaimNames.Subの名前空間をtokenValidationParametersに設定することです。これは、標準の使用を継続できるようになります:

var tokenValidationParameters = new TokenValidationParameters 
{ 
    // Ensure that User.Identity.Name is set correctly after login 
    NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", 

    ... existing code ... 
} 

アップデート:ディオゴ・バロスは、このトピックについての私のブログにコメントを残し:。

「こんにちは、

これは働いていたあなたの助けをありがとう 一貫性と安全性を高めるには、ハードコードされた文字列ではなく、(System.Security.Claims名前空間内の)ClaimTypes.NameIdentifierを使用できます。

私はこれをテストしませんでしたが、名前空間文字列を使用するよりも少しエレガントに見えます。

+0

トークンの "サブ"フィールドを使用すると、受け入れられた答えよりも標準的に見えますし、トークンのサイズも少し小さくなります:-) – youen