426 lines
12 KiB
C#
426 lines
12 KiB
C#
using System;
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
using xCommons.Extensions;
|
|
using xCommons.Providers;
|
|
using xExceptions.Constants;
|
|
using xIdentityModels.Configurations;
|
|
using xIdentityModels.Extensions;
|
|
using xIdentityModels.Models;
|
|
using xIds.Interfaces;
|
|
|
|
namespace xIds.Helpers
|
|
{
|
|
public class XIdentityHelper : IXIdentityHelper
|
|
{
|
|
private readonly XIdentityConfiguration configurations;
|
|
private readonly JwtSecurityTokenHandler tokenHandler;
|
|
private readonly XValidationProvider dataValidationHelper;
|
|
|
|
public XIdentityHelper(
|
|
XIdentityConfiguration configurations,
|
|
XValidationProvider dataValidationHelper
|
|
)
|
|
{
|
|
//
|
|
this.configurations = configurations;
|
|
this.tokenHandler = new JwtSecurityTokenHandler();
|
|
this.dataValidationHelper = dataValidationHelper;
|
|
}
|
|
|
|
//
|
|
#region Configuration Parser ...
|
|
/// <summary>
|
|
/// Generate a Key for Signing JWT Tokens
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public SymmetricSecurityKey GetTokenSecretKey()
|
|
{
|
|
//
|
|
dataValidationHelper
|
|
.NotEmpty(configurations.IdentitySecretKey);
|
|
|
|
//
|
|
var result = new SymmetricSecurityKey(configurations
|
|
.IdentitySecretKey.ToBytes());
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate Security Token Signing Key
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public SigningCredentials GetTokenSigningCredentials()
|
|
{
|
|
//
|
|
var key = GetTokenSecretKey();
|
|
dataValidationHelper
|
|
.NotNull(key);
|
|
|
|
//
|
|
var result = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get Token Validation Parameters
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public TokenValidationParameters GetTokenValidationParams()
|
|
{
|
|
//
|
|
var key = GetTokenSecretKey();
|
|
var issuer = configurations.IdentityIssuer;
|
|
var audience = configurations.IdentityAudience;
|
|
|
|
//
|
|
dataValidationHelper
|
|
.NotNull(key);
|
|
dataValidationHelper
|
|
.NotEmpty(issuer, audience);
|
|
|
|
//
|
|
var result = new TokenValidationParameters
|
|
{
|
|
ValidIssuer = issuer,
|
|
ValidAudience = audience,
|
|
ValidateLifetime = true,
|
|
IssuerSigningKey = key
|
|
};
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get Account Lockout Time Span after Max Fail Reached
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public TimeSpan GetLockoutTimeSpan()
|
|
{
|
|
//
|
|
dataValidationHelper
|
|
.NotNull(configurations.Policy, configurations.Policy.Lockout);
|
|
|
|
//
|
|
var timeSpanString = configurations.Policy.Lockout.LockoutTimeSpanProvider;
|
|
dataValidationHelper
|
|
.NotEmpty(timeSpanString);
|
|
|
|
//
|
|
var mExpireValue = 0;
|
|
var mExpireValueStr = timeSpanString.GetDigits();
|
|
var mExpireUnit = timeSpanString.Replace(mExpireValueStr, "");
|
|
dataValidationHelper
|
|
.NotEmpty(mExpireUnit);
|
|
dataValidationHelper
|
|
.NotEmpty(mExpireValueStr);
|
|
|
|
//
|
|
var isParsed = int.TryParse(mExpireValueStr, out mExpireValue);
|
|
|
|
//
|
|
switch (mExpireUnit)
|
|
{
|
|
case "d":
|
|
return TimeSpan.FromDays(mExpireValue);
|
|
|
|
case "h":
|
|
return TimeSpan.FromHours(mExpireValue);
|
|
|
|
case "m":
|
|
return TimeSpan.FromMinutes(mExpireValue);
|
|
|
|
case "s":
|
|
return TimeSpan.FromSeconds(mExpireValue);
|
|
|
|
case "ms":
|
|
default:
|
|
return TimeSpan.FromMilliseconds(mExpireValue);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate Security Token Descriptor for Tokenize another
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public SecurityTokenDescriptor GetActionTokenDescriptor()
|
|
{
|
|
//
|
|
dataValidationHelper
|
|
.NotNull(configurations);
|
|
|
|
//
|
|
var issuer = configurations.IdentityIssuer;
|
|
var audience = configurations.IdentityAudience;
|
|
dataValidationHelper
|
|
.NotEmpty(issuer, audience);
|
|
|
|
//
|
|
var expDate = GetActionTokenExpirationDate();
|
|
var signingCreds = GetTokenSigningCredentials();
|
|
dataValidationHelper
|
|
.NotNull(expDate, signingCreds);
|
|
|
|
//
|
|
var descriptor = new SecurityTokenDescriptor
|
|
{
|
|
Issuer = issuer,
|
|
Audience = audience,
|
|
Expires = expDate,
|
|
SigningCredentials = signingCreds
|
|
};
|
|
|
|
//
|
|
return descriptor;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get Action Token Expiration Date
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public DateTime GetActionTokenExpirationDate()
|
|
{
|
|
//
|
|
dataValidationHelper
|
|
.NotNull(configurations);
|
|
|
|
//
|
|
var expDateProvider = configurations
|
|
.ActionTokenExpirationDateProvider;
|
|
dataValidationHelper
|
|
.NotEmpty(expDateProvider);
|
|
|
|
//
|
|
var result = GetExpirationTime(expDateProvider);
|
|
dataValidationHelper
|
|
.NotNull(result);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
//
|
|
#region Action Token Handlers ...
|
|
public bool ValidateToken(string token)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
dataValidationHelper
|
|
.NotEmpty(token);
|
|
dataValidationHelper
|
|
.NotNull(tokenHandler);
|
|
|
|
//
|
|
// Prepare Requirements ...
|
|
var tokenValidationParams = GetTokenValidationParams();
|
|
dataValidationHelper
|
|
.NotNull(tokenValidationParams);
|
|
|
|
//
|
|
var result = token
|
|
.ValidateToken(tokenHandler, tokenValidationParams);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a Token string to SecurityToken instance
|
|
/// </summary>
|
|
/// <param name="token"></param>
|
|
/// <returns></returns>
|
|
public SecurityToken ToSecurityToken(string token)
|
|
{
|
|
//
|
|
dataValidationHelper
|
|
.NotEmpty(token);
|
|
|
|
//
|
|
// Validate token ...
|
|
var isTokenValid = ValidateToken(token);
|
|
if (!isTokenValid)
|
|
{
|
|
XException.InvalidToken.Throw();
|
|
}
|
|
|
|
//
|
|
// Prepare and Validate Requirements ...
|
|
var tokenValidationParams = GetTokenValidationParams();
|
|
dataValidationHelper
|
|
.NotNull(tokenHandler, tokenValidationParams);
|
|
|
|
//
|
|
var result = token
|
|
.ToSecurityToken(tokenHandler, tokenValidationParams);
|
|
dataValidationHelper
|
|
.NotNull(result);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert an ActionRequest to Token Object
|
|
/// </summary>
|
|
/// <param name="request"></param>
|
|
/// <returns></returns>
|
|
public SecurityToken ToSecurityToken(XActionRequestToken request)
|
|
{
|
|
//
|
|
var tokenDescriptor = GetActionTokenDescriptor();
|
|
|
|
//
|
|
dataValidationHelper.NotNull(request, tokenHandler, tokenDescriptor);
|
|
|
|
//
|
|
var result = request.ToJwtToken(tokenHandler, tokenDescriptor);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve a Token Exiration Date
|
|
/// </summary>
|
|
/// <param name="token"></param>
|
|
/// <returns></returns>
|
|
public DateTime GetTokenExpirationDate(string token)
|
|
{
|
|
//
|
|
var tokenObj = ToSecurityToken(token);
|
|
dataValidationHelper.NotNull(tokenObj);
|
|
|
|
//
|
|
var result = tokenObj.ValidTo;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
public XActionRequestToken ParseActionRequestToken(string token)
|
|
{
|
|
//
|
|
dataValidationHelper
|
|
.NotEmpty(token);
|
|
|
|
//
|
|
// Validate token ...
|
|
var isTokenValid = ValidateToken(token);
|
|
if (!isTokenValid)
|
|
{
|
|
XException.InvalidToken.Throw();
|
|
}
|
|
|
|
//
|
|
// Prepare and Validate Requirements ...
|
|
var tokenValidationParams = GetTokenValidationParams();
|
|
dataValidationHelper
|
|
.NotNull(tokenHandler, tokenValidationParams);
|
|
|
|
//
|
|
var result = token
|
|
.ParseActionRequestToken(tokenHandler, tokenValidationParams);
|
|
dataValidationHelper
|
|
.NotNull(result);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert a JWT Security Token Object to
|
|
/// it's String Representation
|
|
/// </summary>
|
|
/// <param name="token"></param>
|
|
/// <returns></returns>
|
|
public string ToTokenString(JwtSecurityToken token)
|
|
{
|
|
//
|
|
dataValidationHelper.NotNull(token);
|
|
|
|
//
|
|
var result = tokenHandler
|
|
.WriteToken(token);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert an Action Token Object to it's String Representation
|
|
/// </summary>
|
|
/// <param name="token"></param>
|
|
/// <returns></returns>
|
|
public string ToTokenString(SecurityToken token)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
dataValidationHelper
|
|
.NotNull(token, tokenHandler);
|
|
|
|
//
|
|
// Generate and return Result ...
|
|
var result = token.ToTokenString(tokenHandler);
|
|
dataValidationHelper
|
|
.NotEmpty(result);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
//
|
|
#region Private Actions ...
|
|
/// <summary>
|
|
/// Calculating Date Difference Provider String
|
|
/// and Generate Date based on UTC Time
|
|
/// </summary>
|
|
/// <param name="expirationProvider"></param>
|
|
/// <returns></returns>
|
|
private DateTime GetExpirationTime(string expirationProvider)
|
|
{
|
|
//
|
|
dataValidationHelper
|
|
.NotEmpty(expirationProvider);
|
|
|
|
//
|
|
var mExpireValue = 0;
|
|
var mExpireValueStr = expirationProvider.GetDigits();
|
|
var mExpireUnit = expirationProvider.Replace(mExpireValueStr, "");
|
|
dataValidationHelper
|
|
.NotEmpty(mExpireUnit);
|
|
dataValidationHelper
|
|
.NotEmpty(mExpireValueStr);
|
|
|
|
//
|
|
var isParsed = int.TryParse(mExpireValueStr, out mExpireValue);
|
|
|
|
//
|
|
switch (mExpireUnit)
|
|
{
|
|
case "d":
|
|
return DateTime.UtcNow.AddDays(mExpireValue);
|
|
|
|
case "h":
|
|
return DateTime.UtcNow.AddHours(mExpireValue);
|
|
|
|
case "m":
|
|
return DateTime.UtcNow.AddMinutes(mExpireValue);
|
|
|
|
case "s":
|
|
return DateTime.UtcNow.AddSeconds(mExpireValue);
|
|
|
|
case "ms":
|
|
default:
|
|
return DateTime.UtcNow.AddMilliseconds(mExpireValue);
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
} |