-
Petar Hristov authoredPetar Hristov authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
JwtUtil.cs 4.99 KiB
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using Winton.Extensions.Configuration.Consul;
namespace Coscine.ApiClient.Core
{
public class JwtUtil
{
public static JwtConfiguration RetrieveJwtConfiguration(string environment = "development", string? givenConsulUrl = null)
{
var consulUrl = givenConsulUrl ?? Environment.GetEnvironmentVariable("CONSUL_URL") ?? "http://localhost:8500";
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: true)
.AddConsul(
"coscine/Coscine.Api/appsettings",
options =>
{
options.ConsulConfigurationOptions =
cco => cco.Address = new Uri(consulUrl);
options.Optional = true;
options.ReloadOnChange = true;
options.PollWaitTime = TimeSpan.FromSeconds(5);
options.OnLoadException = exceptionContext => exceptionContext.Ignore = true;
}
)
.AddConsul(
$"coscine/Coscine.Api/appsettings.{environment}",
options =>
{
options.ConsulConfigurationOptions =
cco => cco.Address = new Uri(consulUrl);
options.Optional = true;
options.ReloadOnChange = true;
options.PollWaitTime = TimeSpan.FromSeconds(5);
options.OnLoadException = exceptionContext => exceptionContext.Ignore = true;
}
)
.AddEnvironmentVariables()
.Build();
return RetrieveJwtConfiguration(configuration);
}
public static JwtConfiguration RetrieveJwtConfiguration(IConfiguration configuration)
{
var jwtConfiguration = new JwtConfiguration();
configuration.Bind(JwtConfiguration.Section, jwtConfiguration);
return jwtConfiguration;
}
public static string GenerateAdminToken(JwtConfiguration jwtConfiguration, int expiresInDays = 1)
{
var jwtSecurityToken = GenerateJwtSecurityToken(
jwtConfiguration,
new Dictionary<string, string>
{
[ClaimTypes.Role] = "administrator"
},
TimeSpan.FromDays(expiresInDays).TotalMinutes,
jwtConfiguration.JsonWebKeys.First(x => x.KeySize >= 256)
);
return GetJwtStringFromToken(jwtSecurityToken);
}
/// <summary>Generates the JWT security token.</summary>
/// <param name="jwtConfiguration">Jwt Configuration.</param>
/// <param name="payloadContents">The payload contents.</param>
/// <param name="expiresInMinutes">The expires in minutes.</param>
/// <param name="jsonWebKey">The json web key.</param>
/// <returns>The generated JWT security token.</returns>
public static JwtSecurityToken GenerateJwtSecurityToken(JwtConfiguration jwtConfiguration, IReadOnlyDictionary<string, string> payloadContents, double expiresInMinutes, JsonWebKey jsonWebKey)
{
var now = DateTime.UtcNow;
// Create claims for the JWT token
var claims = payloadContents.Select(c => new Claim(c.Key, c.Value)).ToList();
claims.Add(new Claim("iat", EpochTime.GetIntDate(now).ToString(), ClaimValueTypes.Integer64));
// Create the security key from the secret key
var securityKey = new SymmetricSecurityKey(Base64UrlEncoder.DecodeBytes(jsonWebKey.K));
// Create signing credentials using the security key
var signingCredentials = new SigningCredentials(securityKey, jsonWebKey.Alg);
// Create the JWT token
return new JwtSecurityToken(
issuer: jwtConfiguration.ValidIssuers[0],
audience: jwtConfiguration.ValidAudiences[0],
claims: claims,
notBefore: now,
expires: now.AddMinutes(expiresInMinutes), // Token expiration time
signingCredentials: signingCredentials
);
}
/// <summary>Gets the JWT string from token.</summary>
/// <param name="token">The token.</param>
/// <returns>The JWT as a string.</returns>
public static string GetJwtStringFromToken(JwtSecurityToken token)
{
// Generate the encoded JWT token
var tokenHandler = new JwtSecurityTokenHandler();
return tokenHandler.WriteToken(token);
}
}
}