Skip to content

Instantly share code, notes, and snippets.

@antmdvs
Created June 10, 2021 19:12
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 antmdvs/6ad81b41b979ac522a16415ca6b3b24e to your computer and use it in GitHub Desktop.
Save antmdvs/6ad81b41b979ac522a16415ca6b3b24e to your computer and use it in GitHub Desktop.
// https://medium.com/asos-techblog/testing-authorization-scenarios-in-asp-net-core-web-api-484bc95d5f6f
// https://github.com/dylan-asos/netcore-authz-inmemory-bddfy/blob/master/src/Asos.DotNetCore.Auth.Api.ComponentTests/BearerTokenBuilder.cs
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
namespace IsildurClient.Test
{
public class JwtTokenBuilder
{
private X509Certificate2 _signingCertificate;
private string _issuer = "https://issuer.com";
private string _audience = "https://subject.com";
private TimeSpan _life = TimeSpan.FromHours(1);
private DateTime _notBefore = DateTime.UtcNow;
private readonly List<Claim> _claims = new List<Claim>();
private readonly JwtSecurityTokenHandler _securityTokenHandler = new JwtSecurityTokenHandler();
public JwtTokenBuilder IssuedBy(string issuer)
{
if (string.IsNullOrEmpty(issuer))
{
throw new ArgumentException("Issued by cannot be null or empty", nameof(issuer));
}
_issuer = issuer;
return this;
}
public JwtTokenBuilder ForAudience(string audience)
{
if (string.IsNullOrEmpty(audience))
{
throw new ArgumentException("Audience cannot be null or empty", nameof(audience));
}
_audience = audience;
return this;
}
public JwtTokenBuilder ForSubject(string subject)
{
if (string.IsNullOrEmpty(subject))
{
throw new ArgumentException("Subject cannot be null or empty", nameof(subject));
}
if (_claims.FirstOrDefault(claim => claim.Type == "sub") == null)
{
_claims.Add(new Claim("sub", subject));
}
return this;
}
public JwtTokenBuilder WithSigningCertificate(X509Certificate2 certificate)
{
_signingCertificate = certificate ?? throw new ArgumentException("Certificate cannot be null or empty", nameof(certificate));
return this;
}
public JwtTokenBuilder WithClaim(string claimType, string value)
{
if (string.IsNullOrEmpty(claimType))
{
throw new ArgumentException("Claim type cannot be null or empty", nameof(claimType));
}
if (value == null)
{
value = string.Empty;
}
_claims.Add(new Claim(claimType, value));
return this;
}
public JwtTokenBuilder WithLifetime(TimeSpan life)
{
if (life == null)
{
throw new ArgumentException("Lifetime cannot be null", nameof(life));
}
_life = life;
return this;
}
public JwtTokenBuilder NotBefore(DateTime notBefore)
{
if (notBefore == null)
{
throw new ArgumentException("Not before cannot be null", nameof(notBefore));
}
_notBefore = notBefore;
return this;
}
public string BuildToken()
{
if (_signingCertificate == null)
{
throw new InvalidOperationException(
"You must specify an X509 certificate to use for signing the JWT Token");
}
var signingCredentials = new SigningCredentials(new X509SecurityKey(_signingCertificate), SecurityAlgorithms.RsaSha256);
var notBefore = _notBefore;
var expires = notBefore.Add(_life);
var identity = new ClaimsIdentity(_claims);
var securityTokenDescriptor = new SecurityTokenDescriptor
{
Audience = _audience,
Issuer = _issuer,
NotBefore = notBefore,
Expires = expires,
SigningCredentials = signingCredentials,
Subject = identity
};
var token = _securityTokenHandler.CreateToken(securityTokenDescriptor);
var encodedAccessToken = _securityTokenHandler.WriteToken(token);
return encodedAccessToken;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment