2017-06-28 42 views
0

我在React JS中擁有.net核心Web API和SPA客戶端。我想允許用戶使用在Azure AD中註冊的電子郵件從客戶端登錄,並使用JWT令牌保護我的web api。我嘗試使用簡單的硬編碼用戶名和密碼生成令牌,但我不知道如何從Azure AD獲取用戶並生成JWT令牌。如何在使用JWT令牌保護asp.net核心Web API時從Azure AD獲取用戶

這裏是我的JWTController:

[Route("api/[controller]")] 
public class JwtController : Controller 
{ 
    private readonly JwtIssuerOptions _jwtOptions; 
    private readonly ILogger _logger; 
    private readonly JsonSerializerSettings _serializerSettings; 

    public JwtController(IOptions<JwtIssuerOptions> jwtOptions, ILoggerFactory loggerFactory) 
    { 
     _jwtOptions = jwtOptions.Value; 
     ThrowIfInvalidOptions(_jwtOptions); 

     _logger = loggerFactory.CreateLogger<JwtController>(); 

     _serializerSettings = new JsonSerializerSettings 
     { 
      Formatting = Formatting.Indented 
     }; 
    } 

    [HttpPost] 
    [AllowAnonymous] 
    public async Task<IActionResult> Get([FromForm] string Username, string Password) 
    { 
     var applicationUser = new ApplicationUser(); 
     applicationUser.UserName = Username; 
     applicationUser.Password = Password; 
     var identity = await GetClaimsIdentity(applicationUser); 
     if (identity == null) 
     { 
      _logger.LogInformation($"Invalid username({applicationUser.UserName}) or password ({applicationUser.Password})"); 
      return BadRequest("Invalid credentials"); 
     } 

     var claims = new[] 
     { 
      new Claim(JwtRegisteredClaimNames.Sub, applicationUser.UserName), 
      new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()), 
      new Claim(JwtRegisteredClaimNames.Iat, 
       ToUnixExpochDate(_jwtOptions.IssuedAt).ToString(), 
       ClaimValueTypes.Integer64), 
      identity.FindFirst("Disney") 
     }; 

     //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); 
    } 

    private static void ThrowIfInvalidOptions(JwtIssuerOptions options) 
    { 
     if (options == null) throw new ArgumentNullException(nameof(options)); 

     if (options.ValidFor <= TimeSpan.Zero) 
     { 
      throw new ArgumentException("Must be a non-zero TimeSpan.", nameof(JwtIssuerOptions.ValidFor)); 
     } 

     if (options.SigningCredentials == null) 
     { 
      throw new ArgumentNullException(nameof(JwtIssuerOptions.SigningCredentials)); 
     } 

     if (options.JtiGenerator == null) 
     { 
      throw new ArgumentNullException(nameof(JwtIssuerOptions.JtiGenerator)); 
     } 
    } 

    private static long ToUnixExpochDate(DateTime date) 
     => (long)Math.Round((date.ToUniversalTime() - 
      new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)) 
      .TotalSeconds); 

    private Task<ClaimsIdentity> GetClaimsIdentity(ApplicationUser user) 
    { 
     if (user.UserName == "mickey" && user.Password == "mouse") 
     { 
      return Task.FromResult(new ClaimsIdentity(
       new GenericIdentity(user.UserName, "Token"), 
       new[] 
       { 
        new Claim("Disney", "mickey") 
       })); 
     } 

     if (user.UserName == "notmickey" && user.Password == "mouse") 
     { 
      return Task.FromResult(new ClaimsIdentity(
       new GenericIdentity(user.UserName, "Token"), 
       new Claim[] { })); 
     } 

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

人有一個想法如何實現這一點?

回答

1

我想你已經有點倒退了。

您的React客戶端應該重定向到Azure AD登錄頁面,然後從Azure AD獲取JWT 以調用您的API。然後你的API只需要驗證傳入的令牌併爲請求建立一個用戶標識。在ASP.NET Core中有現成的組件。使用Adal.js與之反應的

一個例子:https://blog.mastykarz.nl/building-office-365-web-applications-react/

在ASP.NET MVC核心API Azure的AD V2使用示例:https://contos.io/protecting-a-net-core-api-with-azure-active-directory-59bbcd5b3429

+0

我不明白這一點。 JWT令牌如何通過客戶端的簡單重定向從AzureAD生成? –

+0

請參閱此處的流程圖瞭解其工作原理:https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-authentication-scenarios#single-page-application-溫泉。如果您的API和SPA前端在Azure AD中實際上是同一個應用程序,那麼您可以在他們提到的地方進行操作,然後只發送ID令牌。否則,您可以使用Adal.js爲其他API獲取額外的訪問令牌。 – juunas

+0

還有一個使用Angular的示例應用程序:https://github.com/Azure-Samples/active-directory-angularjs-singlepageapp – juunas

相關問題