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 ...
///
/// Generate a Key for Signing JWT Tokens
///
///
public SymmetricSecurityKey GetTokenSecretKey()
{
//
dataValidationHelper
.NotEmpty(configurations.IdentitySecretKey);
//
var result = new SymmetricSecurityKey(configurations
.IdentitySecretKey.ToBytes());
//
return result;
}
///
/// Generate Security Token Signing Key
///
///
public SigningCredentials GetTokenSigningCredentials()
{
//
var key = GetTokenSecretKey();
dataValidationHelper
.NotNull(key);
//
var result = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
//
return result;
}
///
/// Get Token Validation Parameters
///
///
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;
}
///
/// Get Account Lockout Time Span after Max Fail Reached
///
///
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);
}
}
///
/// Generate Security Token Descriptor for Tokenize another
///
///
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;
}
///
/// Get Action Token Expiration Date
///
///
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;
}
///
/// Converts a Token string to SecurityToken instance
///
///
///
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;
}
///
/// Convert an ActionRequest to Token Object
///
///
///
public SecurityToken ToSecurityToken(XActionRequestToken request)
{
//
var tokenDescriptor = GetActionTokenDescriptor();
//
dataValidationHelper.NotNull(request, tokenHandler, tokenDescriptor);
//
var result = request.ToJwtToken(tokenHandler, tokenDescriptor);
//
return result;
}
///
/// Retrieve a Token Exiration Date
///
///
///
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;
}
///
/// Convert a JWT Security Token Object to
/// it's String Representation
///
///
///
public string ToTokenString(JwtSecurityToken token)
{
//
dataValidationHelper.NotNull(token);
//
var result = tokenHandler
.WriteToken(token);
//
return result;
}
///
/// Convert an Action Token Object to it's String Representation
///
///
///
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 ...
///
/// Calculating Date Difference Provider String
/// and Generate Date based on UTC Time
///
///
///
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
}
}