-
-
Save chriskuech/c83dc2f7322aabc2169149d84d92dbb7 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
[Route(Constants.TokenRoute)] | |
[Consumes("application/json")] | |
[Produces("application/json")] | |
[ApiController] | |
public class TokenController : ControllerBase | |
{ | |
private static readonly JsonWebTokenHandler TokenHandler = new JsonWebTokenHandler(); | |
private X509SigningCredentials signingCredentials; | |
public TokenController( | |
// Add this to dependency injection. | |
IEnumerable<X509Certificate2> signingCertificates) | |
{ | |
var signingCertificate = signingCertificates | |
.OrderByDescending(certificate => certificate.NotAfter) | |
.First(); | |
this.signingCredentials = new X509SigningCredentials(signingCertificate); | |
} | |
[HttpPost] | |
public async Task<IActionResult> PostToken([FromBody] TokenRequest tokenRequest) | |
{ | |
try | |
{ | |
// Disable caching. | |
Response.Headers.Add("Cache-Control", CacheControlHeaderValue.NoStoreString); | |
Response.Headers.Add("Pragma", CacheControlHeaderValue.NoCacheString); | |
await AssertValidClient(tokenRequest); | |
await AssertValidScopes(tokenRequest); | |
var claims = await DeriveClaims(tokenRequest); | |
var now = DateTime.UtcNow; | |
var lifespan = TimeSpan.FromMinutes(Constants.TokenLifespanMins); | |
var tokenDescriptor = new SecurityTokenDescriptor | |
{ | |
Claims = claims, | |
Expires = now + lifespan, | |
Issuer = Constants.Issuer, | |
NotBefore = now, | |
SigningCredentials = this.signingCredentials, | |
}; | |
var token = TokenHandler.CreateToken(tokenDescriptor); | |
return Ok(token); | |
} | |
catch (ClientException exception) | |
{ | |
return BadRequest(exception.Message); | |
} | |
} | |
public async Task AssertValidClient(TokenRequest tokenRequest) | |
{ | |
// Implement this method. | |
// This method will determine if the identity provided by the client in the tokenRequest or HttpContext is valid, using your team's aforementioned identity provider. | |
// Throw a ClientException if the client's identity is invalid. | |
throw new NotImplementedException(); | |
} | |
public async Task AssertValidScopes(TokenRequest tokenRequest) | |
{ | |
// Implement this method. | |
// This method will determine if the identity provided by the client in the tokenRequest has access to the scopes defined in the tokenRequest. | |
// Throw a ClientException if the client requested scopes it does not have access to. | |
throw new NotImplementedException(); | |
} | |
public async Task<IDictionary<string, object>> DeriveClaims(TokenRequest tokenRequest) | |
{ | |
// Implement this method. | |
// This method will derive additional identity information about the client from the tokenRequest, HttpContext, and (probably) a database and return them in a dictionary mapping claim types to claim values. | |
// Don't forget to set a `scope` claim in your token for use by your servers! | |
// Return a Dictionary<string, object> mapping Claim types to Claim values. | |
throw new NotImplementedException(); | |
} | |
} | |
/// <summary> | |
/// Throw if the client request is invalid. | |
/// </summary> | |
class ClientException : Exception | |
{ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment