Initial Commit ...

This commit is contained in:
2024-01-25 04:44:02 +03:30
commit a8e257b855
36 changed files with 6645 additions and 0 deletions
@@ -0,0 +1,32 @@
using IdentityModel;
using Microsoft.AspNetCore.Authorization;
namespace xIdentityService.Extensions {
public static class AuthorizationPolicyBuilderExtensions {
/// <summary>
/// Adds a policy to check for required scopes.
/// </summary>
/// <param name="builder"></param>
/// <param name="scope">List of any required scopes. The token must contain at least one of the listed scopes.</param>
/// <returns></returns>
public static AuthorizationPolicyBuilder RequireScope (this AuthorizationPolicyBuilder builder, params string[] scope) {
return builder.RequireClaim (JwtClaimTypes.Scope, scope);
}
}
/// <summary>
/// Helper for creating scope-related policies
/// </summary>
public static class ScopePolicy {
/// <summary>
/// Creates a policy to check for required scopes.
/// </summary>
/// <param name="scopes">List of any required scopes. The token must contain at least one of the listed scopes.</param>
/// <returns></returns>
public static AuthorizationPolicy Create (params string[] scopes) {
return new AuthorizationPolicyBuilder ()
.RequireScope (scopes)
.Build ();
}
}
}
+145
View File
@@ -0,0 +1,145 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Constants;
using xCommons.Extensions;
using xIdentityModels.Models;
using xIdentityService.Constants;
namespace xIdentityService.Extensions {
public static class HttpContextExtensions {
/// <summary>
/// Retrieve Authentication Service ...
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public static IAuthenticationService GetAuthenticationService (this HttpContext context) {
//
var result = context.RequestServices
.GetRequiredService<IAuthenticationService> ();
//
return result;
}
/// <summary>
/// Retrieve Specific Token from HttpContext ...
/// </summary>
/// <param name="context"></param>
/// <param name="tokenName"></param>
/// <param name="scheme"></param>
/// <returns></returns>
public static async Task<string> GetXTokenAsync (
this HttpContext context,
string tokenName,
XAuthenticationScheme scheme = XAuthenticationScheme.XToken
) {
//
// Validate Args ...
if (tokenName.IsNullOrEmpty ()) {
return null;
}
//
var authService = context.GetAuthenticationService ();
if (authService.IsNull ()) {
return null;
}
//
var authResult = await authService
.AuthenticateAsync (
context,
scheme
.GetStringValue ()
);
//
var result = authResult?.Properties?
.GetTokenValue (tokenName);
return result;
}
/// <summary>
/// Retrieve Access Token
/// </summary>
/// <returns></returns>
public static async Task<string> GetAccessToken (this HttpContext context) {
//
var accessToken = context.Request.Headers[XAuthorization.Header]
.ToString ();
if (accessToken.IsNullOrEmpty ()) {
accessToken = await context
.GetTokenAsync (XAuthorization.AccessToken);
}
//
if (accessToken
.ToNormalString ()
.Contains (XAuthorization.TokenIdentifier
.ToNormalString ())) {
accessToken = accessToken
.Remove (0, XAuthorization.TokenIdentifier.Length);
}
//
return accessToken;
}
/// <summary>
/// Retrieve Refresh Token
/// </summary>
/// <returns></returns>
public static async Task<string> GetRefreshToken (this HttpContext context) {
//
var refreshToken = context.Request.Headers[XAuthorization.RefreshToken]
.ToString ();
if (refreshToken.IsNullOrEmpty ()) {
refreshToken = await context
.GetTokenAsync (XAuthorization.RefreshToken);
}
//
return refreshToken;
}
/// <summary>
/// Retrieve Access Token Expiration Date
/// </summary>
/// <returns></returns>
public static async Task<long> GetTokenExpiresAt (this HttpContext context) {
//
var expiresAtStr = context.Request.Headers[XAuthorization.ExpiresAt]
.ToString ();
if (expiresAtStr.IsNullOrEmpty ()) {
expiresAtStr = await context
.GetTokenAsync (XAuthorization.ExpiresAt);
}
//
var expiresAt = expiresAtStr.ConvertTo<long> ();
//
return expiresAt;
}
/// <summary>
/// Retrieve All Required Tokens
/// </summary>
/// <returns></returns>
public static async Task<XTokenResponse> RetrieveTokensAsXTokenResponse (HttpContext context) {
//
var accessToken = await GetAccessToken (context);
var refreshToken = await GetRefreshToken (context);
var expiresAt = await GetTokenExpiresAt (context);
//
return new XTokenResponse {
AccessToken = accessToken,
RefreshToken = refreshToken,
ExpiresAt = expiresAt
};
}
}
}
+370
View File
@@ -0,0 +1,370 @@
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 {
/// <summary>
/// Retrieve Tokens From Headers
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
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<long> ();
//
if (accessToken
.ToNormalString ()
.Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
}
//
return new XLoginResponse {
AccessToken = accessToken,
RefreshToken = refreshToken,
ExpiresAt = expiresAt
};
}
/// <summary>
/// Retrieve Tokens From HttpContext
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static async Task<XLoginResponse> 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<long> ();
//
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;
}
/// <summary>
/// Retrieve Tokens From ActionExecutingContext
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static async Task<XLoginResponse> RetrieveTokens (this ActionExecutingContext source) {
//
var result = await source.HttpContext.RetrieveTokens ();
return result;
}
/// <summary>
/// Retrieve Tokens From XUserInfo instance
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XTokenResponse RetrieveTokens (this XUserClaimsInfoDto source) {
//
var result = new XLoginResponse {
AccessToken = source.AccessToken,
RefreshToken = source.RefreshToken,
ExpiresAt = source.ExpiresAt
};
//
return result;
}
/// <summary>
/// Retrieve Tokens From IHeader Dictionary
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
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<long> ();
//
var result = new XLoginResponse {
AccessToken = accessToken,
RefreshToken = refreshToken,
ExpiresAt = expiresAt
};
//
return result;
}
/// <summary>
/// Retrieve IXIdentityProvider from HttpContext
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static IXIdentityProvider GetXApiIdentityProvider (this FilterContext source) {
//
var services = source.HttpContext.RequestServices;
return (IXIdentityProvider) services
.GetService (typeof (IXIdentityProvider));
}
/// <summary>
/// Generate XLoginResponse instance based on TokenResponse
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific IHeaderDictionary instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
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);
}
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific IHeaderDictionary instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
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}");
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific HttpRequest instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (this HttpRequest source, XLoginResponse model) {
source.Headers.SetXAuthenticationTokens (model);
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific HttpRequest instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (this HttpRequestMessage source, XLoginResponse model) {
source.Headers.SetXAuthenticationTokens (model);
}
/// <summary>
/// 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
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (this HttpResponse source, XLoginResponse model, string secret) {
source.Headers.SetXAuthenticationTokens (model, secret);
}
/// <summary>
/// Determines a Token Can Refrsh or not
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Generate a Revision Checksum for new Tokens
/// </summary>
/// <param name="source"></param>
/// <param name="secret"></param>
/// <returns></returns>
public static string GetRevisionChecksum (this XLoginResponse source, string secret) {
return (source.AccessToken +
secret +
source.RefreshToken +
secret +
source.ExpiresAt.ToString ()
)
.ToMd5String ();
}
/// <summary>
/// Generate a Revision Checksum for new Tokens
/// </summary>
/// <param name="source"></param>
/// <param name="secret"></param>
/// <returns></returns>
public static string GetRevisionChecksum (this XTokenResponse source, string secret) {
return (source.AccessToken +
secret +
source.RefreshToken +
secret +
source.ExpiresAt.ToString ()
)
.ToMd5String ();
}
/// <summary>
/// Check an XLoginResponse instance is Valid with it's revision
/// </summary>
/// <param name="source"></param>
/// <param name="checksum"></param>
/// <param name="secret"></param>
/// <returns></returns>
public static bool ValidateRevisionChecksum (this XLoginResponse source, string checksum, string secret) {
//
var xChecksum = source.GetRevisionChecksum (secret);
return checksum == xChecksum;
}
/// <summary>
/// Check an XTokenResponse instance is Valid with it's revision
/// </summary>
/// <param name="source"></param>
/// <param name="checksum"></param>
/// <param name="secret"></param>
/// <returns></returns>
public static bool ValidateRevisionChecksum (this XTokenResponse source, string checksum, string secret) {
//
var xChecksum = source.GetRevisionChecksum (secret);
return checksum == xChecksum;
}
/// <summary>
/// Retrieve Exception Details if Fails
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static Exception GetException (this TokenResponse source) {
//
// Validate Args ...
if (source.IsNull () || !source.IsError) {
return XException.ActionFailed.ToException ();
}
//
XError error = source.ErrorDescription.FromJSON<XError> ();
return error.ToException ();
}
/// <summary>
/// Convert XTokenResponse to Header Dictionary
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static IDictionary<string, string> ToHeaderDictionary (this XTokenResponse source) {
//
var result = new Dictionary<string, string> { { XAuthorization.RefreshToken, source.RefreshToken },
{ XAuthorization.ExpiresAt, source.ExpiresAt.ToString () }
};
//
return result;
}
}
@@ -0,0 +1,55 @@
using xCommons.Extensions;
using xIdentityModels.Constants;
using xIdentityModels.Models;
namespace xIdentityService.Extensions {
public static class XUserClaimsInfoDtoExtensions {
public static string GetUserSelectByParam (
this XUserClaimsInfoDto source,
XUserSelectBy userSelectBy = XUserSelectBy.Username
) {
//
var result = "";
//
switch (userSelectBy) {
//
case XUserSelectBy.ID:
result = source.UserId;
break;
//
case XUserSelectBy.Username:
result = source.UserName;
break;
//
case XUserSelectBy.Email:
result = source.Email;
break;
//
case XUserSelectBy.MobileNumber:
result = source.PhoneNumber;
break;
}
//
if (result.IsNullOrEmpty ()) {
//
if (!source.UserId.IsNullOrEmpty ()) {
result = source.UserId;
} else if (!source.UserName.IsNullOrEmpty ()) {
result = source.UserName;
} else if (!source.Email.IsNullOrEmpty ()) {
result = source.Email;
} else if (!source.PhoneNumber.IsNullOrEmpty ()) {
result = source.PhoneNumber;
}
}
//
return result;
}
}
}