Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@chriskuech
Created April 1, 2020 20:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chriskuech/c83dc2f7322aabc2169149d84d92dbb7 to your computer and use it in GitHub Desktop.
Save chriskuech/c83dc2f7322aabc2169149d84d92dbb7 to your computer and use it in GitHub Desktop.
[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