Last active
November 1, 2016 08:20
-
-
Save testfirstcoder/95ea7549cef7384fb78dad36a50fbd5b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Authorization; | |
using Microsoft.AspNetCore.Mvc; | |
using Microsoft.Extensions.Logging; | |
using Microsoft.Extensions.Options; | |
using Newtonsoft.Json; | |
using System; | |
using System.IdentityModel.Tokens.Jwt; | |
using System.Security.Claims; | |
using System.Security.Principal; | |
using System.Threading.Tasks; | |
using WebApiJwtAuthDemo.Models; | |
using WebApiJwtAuthDemo.Options; | |
namespace WebApiJwtAuthDemo.Controllers | |
{ | |
[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] ApplicationUser applicationUser) | |
{ | |
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, | |
ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), | |
ClaimValueTypes.Integer64), | |
identity.FindFirst("DisneyCharacter") | |
}; | |
// 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)); | |
} | |
} | |
/// <returns>Date converted to seconds since Unix epoch (Jan 1, 1970, midnight UTC).</returns> | |
private static long ToUnixEpochDate(DateTime date) => new DateTimeOffset(date).ToUnixTimeSeconds(); | |
/// <summary> | |
/// IMAGINE BIG RED WARNING SIGNS HERE! | |
/// You'd want to retrieve claims through your claims provider | |
/// in whatever way suits you, the below is purely for demo purposes! | |
/// </summary> | |
private static Task<ClaimsIdentity> GetClaimsIdentity(ApplicationUser user) | |
{ | |
if (user.UserName == "MickeyMouse" && | |
user.Password == "MickeyMouseIsBoss123") | |
{ | |
return Task.FromResult(new ClaimsIdentity( | |
new GenericIdentity(user.UserName, "Token"), | |
new[] | |
{ | |
new Claim("DisneyCharacter", "IAmMickey") | |
})); | |
} | |
if (user.UserName == "NotMickeyMouse" && | |
user.Password == "MickeyMouseIsBoss123") | |
{ | |
return Task.FromResult(new ClaimsIdentity( | |
new GenericIdentity(user.UserName, "Token"), | |
new Claim[] { })); | |
} | |
// Credentials are invalid, or account doesn't exist | |
return Task.FromResult<ClaimsIdentity>(null); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment