<Reusing JWT;
using JWT.Algorithms;
using JWT.Builder;
using JWT.Serializers;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
namespace Tango.Web.Security
{
public class WebToken
{
public DateTime Issued { get; protected set; }
public DateTime? Expiration { get; protected set; }
public String AccessToken { get; protected set; }
public String RefreshToken { get; protected set; }
public WebToken()
{
}
public static WebToken CreateNew(String secret, DateTime? expiration = null)
{
DateTime issued = DateTime.UtcNow;
var builder = new JwtBuilder()
.WithAlgorithm(new HMACSHA256Algorithm())
.WithSecret(secret)
.IssuedAt(issued);
if (expiration != null)
{
builder = builder.ExpirationTime(expiration.Value);
}
String refreshToken = Guid.NewGuid().ToString();
builder = builder.AddClaim("object", null);
builder = builder.AddClaim("refresh-token", refreshToken);
return new WebToken()
{
AccessToken = builder.Build(),
RefreshToken = refreshToken,
Expiration = expiration,
Issued = issued,
};
}
public static void Validate(String secret, String token)
{
var json = new JwtBuilder()
.WithSecret(secret)
.MustVerifySignature()
.Decode(token);
}
public void Validate(String secret)
{
var json = new JwtBuilder()
.WithSecret(secret)
.MustVerifySignature()
.Decode(AccessToken);
}
public WebToken Renew(String secret)
{
var newToken = CreateNew(secret, DateTime.UtcNow.Add(Expiration.Value - Issued));
newToken.RefreshToken = RefreshToken;
return newToken;
}
public static WebToken FromToken(String token)
{
WebToken webToken = new WebToken();
var payload = new JwtBuilder()
.WithValidator(null)
.Decode<IDictionary<string, object>>(token);
webToken.AccessToken = token;
if (payload.ContainsKey("exp"))
{
long exp = long.Parse(payload["exp"].ToString());
webToken.Expiration = ConvertEpochToDateTime(exp);
}
if (payload.ContainsKey("iat"))
{
long iat = long.Parse(payload["iat"].ToString());
webToken.Issued = ConvertEpochToDateTime(iat);
}
if (payload.ContainsKey("refresh-token"))
{
webToken.RefreshToken = payload["refresh-token"].ToString();
}
return webToken;
}
protected static DateTime ConvertEpochToDateTime(long seconds)
{
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return epoch.AddSeconds(seconds);
}
}
public class WebToken<T> : WebToken where T : class
{
public T Object { get; protected set; }
private WebToken()
{
}
public static WebToken<T> CreateNew(String secret, T obj = null, DateTime? expiration = null)
{
DateTime issued = DateTime.UtcNow;
var builder = new JwtBuilder()
.WithAlgorithm(new HMACSHA256Algorithm())
.WithSecret(secret)
.IssuedAt(issued);
if (expiration != null)
{
builder = builder.ExpirationTime(expiration.Value);
}
String refreshToken = Guid.NewGuid().ToString();
builder = builder.AddClaim("object", obj);
builder = builder.AddClaim("refresh-token", refreshToken);
return new WebToken<T>()
{
AccessToken = builder.Build(),
RefreshToken = refreshToken,
Expiration = expiration,
Issued = issued,
Object = obj,
};
}
public static new WebToken<T> FromToken(String token)
{
WebToken<T> webToken = new WebToken<T>();
var payload = new JwtBuilder()
.WithValidator(null)
.Decode<IDictionary<string, object>>(token);
webToken.AccessToken = token;
if (payload.ContainsKey("exp"))
{
long exp = long.Parse(payload["exp"].ToString());
webToken.Expiration = ConvertEpochToDateTime(exp);
}
if (payload.ContainsKey("iat"))
{
long iat = long.Parse(payload["iat"].ToString());
webToken.Issued = ConvertEpochToDateTime(iat);
}
if (payload.ContainsKey("refresh-token"))
{
webToken.RefreshToken = payload["refresh-token"].ToString();
}
webToken.Object = JsonConvert.DeserializeObject<T>(payload["object"].ToString());
return webToken;
}
public new WebToken<T> Renew(String secret)
{
var newToken = WebToken<T>.CreateNew(secret, Object, DateTime.UtcNow.Add(Expiration.Value - Issued));
newToken.RefreshToken = RefreshToken;
return newToken;
}
}
}