using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using xCommons.Constants;
using xCommons.Extensions;
using xExceptions.Constants;
using xExceptions.Models;
using xIdentityModels.Models;
using xIdentityService.Interfaces;
public static partial class XTokenExtensions {
///
/// Retrieve Tokens From Headers
///
///
///
public static XLoginResponse RetrieveTokens (this HttpRequest source) {
//
var accessToken = source.Headers[XAuthorization.Header].ToString ();
var refreshToken = source.Headers[XAuthorization.RefreshToken].ToString ();
//
var expiresAtStr = source.Headers[XAuthorization.ExpiresAt].ToString ();
long expiresAt = expiresAtStr.ConvertTo ();
//
if (accessToken
.ToNormalString ()
.Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
}
//
return new XLoginResponse {
AccessToken = accessToken,
RefreshToken = refreshToken,
ExpiresAt = expiresAt
};
}
///
/// Retrieve Tokens From HttpContext
///
///
///
public static async Task RetrieveTokens (this HttpContext source) {
//
var accessToken = await source.GetTokenAsync (XAuthorization.AccessToken);
if (accessToken
.ToNormalString ()
.Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
}
var refreshToken = await source.GetTokenAsync (XAuthorization.RefreshToken);
var expiresAtStr = await source.GetTokenAsync (XAuthorization.ExpiresAt);
long expiresAt = expiresAtStr.ConvertTo ();
//
var headerRequestTokens = source.Request.RetrieveTokens ();
//
var result = new XLoginResponse {
AccessToken = accessToken ?? headerRequestTokens.AccessToken,
RefreshToken = refreshToken ?? headerRequestTokens.RefreshToken,
ExpiresAt = expiresAt != 0 ? expiresAt : headerRequestTokens.ExpiresAt
};
//
return result;
}
///
/// Retrieve Tokens From ActionExecutingContext
///
///
///
public static async Task RetrieveTokens (this ActionExecutingContext source) {
//
var result = await source.HttpContext.RetrieveTokens ();
return result;
}
///
/// Retrieve Tokens From XUserInfo instance
///
///
///
public static XTokenResponse RetrieveTokens (this XUserClaimsInfoDto source) {
//
var result = new XLoginResponse {
AccessToken = source.AccessToken,
RefreshToken = source.RefreshToken,
ExpiresAt = source.ExpiresAt
};
//
return result;
}
///
/// Retrieve Tokens From IHeader Dictionary
///
///
///
public static XLoginResponse RetrieveTokens (this IHeaderDictionary source) {
//
var accessToken = source[XAuthorization.Header].ToString () ?? "";
if (accessToken
.ToNormalString ()
.Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
}
//
var refreshToken = source[XAuthorization.RefreshToken].ToString () ?? "";
//
var expiresAtStr = source[XAuthorization.ExpiresAt].ToString () ?? "";
var expiresAt = expiresAtStr.ConvertTo ();
//
var result = new XLoginResponse {
AccessToken = accessToken,
RefreshToken = refreshToken,
ExpiresAt = expiresAt
};
//
return result;
}
///
/// Retrieve IXIdentityProvider from HttpContext
///
///
///
public static IXIdentityProvider GetXApiIdentityProvider (this FilterContext source) {
//
var services = source.HttpContext.RequestServices;
return (IXIdentityProvider) services
.GetService (typeof (IXIdentityProvider));
}
///
/// Generate XLoginResponse instance based on TokenResponse
///
///
///
public static XLoginResponse CreateXLoginResponse (this TokenResponse source) {
//
if (source.IsNull () ||
source.IsError) {
XException.InvalidToken.Throw ();
}
//
var expiresAt = new DateTimeOffset (DateTime.UtcNow)
.ToUnixTimeSeconds () +
source.ExpiresIn;
//
var result = new XLoginResponse {
AccessToken = source.AccessToken,
RefreshToken = source.RefreshToken,
ExpiresAt = expiresAt
};
//
return result;
}
///
/// Add Authorization Tokens in Headers of
/// Specific IHeaderDictionary instance
///
///
///
public static void SetXAuthenticationTokens (this IHeaderDictionary source, XLoginResponse model, string secret = null) {
//
source.Remove (XAuthorization.Header);
source.Remove (XAuthorization.RefreshToken);
source.Remove (XAuthorization.ExpiresAt);
source.Remove (XAuthorization.RevisionChecksum);
//
source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}");
source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}");
source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}");
//
if (!secret.IsNullOrEmpty ()) {
var revisionChecksum = model.GetRevisionChecksum (secret);
source.Add (XAuthorization.RevisionChecksum, revisionChecksum);
}
}
///
/// Add Authorization Tokens in Headers of
/// Specific IHeaderDictionary instance
///
///
///
public static void SetXAuthenticationTokens (this HttpRequestHeaders source, XLoginResponse model) {
//
source.Remove (XAuthorization.Header);
source.Remove (XAuthorization.RefreshToken);
source.Remove (XAuthorization.ExpiresAt);
source.Remove (XAuthorization.RevisionChecksum);
//
source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}");
source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}");
source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}");
}
///
/// Add Authorization Tokens in Headers of
/// Specific HttpRequest instance
///
///
///
public static void SetXAuthenticationTokens (this HttpRequest source, XLoginResponse model) {
source.Headers.SetXAuthenticationTokens (model);
}
///
/// Add Authorization Tokens in Headers of
/// Specific HttpRequest instance
///
///
///
public static void SetXAuthenticationTokens (this HttpRequestMessage source, XLoginResponse model) {
source.Headers.SetXAuthenticationTokens (model);
}
///
/// Add ReNewed Authorization Tokens in Headers of
/// Specific Response.
/// Later in HttpInterceptors we can Look for AccessToken-ReNewed
/// header Value and Renew User Tokens based on it
///
///
///
public static void SetXAuthenticationTokens (this HttpResponse source, XLoginResponse model, string secret) {
source.Headers.SetXAuthenticationTokens (model, secret);
}
///
/// Determines a Token Can Refrsh or not
///
///
///
public static bool IsRefreshable (this XLoginResponse source) {
//
var containsTokenData = !source.IsNull () &&
!source.AccessToken.IsNullOrEmpty () &&
!source.RefreshToken.IsNullOrEmpty ();
if (!containsTokenData) {
return false;
}
//
var current = new DateTimeOffset (DateTime.UtcNow)
.ToUnixTimeSeconds ();
//
// var result = current > source.ExpiresAt || current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration;
var result = current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration;
//
return result;
}
///
/// Generate a Revision Checksum for new Tokens
///
///
///
///
public static string GetRevisionChecksum (this XLoginResponse source, string secret) {
return (source.AccessToken +
secret +
source.RefreshToken +
secret +
source.ExpiresAt.ToString ()
)
.ToMd5String ();
}
///
/// Generate a Revision Checksum for new Tokens
///
///
///
///
public static string GetRevisionChecksum (this XTokenResponse source, string secret) {
return (source.AccessToken +
secret +
source.RefreshToken +
secret +
source.ExpiresAt.ToString ()
)
.ToMd5String ();
}
///
/// Check an XLoginResponse instance is Valid with it's revision
///
///
///
///
///
public static bool ValidateRevisionChecksum (this XLoginResponse source, string checksum, string secret) {
//
var xChecksum = source.GetRevisionChecksum (secret);
return checksum == xChecksum;
}
///
/// Check an XTokenResponse instance is Valid with it's revision
///
///
///
///
///
public static bool ValidateRevisionChecksum (this XTokenResponse source, string checksum, string secret) {
//
var xChecksum = source.GetRevisionChecksum (secret);
return checksum == xChecksum;
}
///
/// Retrieve Exception Details if Fails
///
///
///
public static Exception GetException (this TokenResponse source) {
//
// Validate Args ...
if (source.IsNull () || !source.IsError) {
return XException.ActionFailed.ToException ();
}
//
XError error = source.ErrorDescription.FromJSON ();
return error.ToException ();
}
///
/// Convert XTokenResponse to Header Dictionary
///
///
///
public static IDictionary ToHeaderDictionary (this XTokenResponse source) {
//
var result = new Dictionary { { XAuthorization.RefreshToken, source.RefreshToken },
{ XAuthorization.ExpiresAt, source.ExpiresAt.ToString () }
};
//
return result;
}
}