
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Configuration\XIdentityServiceConfiguration.cs

using xIdentityService.Constants;

namespace xIdentityService.Configuration {
    public partial class XIdentityServiceConfiguration {
        public string Authority { get; set; }
        public string ApiName { get; set; }
        public string ApiSecret { get; set; }
        public string ClientId { get; set; }
        public string ClientSecret { get; set; }
        public string XPoweredValue { get; set; }
        public XTokenType TokenType { get; set; }
        public string XRevisionSecretKey { get; set; }
        public int DefaultClientTimeout { get; set; } = 360;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Configuration\XProxyConfiguration.cs

using System.Collections.Generic;
using xModels.Base;

namespace xIdentityService.Configuration {
    /// <summary>
    /// XProxy Middleware Configuration ...
    /// </summary>
    public class XProxyConfiguration {
        /// <summary>
        /// Proxy Host Address for Clients Which Use XProxy Server ...
        /// </summary>
        /// <value></value>
        public string Host { get; set; }

        /// <summary>
        /// if EnableXPoweredByAthorization property setted to true, this property determines
        /// the header must be this value ...
        /// </summary>
        /// <value></value>
        public string XPoweredValue { get; set; }

        /// <summary>
        /// Determines Proxy Http Handler Check SSL or not ...
        /// </summary>
        /// <value></value>
        public bool DisableSSLCheck { get; set; }

        /// <summary>
        /// Determines Http Client Handler Allow Auto Redirect or not ...
        /// </summary>
        /// <value></value>
        public bool AllowAutoRedirect { get; set; }

        /// <summary>
        /// Determines Proxy Server Log Received Requests or not ...
        /// </summary>
        /// <value></value>
        public bool EnableLogging { get; set; }

        /// <summary>
        /// DefineRoutes for Handling ...
        /// </summary>
        /// <value></value>
        public HashSet<XProxyRouteDescriptor> Routes { get; set; }
    }

    /// <summary>
    /// Describe a Proxy Route ...
    /// </summary>
    public class XProxyRouteDescriptor : XBaseDescriptor {
        /// <summary>
        /// Determines which route can handled for Proxyfing ...
        /// </summary>
        /// <value></value>
        public string Route { get; set; }

        /// <summary>
        /// Determines Proxy Server Handle Athorization or not ...
        /// </summary>
        /// <value></value>
        public bool EnableAuthorization { get; set; }

        /// <summary>
        /// Determines Which Scopes allowed to this route if authorizations enabled ...
        /// </summary>
        /// <value></value>
        public HashSet<string> AllowedScopes { get; set; }

        /// <summary>
        /// Determines Which Roles allowed to this route if authorizations enabled ...
        /// </summary>
        /// <value></value>
        public HashSet<string> AllowedRoles { get; set; }

        /// <summary>
        /// Determines XProxy Can Check XPowered By Authorization or not ...
        /// </summary>
        /// <value></value>
        public bool EnableXPoweredByAthorization { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\ConfigurationNodeNames.cs

namespace xIdentityService.Constants {
    public partial struct ConfigurationNodeNames {
        public const string XPROXY_CONFIGURATION_NODE_NAME = "ProxyConfiguration";
        public const string IDENTITY_SERVICE_NODE_NAME = "IdentityServiceConfiguration";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\XApiAccountEndpoint.cs

using xExceptions.Attributes;

namespace xIdentityService.Constants
{
    public enum XApiAccountEndpoint
    {
        //
        #region Authentication ...
        [StringValue("Account/DiscoveryDocument")]
        DiscoveryDocument,

        [StringValue("Account/RequestScopeAccessToken")]
        RequestScopeAccessToken,

        [StringValue("Account/Authenticate")]
        Authenticate,

        [StringValue("Account/Login")]
        Login,

        [StringValue("Account/RefreshTokens")]
        RefreshTokens,

        [StringValue("Account/ChangePassword")]
        ChangePassword,

        [StringValue("Account/ResetPassword")]
        ResetPassword,
        #endregion

        //
        #region Proile ...
        [StringValue("Account/Profile/{ids}/GetNames")]
        GetNames,

        [StringValue("Account/Profile/GetNameIds")]
        GetNameIds,

        [StringValue("Account/Profile/{userSelectByParam}")]
        GetProfile,

        [StringValue("Account/Profile/Query")]
        QueryProfiles,

        [StringValue("Account/Profile/Avatars/Query/{userSelectByParam}")]
        QueryAvatars,

        [StringValue("Account/Profile/Update/{userSelectByParam}")]
        UpdateProfile,

        [StringValue("Account/Profile/{userSelectByParam}")]
        FullUpdateProfile,

        [StringValue("Account/Profile/Avatar")]
        AddAvatar,

        [StringValue("Account/Profile/Avatars")]
        AddAvatars,

        [StringValue("Account/Profile/Avatars/{ids}")]
        RemoveAvatars,

        [StringValue("Account/Profile/Avatars/{id}/Set")]
        SetAvatar,
        #endregion

        //
        #region Search ...
        [StringValue("Account/OpenToSearch/Query")]
        QueryOpenToSearchProfiles,
        #endregion

        //
        #region Registration ...
        [StringValue("Account/CanRegisterUserName/{userName}")]
        CanRegisterUserName,

        [StringValue("Account/CanRegisterMobileNumber/{mobileNumber}")]
        CanRegisterMobileNumber,

        [StringValue("Account/CanRegisterEmail/{email}")]
        CanRegisterEmail,

        [StringValue("Account/IsConfirmedEmail")]
        IsConfirmedEmail,

        [StringValue("Account/IsConfirmedMobile")]
        IsConfirmedMobile,

        [StringValue("Account/ConfirmRegistration")]
        ConfirmRegistration,

        [StringValue("Account/ConfirmMobileNumber")]
        ConfirmMobileNumber,

        [StringValue("Account/ConfirmEmailAddress")]
        ConfirmEmailAddress,

        [StringValue("Account/RequestConfirmMobile")]
        RequestConfirmMobile,

        [StringValue("Account/RequestConfirmEmail")]
        RequestConfirmEmail,

        [StringValue("Account/RequestResetPassword")]
        RequestResetPassword,

        [StringValue("Account/RequestConfirmRegistration")]
        RequestConfirmRegistration,

        [StringValue("Account/InviteUser")]
        InviteUser,

        [StringValue("Account/RequestRegistration")]
        RequestRegistration,

        [StringValue("Account/AddAccountInfo")]
        AddAccountInfo,

        [StringValue("Account/AttachProfileImage")]
        AttachProfileImage,

        [StringValue("Account/FinishRegistration")]
        FinishRegistration,
        #endregion

        //
        #region Friendship ...
        [StringValue("Account/Friendship/{destUser}/Follow")]
        Follow,

        [StringValue("Account/Friendship/{destUser}/Cancel")]
        Cancel,

        [StringValue("Account/Friendship/{destUser}/UnFollowFollower")]
        UnFollowFollower,

        [StringValue("Account/Friendship/{destUser}/UnFollowFollowing")]
        UnFollowFollowing,

        [StringValue("Account/Friendship/{destUser}/Block")]
        Block,

        [StringValue("Account/Friendship/{destUser}/UnBlock")]
        UnBlock,

        [StringValue("Account/Friendship/{destUser}/AcceptRequest")]
        AcceptRequest,

        [StringValue("Account/Friendship/{destUser}/RejectRequest")]
        RejectRequest,

        [StringValue("Account/Friendship/{destUser}/FriendshipInfo")]
        FriendshipInfo,

        [StringValue("Account/Friendship/{destUser}/IsFollower")]
        IsFollower,

        [StringValue("Account/Friendship/{destUser}/FollowerState")]
        FollowerState,

        [StringValue("Account/Friendship/{destUser}/Follower")]
        Follower,

        [StringValue("Account/Friendship/Followers")]
        Followers,

        [StringValue("Account/Friendship/AllFollowers")]
        AllFollowers,

        [StringValue("Account/Friendship/FollowersList")]
        FollowersList,

        [StringValue("Account/Friendship/QueryFollowers")]
        QueryFollowers,

        [StringValue("Account/Friendship/{destUser}/IsFollowing")]
        IsFollowing,

        [StringValue("Account/Friendship/{destUser}/FollowingState")]
        FollowingState,

        [StringValue("Account/Friendship/{destUser}/Following")]
        Following,

        [StringValue("Account/Friendship/Followings")]
        Followings,

        [StringValue("Account/Friendship/AllFollowings")]
        AllFollowings,

        [StringValue("Account/Friendship/FollowingsList")]
        FollowingsList,

        [StringValue("Account/Friendship/QueryFollowings")]
        QueryFollowings,
        #endregion

        //
        #region Admin ...
        [StringValue("Account/Ban")]
        Ban,

        [StringValue("Account/UnBan")]
        UnBan,

        [StringValue("Account/IsBanned/{userSelectByParam}")]
        IsBanned,
        #endregion

        //
        #region Open Actions ...
        [StringValue("Account/Open")]
        Open,
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\XAuthenticationScheme.cs

using xExceptions.Attributes;

namespace xIdentityService.Constants {
    public enum XAuthenticationScheme {
        [StringValue ("token")]
        XToken, 
        [StringValue ("introspection")]
        XIntrospection,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\XHeader.cs

using xExceptions.Attributes;

namespace xIdentityService.Constants
{
    /// <summary>
    /// All Available Headers ...
    /// </summary>
    public enum XHeader
    {
        /// <summary>
        /// Hub Connection ID Header Keys ...
        /// </summary>
        [StringValue("requestID")]
        ConnectionId,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\XParam.cs

using xExceptions.Attributes;

namespace xIdentityService.Constants {
    public enum XParam {
        [StringValue ("Content-Type")]
        XContentType,

        [StringValue ("{boundary}")]
        XBoundary,

        [StringValue ("{userSelectByParam}")]
        XUserSelectByParam,

        [StringValue ("{destUser}")]
        XDestUser,

        [StringValue ("{id}")]
        XId,

        [StringValue ("{ids}")]
        XIds,

        [StringValue ("Origin")]
        XOrigin,

        [StringValue ("{userName}")]
        XUserName,

        [StringValue ("{mobileNumber}")]
        XMobileNumber,

        [StringValue ("{email}")]
        XEmail,

        [StringValue ("role")]
        XRole,

        [StringValue ("forceRole")]
        XForceRole,

        [StringValue ("IsRefreshed")]
        XIsRefreshed,

        [StringValue ("file")]
        XFile,

        [StringValue ("files")]
        XFiles,

        [StringValue ("actionToken")]
        XActionToken,

        [StringValue ("request")]
        XRequest,

        [StringValue ("scope")]
        XScope,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\XProxyConstants.cs

namespace xIdentityService.Constants {
    public struct XProxyConstants {
        public const string XPROXY_HTTP_CLIENT = "XProxyHttpClient";
        public const string XPROXY_FORWARD_HEADER = "xForwardHeader";
        public const string XPROXY_ACCEPTED_HEADERS = "xAcceptedHeaders";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\XResponseContentTypes.cs

namespace xIdentityService.Constants {
    public struct XResponseContentTypes {
        public const string HTML = "text/html";
        public const string JSON = "application/json";
        public const string JavaScript = "text/javascript";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\XTokenType.cs

namespace xIdentityService.Constants {
    public enum XTokenType {
        //
        // Summary:
        //     Self-contained Json Web Token
        Jwt,
        //
        // Summary:
        //     Reference token
        Reference
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Controllers\XBaseIdentityApiController.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Attributes;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;

namespace xIdentityService.Controllers
{
    /// <summary>
    /// Base Identity Api Controller 
    /// </summary>
    [ApiController]
    [RequireXPowered(true)]
    [Route("api/[controller]")]
    [Produces("application/json")]
    public abstract class XBaseIdentityApiController : XBaseIdentityController
    {
        protected XBaseIdentityApiController(
            ILogger logger, 
            XAppConfiguration appConfiguration, 
            IXIdentityProvider identityProvider, 
            XValidationProvider validationProvider
        ) : base(
            logger, 
            appConfiguration, 
            identityProvider, 
            validationProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Controllers\XBaseIdentityApiV1Controller.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Attributes;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;

namespace xIdentityService.Controllers
{
    /// <summary>
    /// Base Identity Api V1 Controller 
    /// </summary>
    [ApiController]
    [ApiVersion("1.0")]
    [RequireXPowered(true)]
    [Route("api/v{version:apiVersion}/[controller]")]
    public abstract class XBaseIdentityApiV1Controller : XBaseIdentityApiController
    {
        protected XBaseIdentityApiV1Controller(
            ILogger logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Controllers\XBaseIdentityController.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Constants;
using xCommons.Controllers;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Models;
using xIdentityService.Constants;
using xIdentityService.Interfaces;

namespace xIdentityService.Controllers
{
    public abstract class XBaseIdentityController : XBaseController
    {
        //
        public IXIdentityProvider IdentityProvider { get; }

        protected XBaseIdentityController(
            ILogger logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider
        ) : base(
            logger,
            appConfiguration,
            validationProvider
        )
        {
            IdentityProvider = identityProvider;
        }

        //
        #region NonActions ...
        /// <summary>
        /// Retrieve Connection ID for Hubs ...
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public string GetConnectionId()
        {
            //
            var result = "";

            //
            var headerKey = XHeader.ConnectionId.GetStringValue();

            //
            // Check if Connection ID is Provided ...
            if (Request.Headers.ContainsKey(headerKey))
            {
                result = Request.Headers[headerKey];
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve User Identifier Base on XActionRequest
        /// </summary>
        /// <param name="model"></param>
        /// <param name="forceNotNull"></param>
        /// <param name="excludes"></param>
        /// <returns></returns>
        [NonAction]
        public string GetUserSelectByParam(
            XActionRequest model,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(model);

            //
            var result = IdentityProvider.GetUserSelectByParam(
                model,
                forceNotNull,
                excludes
            );

            //
            return result;
        }

        /// <summary>
        /// Retrieve Access Token
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<string> GetAccessToken()
        {
            //
            var accessToken = Request.Headers[XAuthorization.Header].ToString();
            if (accessToken.IsNullOrEmpty())
            {
                //
                accessToken = await HttpContext
                    .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>
        [NonAction]
        public async Task<string> GetRefreshToken()
        {
            //
            var refreshToken = Request.Headers[XAuthorization.RefreshToken].ToString();
            if (refreshToken.IsNullOrEmpty())
            {
                //
                refreshToken = await HttpContext
                    .GetTokenAsync(XAuthorization.RefreshToken);
            }

            //
            return refreshToken;
        }

        /// <summary>
        /// Retrieve Access Token Expiration Date
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<long> GetTokenExpiresAt()
        {
            //
            var expiresAtStr = Request.Headers[XAuthorization.ExpiresAt].ToString();
            if (expiresAtStr.IsNullOrEmpty())
            {
                //
                expiresAtStr = await HttpContext
                    .GetTokenAsync(XAuthorization.ExpiresAt);
            }

            //
            var expiresAt = expiresAtStr.ConvertTo<long>();

            //
            return expiresAt;
        }

        /// <summary>
        /// Retrieve All Required Tokens
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<XLoginResponse> RetrieveTokensAsXLoginResponse()
        {
            //
            var accessToken = await GetAccessToken();
            var refreshToken = await GetRefreshToken();
            var expiresAt = await GetTokenExpiresAt();

            //
            return new XLoginResponse
            {
                AccessToken = accessToken,
                RefreshToken = refreshToken,
                ExpiresAt = expiresAt
            };
        }

        /// <summary>
        /// Retrieve All Required Tokens
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<XTokenResponse> RetrieveTokensAsXTokenResponse()
        {
            //
            var accessToken = await GetAccessToken();
            var refreshToken = await GetRefreshToken();
            var expiresAt = await GetTokenExpiresAt();

            //
            return new XTokenResponse
            {
                AccessToken = accessToken,
                RefreshToken = refreshToken,
                ExpiresAt = expiresAt
            };
        }

        /// <summary>
        /// Retrive UserInfo
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<XUserClaimsInfoDto> GetUserInfo()
        {
            //
            var claims = User.Claims ?? null;
            if (!claims.HasChild())
            {
                return null;
            }

            var xTokens = await RetrieveTokensAsXTokenResponse();
            var result = new XUserClaimsInfoDto(
                xTokens.AccessToken,
                xTokens.RefreshToken,
                xTokens.ExpiresAt,
                User.Claims
            );

            //
            return result;
        }

        /// <summary>
        /// Validate User Authenticated and Retrieve User Info
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<XUserClaimsInfoDto> ValidateAndGetUserInfo()
        {
            //
            if (!User.Identity.IsAuthenticated)
            {
                XException.NotAuthorized.Throw();
            }

            //
            var result = await GetUserInfo();
            if (result.IsNull())
            {
                XException.NotAuthorized.Throw();
            }

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\DI\XDIHelperExtension.cs

using System;
using IdentityModel.AspNetCore.OAuth2Introspection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Authorization;
using xCommons.Extensions;
using xIdentityService.Configuration;
using xIdentityService.Constants;
using xIdentityService.Interfaces;
using xIdentityService.Providers;
using xIdentityService.Security;

namespace xIdentityService.DI {
    public static partial class XDIHelperExtension {
        /// <summary>
        /// Extract Module Configuration Structure from IConfiguration interface 
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        public static XIdentityServiceConfiguration GetXIdentityServiceConfiguration (this IConfiguration config) {
            //
            var xIdentityServiceConfigSection = config.GetSection (ConfigurationNodeNames.IDENTITY_SERVICE_NODE_NAME);
            return xIdentityServiceConfigSection.Get<XIdentityServiceConfiguration> ();
        }

        /// <summary>
        /// Register Service and All it's Requirements
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXIdentityService (
            this IServiceCollection services,
            IConfiguration configuration,
            ServiceLifetime lifeTime = ServiceLifetime.Singleton
        ) {
            //
            var identityConfiguration = configuration.GetXIdentityServiceConfiguration ();
            AddIdentityService (
                services,
                identityConfiguration,
                lifeTime
            );
        }

        /// <summary>
        /// Register Service and All it's Requirements
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXIdentityService (
            this IServiceCollection services,
            XIdentityServiceConfiguration configuration,
            ServiceLifetime lifeTime = ServiceLifetime.Singleton
        ) {
            AddIdentityService (services, configuration, lifeTime);
        }

        /// <summary>
        /// Register Custome Token Provider
        /// </summary>
        /// <param name="services"></param>
        /// <typeparam name="T"></typeparam>
        public static void AddXTokenProvider<T> (
            this IServiceCollection services,
            ServiceLifetime lifetime = ServiceLifetime.Singleton)
        where T : IXTokenProvider {
            //
            Console.WriteLine ("IdentityService: Add Custom Token Provider ...");
            services.Add (new ServiceDescriptor (typeof (IXTokenProvider), typeof (T), lifetime));
        }

        /// <summary>
        /// Use Authentication
        /// </summary>
        /// <param name="app"></param>
        public static void UseXIdentityService (this IApplicationBuilder app) {
            app.UseAuthentication ();
        }

        //
        #region Private ...
        private static void AddIdentityService (
            this IServiceCollection services,
            XIdentityServiceConfiguration config,
            ServiceLifetime lifeTime = ServiceLifetime.Singleton
        ) {
            //
            services.AddSingleton<XIdentityServiceConfiguration> (config);

            //
            var builder = services
                .AddAuthentication (XAuthenticationScheme.XToken.GetStringValue ());

            //
            // Add JWT Handler ...
            builder.AddJwtBearer (
                XAuthenticationScheme.XToken.GetStringValue (), options => {
                    //
                    options.Authority = config.Authority;
                    options.TokenValidationParameters.ValidateAudience = false;
                    options.TokenValidationParameters.ValidTypes = new [] { "at+jwt" };

                    //
                    options.ForwardDefaultSelector = context => {
                        //
                        var path = context.Request.Path.Value;

                        //
                        var fromHeader = TokenRetrieval.FromAuthorizationHeader ();
                        var fromQuery = TokenRetrieval.FromQueryString ();
                        var bearerToken = fromHeader (context.Request) ?? fromQuery (context.Request);

                        //
                        var result = XAuthenticationScheme.XToken.GetStringValue ();
                        if (!bearerToken.IsNull () && !bearerToken.Contains (".")) {
                            result = XAuthenticationScheme.XIntrospection.GetStringValue ();
                        }

                        //
                        return result;
                    };
                });

            //
            // Add OAuthIntrospect ...
            builder.AddOAuth2Introspection (
                XAuthenticationScheme.XIntrospection.GetStringValue (), options => {
                    //
                    options.Authority = config.Authority;
                    options.ClientId = config.ApiName;
                    options.ClientSecret = config.ClientSecret;

                    //
                    options.TokenRetriever = new Func<HttpRequest, string> (req => {
                        //
                        var fromHeader = TokenRetrieval.FromAuthorizationHeader ();
                        var fromQuery = TokenRetrieval.FromQueryString ();

                        //
                        var bearerToken = fromHeader (req) ?? fromQuery (req);

                        //
                        return bearerToken;
                    });
                });

            //
            // Register Authorization Handler ...
            services.AddSingleton<IAuthorizationHandler, RequiredRolesHandler> ();
            Console.WriteLine ("IdentityService: register Authorization Handlers  ...");

            //
            // Register Identity Provider ...
            services.Add (new ServiceDescriptor (typeof (IXIdentityProvider), typeof (XIdentityProvider), lifeTime));
            Console.WriteLine ("IdentityService: Register IdentityProvider ...");

            //
            // Try To Register InMemoryTokenProvier if it's not Provided ...
            IXTokenProvider xTokenProvider = null;
            try {
                xTokenProvider = services.GetRegisteredService<IXTokenProvider> ();
            } catch { }
            if (xTokenProvider.IsNull ()) {
                //
                Console.WriteLine ("IdentityService: there is no Custom Token Provider, Adding InMemoryTokenProvider instead ...");
                services.Add (new ServiceDescriptor (typeof (IXTokenProvider), typeof (XInMemoryTokenProvider), lifeTime));
            }

            //
            // Adding Security Provider ...
            services.Add (new ServiceDescriptor (typeof (IXSecurityProvider), typeof (XSecurityProvider), lifeTime));
            Console.WriteLine ("IdentityService: Register Security Provider ...");
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Extensions\AuthorizationPolicyBuilderExtensions.cs

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 ();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Extensions\HttpContextExtensions.cs

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
            };
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Extensions\StreamExtensions.cs

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using xCommons.Extensions;

namespace xIdentityService.Extensions
{
    public static partial class StreamExtensions
    {
        /// <summary>
        /// Converts an Stream to Async Enumerable ...
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="bufferSize"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async IAsyncEnumerable<byte[]> ToAsyncEnumerable(
            this Stream stream,
            int bufferSize = 8192,
            [System.Runtime.CompilerServices.EnumeratorCancellation]
            CancellationToken cancellationToken = default
        )
        {
            //
            var buffer = new byte[bufferSize];
            while (true)
            {
                //
                int read = await stream
                    .ReadAsync(
                        buffer,
                        0,
                        buffer.Length,
                        cancellationToken
                );

                //
                if (read == 0)
                {
                    yield break;
                }

                //
                yield return buffer.Take(read).ToArray();
            }
        }

        /// <summary>
        /// Converts an Stream to Async Enumerable ...
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="bufferSize"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async IAsyncEnumerable<T> ToAsyncEnumerable<T>(
            this Stream stream,
            int bufferSize = 8192,
            [System.Runtime.CompilerServices.EnumeratorCancellation]
            CancellationToken cancellationToken = default
        )
        {
            //
            var buffer = new byte[bufferSize];
            while (true)
            {
                //
                int read = await stream
                    .ReadAsync(
                        buffer,
                        0,
                        buffer.Length,
                        cancellationToken
                );
                if (read == 0)
                {
                    yield break;
                }

                //
                T chunk = default(T);
                var readedBuffer = buffer.Take(read).ToArray();
                var str = readedBuffer.FromBytes();
                if (str.IsNullOrEmpty())
                {
                    yield return chunk;
                }
                try
                {
                    chunk = str.FromJSON<T>();
                }
                catch
                { }

                //
                yield return chunk;
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Extensions\XModelExtensions.cs

using xIdentityModels.Dtos;
using xModels.Dtos;

namespace xIdentityService.Extensions
{
    public static class XModelExtensions
    {
        public static XPersonDto ToXPersonDto(this XOpenActionUserInfoDto source)
        {
            //
            var result = new XPersonDto
            {
                Avatar = source.Avatar,
                Lastname = source.Lastname,
                Username = source.Username,
                Firstname = source.Firstname,
            };

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Extensions\XTokenExtensions.cs

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;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Extensions\XUserClaimsInfoDtoExtensions.cs

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;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXBaseIdentityHttpProvider.cs

using System;
using System.IO;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using RestSharp;
using xCommons.Providers;
using xHttpService.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Models;
using xIdentityService.Models;

namespace xIdentityService.Interfaces
{
    /// <summary>
    /// an interface for Identity Provided Http Based Services ...
    /// </summary>
    public interface IXBaseIdentityHttpProvider
    {
        /// <summary>
        /// Client Base Url ...
        /// </summary>
        /// <value></value>
        string BaseUrl { get; }

        /// <summary>
        /// Logger ...
        /// </summary>
        /// <value></value>
        ILogger Logger { get; }

        /// <summary>
        /// Powered Value ...
        /// </summary>
        /// <value></value>
        string XPoweredValue { get; }

        /// <summary>
        /// Default Client Timeout ...
        /// </summary>
        /// <value></value>
        int DefaultClientTimeout { get; }

        /// <summary>
        /// Default Buffering Chunk Size ...
        /// </summary>
        /// <value></value>
        int DefaultBufferingChunckSize { get; }

        /// <summary>
        /// Validation Provider ...
        /// </summary>
        /// <value></value>
        XValidationProvider ValidationProvider { get; }

        /// <summary>
        /// Get an Instance of Http Client 
        /// </summary>
        /// <returns></returns>
        HttpClient GetHttpClient(XTokenResponse tokens = null);
        HttpClient GetHttpClient(XUserClaimsInfoDto userInfo = null);

        /// <summary>
        /// Get an Instance of RestClient
        /// </summary>
        /// <returns></returns>
        RestClient GetRestClient(XTokenResponse tokens = null);
        RestClient GetRestClient(XUserClaimsInfoDto userInfo = null);

        /// <summary>
        /// Get an Instance of RestRequest 
        /// </summary>
        /// <param name="endpoint"></param>
        /// <param name="addXPoweredValue"></param>
        /// <param name=""></param>
        /// <param name="headers"></param>
        /// <param name="queryStrings"></param>
        /// <returns></returns>
        RestRequest GetRestRequet(
            Enum endpoint,
            bool addXPoweredValue = true,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> headers = null,
            IDictionary<string, string> queryStrings = null
        );

        /// <summary>
        /// Handle Call Specific Request and retrieve Response
        /// </summary>
        /// <param name="client"></param>
        /// <param name="request"></param>
        /// <param name="method"></param>
        /// <param name="supportRefreshingTokens"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        Task<T> RunRestRequest<T>(
            RestClient client,
            RestRequest request,
            XHttpMethod method,
            bool supportRefreshingTokens = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Access a Get Request Stream as AsyncEnumerable ... 
        /// </summary>
        /// <param name="endpoint"></param>
        /// <param name="bufferLength"></param>
        /// <param name="addXPoweredValue"></param>
        /// <param name="tokens"></param>
        /// <param name="@params"></param>
        /// <param name="headers"></param>
        /// <param name="queryStrings"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        Task<Stream> StreamData(
            Enum endpoint,
            int bufferLength = 8194,
            bool addXPoweredValue = true,
            XTokenResponse tokens = null,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> headers = null,
            IDictionary<string, string> queryStrings = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Handle Call Specified Request and Retrieve XBaseRestResponse<T> ...
        /// </summary>
        /// <param name="client"></param>
        /// <param name="request"></param>
        /// <param name="method"></param>
        /// <param name="supportRefreshingTokens"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns>an instance of XBaseRestResponse<T></returns>
        Task<XBaseRestResponse<T>> RunRestRequestByResponse<T>(
            RestClient client,
            RestRequest request,
            XHttpMethod method,
            bool supportRefreshingTokens = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get User SelectBy Param 
        /// </summary>
        /// <param name="model"></param>
        /// <param name="forceNotNull"></param>
        /// <param name="excludes"></param>
        /// <returns></returns>
        string GetUserSelectByParam(
            XActionRequest model,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        );

        /// <summary>
        /// Converts UserInfo to TokenResponse model ...
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        XTokenResponse ToTokenResponse(XUserClaimsInfoDto userInfo = null);

        /// <summary>
        /// Prepare Url Address of Specified Enum by Filling Params
        /// and Query Strings Attach ...
        /// </summary>
        /// <param name="endpoint"></param>
        /// <param name="attachBaseUrl"></param>
        /// <param name="@params"></param>
        /// <param name="queryStrings"></param>
        /// <returns></returns>
        string PrepareUrl(
            Enum endpoint,
            bool attachBaseUrl = false,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> queryStrings = null
        );

        /// <summary>
        /// Prepare Url Address by Filling Params
        /// and Query Strings Attach ...
        /// </summary>
        /// <param name="url"></param>
        /// <param name="attachBaseUrl"></param>
        /// <param name="@params"></param>
        /// <param name="queryStrings"></param>
        /// <returns></returns>
        string PrepareUrl(
            string url,
            bool attachBaseUrl = false,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> queryStrings = null
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXBaseReferenced.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xDataService.Models;
using xIdentityModels.Models;
using xModels.Base;

namespace xIdentityService.Interfaces
{
    /// <summary>
    /// a Referenced Service is a Service which can Referenced to other Items ...
    /// </summary>
    public interface IXBaseReferenced<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        /// <summary>
        /// Get Reference Identifier for Specified Provider and Specified Item ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <returns></returns>
        string GetIdentifier<TReferenceKey>(
            string providedFor,
            TReferenceKey forProvidedId
        );

        /// <summary>
        /// Check Specified Item has Refernce to Provider ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> IsProvidedFor<TReferenceKey>(
            string providedFor,
            TReferenceKey forProvidedId,
            TKey id,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Specified Reference to Specified Item ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="id"></param>
        /// <param name="forIndex"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task AddReference<TReferenceKey>(
            string providedFor,
            TReferenceKey forProvidedId,
            TKey id,
            int forIndex = 0,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Specified Reference from Specified Item ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="id"></param>
        /// <param name="forIndex"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task RemoveReference<TReferenceKey>(
            string providedFor,
            TReferenceKey forProvidedId,
            TKey id,
            int forIndex = 0,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get Specified References ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="TReferenceKey"></typeparam>
        /// <returns></returns>
        Task<IEnumerable<XReference<string>>> GetReferences(
            string providedFor,
            TKey id,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXBaseReferencedController.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using xDataService.Models;
using xModels.Base;

namespace xIdentityService.Interfaces
{
    public interface IXBaseReferencedController<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        /// <summary>
        /// Check an Item Has Reference to Specified ProvideFor and Specified forProvidedId ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/Reference/IsProvidedFor")]
        Task<ActionResult<bool>> IsProvidedFor(
            [FromRoute] TKey id,
            [FromQuery] string providedFor,
            [FromQuery] object forProvidedId,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add a Reference to Item for Specified ProvideFor and Specified forProvidedId ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="forIndex"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/Reference")]
        Task<ActionResult> AddReference(
            [FromRoute] TKey id,
            [FromQuery] string providedFor,
            [FromQuery] object forProvidedId,
            [FromQuery] int forIndex = 0,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove a Reference from Item for Specified ProvideFor and Specified forProvidedId ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="forIndex"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("{id}/Reference")]
        Task<ActionResult> RemoveReference(
            [FromRoute] TKey id,
            [FromQuery] string providedFor,
            [FromQuery] object forProvidedId,
            [FromQuery] int forIndex = 0,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve References of Specified Itemfor providedFor ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="providedFor"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/References")]
        Task<ActionResult<IEnumerable<XReference<string>>>> GetReferences(
            [FromRoute] TKey id,
            [FromQuery] string providedFor,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXIdentityBaseReferencedProvider.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using xDataService.Models;
using xIdentityModels.Models;
using xModels.Dtos;

namespace xIdentityService.Interfaces
{
    /// <summary>
    /// in Some Cases we have Entities Which Can Referenced for Specified 
    /// Provider and Types ...
    /// this interface Globaly introduce all available Actions for those ...
    /// 
    /// TKey: type of Provider Models Keys ...
    /// TModel: type of Dto which Referenced ...
    /// </summary>
    public interface IXIdentityBaseReferencedProvider<TModel, TKey>
    {
        //
        #region Props ...
        /// <summary>
        /// Provider Identifier ...
        /// </summary>
        string Provider { get; }
        #endregion

        //
        #region Referenced Actions ...
        /// <summary>
        /// Get Specified Indexed Reference for Specific Provided ID ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="forIndex"></param>
        /// <returns></returns>
        Task<TModel> GetReference(
            TKey providedForId,
            int forIndex = 0
        );

        /// <summary>
        /// Retrieve all Exists References of Specific Provided ID ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <returns></returns>
        Task<IEnumerable<TModel>> GetAllReferences(TKey providedForId);

        /// <summary>
        /// Extract all Referencing Models for Specified Key ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <returns></returns> 
        Task<IEnumerable<XReference<TKey>>> GetAllReferencings(TKey providedForId);

        /// <summary>
        /// Count References ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <returns></returns>
        Task<int> CountReferences(TKey providedForId);

        /// <summary>
        /// Retrieve References of Specific Provided ID as Query ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <returns></returns>
        Task<XQueryResult<TModel>> QueryReferences(
            XQuery query,
            TKey providedForId
        );

        /// <summary>
        /// Add Reference a Model to Specific Provided ID ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        Task<bool> AddReference(
            TModel model,
            TKey providedForId,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null
        );

        /// <summary>
        /// Add Reference a Model to Specific XRefence<TKey> ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        Task<bool> AddReference(
            TModel model,
            XReference<TKey> reference,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null
        );

        /// <summary>
        /// Remove Reference a Model for Specific Provided ID ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        Task<bool> RemoveReference(
            TModel model,
            TKey providedForId,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null
        );

        /// <summary>
        /// Remove Reference a Model for Specific XRefence<TKey> ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        Task<bool> RemoveReference(
            TModel model,
            XReference<TKey> reference,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null
        );

        /// <summary>
        /// Remove All References to Specified Key ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        Task<bool> RemoveReferences(
            TKey providedForId,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null
        );
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXIdentityProvider.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Http;
using RestSharp;
using xHttpService.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
using xModels.Dtos;

namespace xIdentityService.Interfaces
{
    public partial interface IXIdentityProvider
    {
        //
        string BaseUrl { get; }
        string RevisionSecretKey { get; }
        IXSecurityProvider SecurityProvider { get; }

        //
        #region Tools ...
        string GetUserSelectByParam(
            XActionRequest model,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        );
        #endregion

        //
        #region Tools ...
        Task<T> RunRestRequest<T>(
            RestClient client,
            RestRequest request,
            XHttpMethod method,
            bool supportRefreshingTokens = false
        );
        #endregion

        //
        #region Authentication ...
        Task<DiscoveryDocumentResponse> RequestDiscoveryDocument();
        Task<XTokenResponse> RequestScopeAccessToken(string scope);
        Task<TokenIntrospectionResponse> Introspection(XTokenResponse model);
        Task<XLoginResponse> Login(XLoginRequest model);
        Task Logout(XTokenResponse model);
        Task<XTokenResponse> Authenticate(XLoginRequest model);
        Task<XTokenResponse> RefreshTokens(XTokenResponse model);

        Task ChangePassword(
            XTokenResponse tokens,
            XActionRequest model
        );
        #endregion

        //
        #region Profile ...
        Task<IEnumerable<string>> GetUserNames(
            XTokenResponse tokens,
            string userIds
        );

        Task<IEnumerable<XUserNameIdResponse>> GetUserNameIds(
            XTokenResponse tokens,
            XUserNameIdRequest model
        );

        Task<XUserProfileDto> GetUserProfile(
            XTokenResponse tokens,
            string userSelectByParam
        );

        Task<XQueryResult<XUserProfileDto>> QueryUsers(
            XTokenResponse tokens,
            XQuery query
        );

        Task<XQueryResult<XUserProfileDto>> QueryInRoleUsers(
            XTokenResponse tokens,
            string role,
            XQuery query,
            bool forceRole = false
        );

        Task<XQueryResult<XProfileImage>> QueryAvatars(
            XTokenResponse tokens,
            string userSelectByParam,
            XQuery query
        );

        Task<XUserProfileDto> ProfileUpdateAsync(
            XTokenResponse tokens,
            string userSelectByParam,
            XProfileUpdateRequest model
        );

        Task<XUserProfileDto> FullProfileUpdateAsync(
            XTokenResponse tokens,
            string userSelectByParam,
            XProfileUpdateRequest request
        );

        Task<XUserProfileDto> AddAvatar(
            XTokenResponse tokens,
            IFormFile file
        );

        Task<XUserProfileDto> AddAvatars(
            XTokenResponse tokens,
            IFormFileCollection files
        );

        Task<XUserProfileDto> SetAvatar(
            XTokenResponse tokens,
            int avatarId
        );

        Task<XUserProfileDto> RemoveAvatars(
            XTokenResponse tokens,
            string avatarIds
        );
        #endregion

        //
        #region Search ...
        /// <summary>
        /// Query Open To Search User Profiles ...
        /// </summary>
        /// <param name="tokens">requested user's identifiers</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        Task<XQueryResult<XUserProfileDto>> QueryOpenToSearchUsers(
            XTokenResponse tokens,
            XQuery query
        );
        #endregion

        //
        #region Registration ...
        Task<bool> CanRegister(string userSelectByParam);

        Task<XActionResponse> InviteUser(
            XTokenResponse tokens,
            XActionRequest model
        );

        Task<XActionResponse> RequestRegistration(
            XActionRequest model
        );

        Task<XActionResponse> AddAccountInfo(
            XActionRequest model
        );

        Task<XActionResponse> AttachProfileImage(
            string actionToken,
            IFormFile file
        );

        Task FinishRegistration(XActionRequest model);

        Task<bool> IsConfirmedEmail(
            XTokenResponse tokens,
            string userSelectByParam
        );

        Task<bool> IsConfirmedMobile(
            XTokenResponse tokens,
            string userSelectByParam
        );

        Task RequestConfirmRegistration(XActionRequest model);

        Task ConfirmRegistration(
            XActionRequest model
        );

        Task<XActionResponse> RequestConfirmMobile(XActionRequest model);

        Task<XActionResponse> ConfirmMobileNumber(XActionRequest model);

        Task<XActionResponse> RequestConfirmEmail(XActionRequest model);

        Task<XActionResponse> ConfirmEmailAddress(XActionRequest model);

        Task<XActionResponse> RequestResetPassword(XActionRequest model);

        Task ResetPassword(XActionRequest model);
        #endregion

        //
        #region Friendship ...
        Task<XFriendshipFollowing> Follow(
            XTokenResponse tokens,
            string destUser
        );

        Task<bool> Cancel(
            XTokenResponse tokens,
            string destUser
        );

        Task UnFollowFollower(
            XTokenResponse tokens,
            string destUser
        );

        Task UnFollowFollowing(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipFollowing> Block(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipFollowing> UnBlock(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipFollower> AcceptRequest(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipFollower> RejectRequest(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipInfoDto> GetFriendshipInfo(
            XTokenResponse tokens,
            string destUser
        );

        Task<bool> IsFollower(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipFollower> GetFollower(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipState> GetFollowerState(
            XTokenResponse tokens,
            string destUser
        );

        Task<IEnumerable<XFriendshipFollower>> GetFollowers(XTokenResponse tokens);

        Task<IEnumerable<XFriendshipFollower>> GetAllFollowers(XTokenResponse tokens);

        Task<IEnumerable<string>> GetFollowingList(XTokenResponse tokens);

        Task<XQueryResult<XFriendDto>> QueryFollowers(
            XQuery query,
            string destUser,
            XTokenResponse tokens
        );

        Task<bool> IsFollowing(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipFollowing> GetFollowing(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipState> GetFollowingState(
            XTokenResponse tokens,
            string destUser
        );

        Task<IEnumerable<XFriendshipFollowing>> GetFollowings(XTokenResponse tokens);

        Task<IEnumerable<XFriendshipFollowing>> GetAllFollowings(XTokenResponse tokens);

        Task<IEnumerable<string>> GetFollowersList(XTokenResponse tokens);

        Task<XQueryResult<XFriendDto>> QueryFollowings(
            XQuery query,
            string destUser,
            XTokenResponse tokens
        );
        #endregion

        //
        #region Admin ...
        Task<IEnumerable<string>> Ban(
            XTokenResponse tokens,
            XUserNameIdRequest model
        );

        Task<IEnumerable<string>> UnBan(
            XTokenResponse tokens,
            XUserNameIdRequest model
        );

        Task<bool> IsBanned(
            XTokenResponse tokens,
            string userSelectByParam
        );
        #endregion

        //
        #region Open Actions ...
        //
        XDeviceDto GetDevice();
        
        //
        Task<XOpenActionInnerDto> OpenGet(
            XOpenActionInnerDto model
        );

        //
        Task<XOpenActionUserInfoDto> GetUserInfo(
            XDeviceDto device,
            string userSelectByParam
        );
        Task<XOpenActionUserInfoDto> GetUserInfo(
            XOpenActionInnerDto dto
        );
        Task<XOpenActionUserInfoDto> GetUserInfo(
            string token,
            string request
        );

        //
        Task<IEnumerable<XOpenActionUserInfoDto>> GetUserInfos(
            XDeviceDto device,
            string ids
        );
        Task<IEnumerable<XOpenActionUserInfoDto>> GetUserInfos(
            XOpenActionInnerDto dto
        );
        Task<IEnumerable<XOpenActionUserInfoDto>> GetUserInfos(
            string token,
            string request
        );
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXProxyHelper.cs

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using xIdentityService.Configuration;

namespace xIdentityService.Interfaces {
    public interface IXProxyHelper {
        /// <summary>
        /// Proxy Configuration ...
        /// </summary>
        /// <value></value>
        XProxyConfiguration Configuration { get; }
        
        /// <summary>
        /// retrie Normalize Host ...
        /// </summary>
        /// <returns></returns>
        string NormalizeHost ();

        /// <summary>
        /// Validate XProxy Configuration for Client ...
        /// </summary>
        /// <returns></returns>
        bool ValidateConfiguration ();

        /// <summary>
        /// Retrieve all Prepared url of Routes ...
        /// </summary>
        /// <returns></returns>
        IEnumerable<string> GetRouteUrls ();

        /// <summary>
        /// retrieve all registred Routes ...
        /// </summary>
        /// <returns></returns>
        IEnumerable<XProxyRouteDescriptor> GetRoutes ();

        /// <summary>
        /// Prepare a request url for a Proxy Route ...
        /// </summary>
        /// <param name="url"></param>
        /// <param name="descriptor"></param>
        /// <returns></returns>
        string PrepareActionUrlForXProxyRoute (
            string url,
            XProxyRouteDescriptor descriptor
        );

        /// <summary>
        /// Prepare a request url for a Selected Proxy Route ...
        /// </summary>
        /// <param name="url"></param>
        /// <param name="whereClause"></param>
        /// <returns></returns>
        string PrepareActionUrlForXProxyRoute (
            string url,
            Expression<Func<XProxyRouteDescriptor, bool>> whereClause
        );

        /// <summary>
        /// Find an Specific Route ...
        /// </summary>
        /// <param name="whereClause"></param>
        /// <returns></returns>
        XProxyRouteDescriptor FindRoute (Expression<Func<XProxyRouteDescriptor, bool>> whereClause);
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXSecurityProvider.cs

namespace xIdentityService.Interfaces
{
    public partial interface IXSecurityProvider
    {
        string Encrypt(string plainText);
        string Decrypt(string cipherText);
        string EncryptFromBytes(byte[] textBytes);
        string DecryptFromBytes(byte[] cipherBytes);
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXTokenProvider.cs

using System.Threading.Tasks;
using xIdentityModels.Models;

namespace xIdentityService.Interfaces {
    public partial interface IXTokenProvider {
        Task<bool> IsTokenExists (string accessToken);
        Task<bool> IsTokenExists (XTokenResponse tokens);
        Task<bool> RemoveToken (string accessToken);
        Task<bool> RemoveToken (XTokenResponse tokens);
        Task<XTokenResponse> RetrieveToken (string accessToken);
        Task<bool> AddToken (XTokenResponse tokens);
        Task<bool> UpdateToken (XTokenResponse tokens);
        Task<bool> AddOrUpdateToken (XTokenResponse tokens);
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Middlewares\XIdentityTokenRefresher.cs

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using xCommons.Constants;
using xCommons.Extensions;
using xIdentityModels.Extensions;
using xIdentityService.Interfaces;

namespace xIdentityService.Middlewares {
    public partial class XIdentityTokenRefresherMiddleware {
        //
        #region Properties ...
        private readonly ILogger logger;
        private readonly RequestDelegate next;
        private readonly IXTokenProvider tokenProvider;
        private readonly IXIdentityProvider identityProvider;
        #endregion

        //
        #region Constructor ...
        public XIdentityTokenRefresherMiddleware (
            RequestDelegate next,
            ILoggerFactory loggerFactory,
            IXTokenProvider tokenProvider,
            IXIdentityProvider identityProvider
        ) {
            //
            this.next = next;
            this.tokenProvider = tokenProvider;
            this.identityProvider = identityProvider;
            this.logger = loggerFactory
                .CreateLogger<XIdentityTokenRefresherMiddleware> ();
        }
        #endregion

        //
        #region Actions ...
        public async Task Invoke (HttpContext context) {
            //
            // Handle Request ...
            await HandleRequest (context);

            //
            // Do Main Task ...
            try {
                await next.Invoke (context);
            } catch (Exception ex) {
                logger.LogError ($"Error: {ex.Message}");
            }

            //
            // Handle Response ...
            await HandleResponse (context);
        }
        #endregion

        //
        #region Private ...
        private async Task HandleRequest (HttpContext context) {
            //
            // Log ...
            logger.LogInformation ($"Start Process Request ...");

            //
            // Check Access Token ...
            var hasAccessToken = HasAccessToken (context);
            if (!hasAccessToken) {
                return;
            }

            //
            // Check Access Token ...
            var accessToken = GetAccessToken (context);
            var isExists = await tokenProvider
                .IsTokenExists (accessToken);
            if (!isExists) {
                return;
            }

            //
            // Try Check is Refreshable ...
            var tokens = await tokenProvider
                .RetrieveToken (accessToken);
            if (tokens.IsNull ()) {
                return;
            }

            //
            // Check is Expired or Refreshable ...
            var isRefreshable = tokens.IsRefreshable ();
            if (!isRefreshable) {
                return;
            }

            //
            // Refresh Token ...
            var refreshedTokens = await identityProvider
                .RefreshTokens (tokens);
            if (refreshedTokens.IsNull ()) {
                return;
            }

            //
            // Set Refreshed AccessToken to Request ...
            context
                .Request
                .Headers[XAuthorization.Header] =
                $"{XAuthorization.TokenIdentifier}{refreshedTokens.AccessToken}";
        }

        private async Task HandleResponse (HttpContext context) {
            //
            // Log ...
            logger.LogInformation ($"Start Process Response ...");

            //
            await Task.Run (() => { });
        }

        private bool HasAccessToken (HttpContext context) {
            //
            // Check Headers ...
            if (context.IsNull () ||
                context.Request.IsNull () ||
                context.Request.Headers.IsNull ()) {
                return false;
            }

            //
            var result = context
                .Request
                .Headers
                .ContainsKey (
                    XAuthorization.Header
                );

            //
            return result;
        }

        private string GetAccessToken (HttpContext context) {
            //
            var hasAccessToken = HasAccessToken (context);
            if (!hasAccessToken) {
                return string.Empty;
            }

            //
            // Get Result ...
            var result = context
                .Request
                .Headers[
                    XAuthorization.Header
                ];
            result = result
                .ToString ()
                .Replace (
                    XAuthorization.TokenIdentifier,
                    ""
                );

            //
            return result;
        }
        #endregion
    }

    /// <summary>
    /// Provide all DI Requirements for XIdentityTokenRefresher Middleware
    /// </summary>
    public static class XIdentityTokenRefresherDIHelper {
        /// <summary>
        /// Use XTokenValidator Middleware
        /// </summary>
        /// <param name="app"></param>
        public static void UseXIdentityTokenRefresher (this IApplicationBuilder app) {
            app.UseMiddleware<XIdentityTokenRefresherMiddleware> ();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Middlewares\XProxyMiddleware.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using IdentityModel;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityService.Configuration;
using xIdentityService.Constants;
using xIdentityService.Interfaces;
using xIdentityService.Providers;
using xModels.Base;

namespace xIdentityService.Middlewares {
    /// <summary>
    /// Proxy Server Middleware ...
    /// </summary>
    public class XProxyMiddleware : XBaseClass {
        //
        #region Pros ...
        private readonly HttpClient HTTP_CLIENT;
        private readonly RequestDelegate NEXT_MIDDLEWARE;
        private readonly XProxyConfiguration CONFIGURATION;
        #endregion

        //
        #region Constructor ...
        public XProxyMiddleware (
            ILoggerFactory loggerFactory,
            RequestDelegate nextMiddleware,
            XProxyConfiguration configuration,
            IHttpClientFactory httpClientFactory
        ) : base (loggerFactory) {
            //
            this.CONFIGURATION = configuration;
            this.NEXT_MIDDLEWARE = nextMiddleware;

            //
            // Create Http Client ...
            this.HTTP_CLIENT = httpClientFactory
                .CreateClient (XProxyConstants.XPROXY_HTTP_CLIENT);

            //
            // Logging Server Configuration ...
            LogXProxyServerConfig ();
        }
        #endregion

        //
        #region Public ...
        public async Task InvokeAsync (HttpContext context) {
            //
            #region Bussiness Logic ...
            //
            var routeDescriptor = GetRouteDescriptor (context.Request);
            if (!routeDescriptor.IsNull ()) {
                //
                #region Handle Authorization ...
                //
                try {
                    //
                    // Handle XPowered ...
                    if (routeDescriptor.EnableXPoweredByAthorization) {
                        //
                        var isPoweredByPass = context.Request.Headers
                            .Any (h => h.Key
                                .ToNormalString () == xCommons.Constants.XAuthorization.XPoweredBy
                                .ToNormalString () &&
                                h.Value
                                .ToString ()
                                .ToNormalString () == CONFIGURATION.XPoweredValue
                                .ToNormalString ()
                            );

                        //
                        if (!isPoweredByPass) {
                            ThrowNotAuthorizedException ();
                        }
                    }

                    //
                    // Handle EndableAuthorization ...
                    if (routeDescriptor.EnableAuthorization) {
                        //
                        // Retrieve User Info for Authentication ...
                        var userName = context.User.Identity.Name;
                        var isUserAuthenticated = !userName.IsNull () &&
                            context.User.Identity.IsAuthenticated;
                        if (!isUserAuthenticated &&
                            !routeDescriptor.AllowedScopes.HasChild ()
                        ) {
                            ThrowNotAuthorizedException ();
                        }

                        //
                        // Check Allowed Scopes Authorization ...
                        if (routeDescriptor.AllowedScopes.HasChild ()) {
                            //
                            var scopeClaims = context.User.Claims
                                .Where (c => c.Type == JwtClaimTypes.Scope)
                                .Select (c => c.Value);
                            var isScopePassed = scopeClaims.HasChild () &&
                                scopeClaims.Any (c => routeDescriptor.AllowedScopes
                                    .Any (allowedScope => allowedScope
                                        .ToNormalString () == c
                                        .ToNormalString ()
                                    )
                                );
                            if (!isScopePassed) {
                                ThrowNotAuthorizedException ();
                            }
                        }

                        //
                        // Check Allowed Roles  Authorization ...
                        if (
                            isUserAuthenticated &&
                            routeDescriptor.AllowedRoles.HasChild ()
                        ) {
                            //
                            var roleClaim = context.User.Claims
                                .FirstOrDefault (c => c.Type == JwtClaimTypes.Role);
                            var isRolePassed = !roleClaim.IsNull () &&
                                routeDescriptor.AllowedRoles
                                .Any (role => role
                                    .ToNormalString () == roleClaim.Value
                                    .ToNormalString ());
                            if (!isRolePassed) {
                                ThrowNotAuthorizedException ();
                            }
                        }
                    }
                } catch {
                    context.Response.StatusCode = (int) HttpStatusCode.Unauthorized;
                    return;
                }
                #endregion

                //
                // Extract Request Uri from Received Request ...
                var requestUri = GetUri (context.Request);
                if (!requestUri.IsNull ()) {
                    //
                    // Retrieve Request based on current ...
                    var request = GetRequestMessage (
                        uri: requestUri,
                        context: context
                    );

                    //
                    SendLog ($"Send Request to Recieve Response ...", LogLevel.Information);

                    //
                    // Send Request and Retrieve Response ...
                    try {
                        //
                        var response = await HTTP_CLIENT.SendAsync (
                            request,
                            HttpCompletionOption.ResponseContentRead
                        );

                        //
                        // Set Current Response Status Code ...
                        context.Response.StatusCode = (int) response.StatusCode;

                        //
                        // Retrieve Response Headers and Set To Current Response ...
                        HandleResponseHeaders (context, response);

                        //
                        // Processing Response Content ...
                        await ProcessResponseContent (context, response);
                    } catch (Exception ex) {
                        //
                        LogMessage ($"Exception: {ex.Message}", LogLevel.Error);

                        //
                        context.Response.StatusCode = (int) HttpStatusCode.BadRequest;
                    }

                    //
                    return;
                }
            }
            #endregion

            //
            await NEXT_MIDDLEWARE (context);
        }
        #endregion

        //
        #region Private ...
        /// <summary>
        /// Throw Required Exception ...
        /// </summary>
        private void ThrowNotAuthorizedException () {
            throw XException.NotAuthorized.ToException ();
        }

        /// <summary>
        /// Show propper logs if Enabled ...
        /// </summary>
        /// <param name="message"></param>
        /// <param name="logLevel"></param>
        private void SendLog (string message, LogLevel logLevel = LogLevel.Information) {
            //
            if (!CONFIGURATION.EnableLogging) {
                return;
            }

            //
            LogMessage (
                message: message,
                logLevel: logLevel
            );
        }

        /// <summary>
        /// Log Proxy Server Configuration ...
        /// </summary>
        private void LogXProxyServerConfig () {
            //
            // Retrieve XProxyConfiguration class from Configurations and Validate them ...
            if (CONFIGURATION.IsNull ()) {
                throw XException.InvalidConfiguration.ToException ();
            }

            //
            // Try to Log Proxy Configuration ...
            ConsoleMessage ("===============================");
            ConsoleMessage ("= Proxy Server Configurations: ");
            ConsoleMessage ("===============================");

            //
            ConsoleMessage ($"Host: {CONFIGURATION.Host}");
            ConsoleMessage ($"XPoweredValue: {CONFIGURATION.XPoweredValue}");
            ConsoleMessage ($"EnableLogging: {CONFIGURATION.EnableLogging}");
            ConsoleMessage ($"DisableSSLCheck: {CONFIGURATION.DisableSSLCheck}");
            ConsoleMessage ($"AllowAutoRedirect: {CONFIGURATION.AllowAutoRedirect}");
            ConsoleMessage ($" ");
            ConsoleMessage ($"Routes: ");
            ConsoleMessage ($" ");

            //
            CONFIGURATION.Routes
                .ToList ()
                .ForEach (routeDescriptor => {
                    ConsoleMessage ("===============================");
                    ConsoleMessage ($"= Rote => {routeDescriptor.Route}");
                    ConsoleMessage ("===============================");
                    ConsoleMessage ($"AllowedRoles: {routeDescriptor.AllowedRoles.ToJSON()}");
                    ConsoleMessage ($"AllowedScopes: {routeDescriptor.AllowedScopes.ToJSON()}");
                    ConsoleMessage ($"EnableAuthorization: {routeDescriptor.EnableAuthorization}");
                    ConsoleMessage ($"EnableXPoweredByAthorization: {routeDescriptor.EnableXPoweredByAthorization}");
                    ConsoleMessage ($" ");
                });
        }

        /// <summary>
        /// Retrieve Destination Request Path based on Current Request ...
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private Uri GetUri (HttpRequest request) {
            //
            // Create temp result ...
            Uri result = null;
            var requestPath = "";

            //
            SendLog ($"Receive Request: {request.Path} ...", LogLevel.Information);

            //
            // Try to Findout Route Descriptor ...
            var routeDescriptor = GetRouteDescriptor (request);

            //
            // Route Descriptor Exists && Path for Delegating ...
            if (!routeDescriptor.IsNull () &&
                request.Path
                .StartsWithSegments (routeDescriptor.Route)
            ) {
                //
                // Prepare Request Path by Cleaning Starter Path Segment ...
                requestPath = request.Path
                    .ToString ()
                    .Replace (routeDescriptor.Route, "");
                if (requestPath.StartsWith ("/")) {
                    requestPath = requestPath.Substring (1);
                }

                //
                // Decoding URL ...
                requestPath = HttpUtility.UrlDecode (requestPath);

                //
                var colonIndex = requestPath.IndexOf (":");
                if (colonIndex > -1) {
                    //
                    var doubleSlash = requestPath.Substring (colonIndex + 1, 2);
                    var isDoubleSlash = doubleSlash == "//";

                    //
                    if (!isDoubleSlash) {
                        //
                        var protocol = requestPath
                            .Substring (0, colonIndex);
                        var section = requestPath
                            .Substring (colonIndex + 2, requestPath.Length - colonIndex - 2);

                        //
                        requestPath = $"{protocol}://{section}";
                    }
                }
            }

            //
            // Validate Request Path ...
            if (!requestPath.IsNullOrEmpty ()) {
                //
                result = new Uri (requestPath);

                //
                SendLog ($"Process Request: {requestPath} ...", LogLevel.Information);
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve Propper Request Message based on HttpContext and uri ...F
        /// </summary>
        /// <param name="context"></param>
        /// <param name="uri"></param>
        /// <returns></returns>
        private HttpRequestMessage GetRequestMessage (
            HttpContext context,
            Uri uri
        ) {
            //
            var result = new HttpRequestMessage ();
            FillRequest (context, result);

            //
            // Handle Queries ...
            SendLog ($"Start Processing Queries: ");
            foreach (var query in context.Request.Query) {
                //
                var key = query.Key;
                var value = HttpUtility.UrlDecode (query.Value);

                //
                uri = new Uri (
                    QueryHelpers.AddQueryString (
                        uri.OriginalString,
                        new Dictionary<string, string> {
                            [key] = value
                        }
                    )
                );

                //
                SendLog ($"Query : {key}:{value} was Processed ...");
            }

            //
            result.RequestUri = uri;
            result.Headers.Host = uri.Host;

            //
            // Retrieve Request Method ...
            result.Method = GetMethod (context.Request.Method);

            //
            return result;
        }

        /// <summary>
        /// Fill Request Message by provide HttpContext ...
        /// </summary>
        /// <param name="context"></param>
        /// <param name="message"></param>
        private void FillRequest (
            HttpContext context,
            HttpRequestMessage message
        ) {
            //
            var requestMethod = context.Request.Method;

            //
            if (!HttpMethods.IsGet (requestMethod) &&
                !HttpMethods.IsHead (requestMethod) &&
                !HttpMethods.IsTrace (requestMethod) &&
                !HttpMethods.IsDelete (requestMethod)
            ) {
                //
                var streamContent = new StreamContent (context.Request.Body);
                message.Content = streamContent;
            }

            //
            // Handle Base Headers ...
            var regularHeaders = context.Request.Headers
                .Where (hr => hr.Key != XProxyConstants.XPROXY_ACCEPTED_HEADERS &&
                    !hr.Key
                    .Contains (
                        XProxyConstants.XPROXY_FORWARD_HEADER
                    )
                );

            //
            // Handle Aceepted Headers ...
            IEnumerable<string> acceptedHeaders = null;
            var acceptedHeadersKeyValue = context.Request.Headers
                .FirstOrDefault (hr =>
                    hr.Key == XProxyConstants.XPROXY_ACCEPTED_HEADERS
                );
            if (!acceptedHeadersKeyValue.IsNull ()) {
                //
                acceptedHeaders = acceptedHeadersKeyValue.Value
                    .ToString ()
                    .ParseListString<string> ();

                //
                // Filter Regular Headers ...
                if (
                    regularHeaders.HasChild () &&
                    acceptedHeaders.HasChild ()
                ) {
                    //
                    regularHeaders = regularHeaders
                        .Where (rhr => acceptedHeaders
                            .Contains (rhr.Key)
                        );
                }
            }
            foreach (var header in regularHeaders) {
                //
                SendLog ($"Adding Header: {header.Key}:{header.Value} ...");

                //
                message.Headers.Add (
                    header.Key,
                    header.Value
                    .ToString ()
                );
            }

            //
            // Handle ForWarded Headers ...
            // Since Forward Headers is Custom kind, this means user actually need this
            // Header, so there is no need to put them on AcceptedHeaders ...
            var forwardHeaders = context.Request.Headers
                .Where (hr => hr.Key
                    .Contains (
                        XProxyConstants.XPROXY_FORWARD_HEADER
                    )
                );
            foreach (var header in forwardHeaders) {
                //
                var key = header.Key
                    .Replace (
                        XProxyConstants.XPROXY_FORWARD_HEADER,
                        string.Empty
                    );

                //
                SendLog ($"Forwarding Header: {header.Key} to {key} ...");

                //
                message.Headers
                    .Add (
                        key,
                        header.Value
                        .ToString ()
                    );
            }
        }

        /// <summary>
        /// Retreive and Extract Method Type of HttpRequest ...
        /// </summary>
        /// <param name="method"></param>
        /// <returns></returns>
        private static HttpMethod GetMethod (string method) {
            //
            if (HttpMethods.IsDelete (method)) {
                return HttpMethod.Delete;
            } else if (HttpMethods.IsGet (method)) {
                return HttpMethod.Get;
            } else if (HttpMethods.IsHead (method)) {
                return HttpMethod.Head;
            } else if (HttpMethods.IsOptions (method)) {
                return HttpMethod.Options;
            } else if (HttpMethods.IsPost (method)) {
                return HttpMethod.Post;
            } else if (HttpMethods.IsPut (method)) {
                return HttpMethod.Put;
            } else if (HttpMethods.IsTrace (method)) {
                return HttpMethod.Trace;
            }

            //
            return new HttpMethod (method);
        }

        /// <summary>
        /// add all headers exists in HttpResponse MEssage to Current Context Response Headers ...
        /// </summary>
        /// <param name="context"></param>
        /// <param name="message"></param>
        private void HandleResponseHeaders (
            HttpContext context,
            HttpResponseMessage message
        ) {
            //
            // Handle Message Headers ...
            foreach (var header in message.Headers) {
                context.Response.Headers[header.Key] = header.Value
                    .ToArray ();
            }

            //
            // Handle Message Content Headers ...
            foreach (var header in message.Content.Headers) {
                context.Response.Headers[header.Key] = header.Value
                    .ToArray ();
            }

            //
            context.Response.Headers.Remove ("transfer-encoding");
        }

        /// <summary>
        /// Processing Response Content and Handle it on HttpContextResponse ...
        /// </summary>
        /// <param name="context"></param>
        /// <param name="response"></param>
        /// <returns></returns>
        private async Task ProcessResponseContent (
            HttpContext context,
            HttpResponseMessage message
        ) {
            //
            // Reading Content as Byte Array ...
            var contentBytes = await message.Content
                .ReadAsByteArrayAsync ();

            //
            // Check ContentType of Response ...
            if (
                IsContentOfType (message, XResponseContentTypes.HTML) ||
                IsContentOfType (message, XResponseContentTypes.JSON) ||
                IsContentOfType (message, XResponseContentTypes.JavaScript)
            ) {
                //
                // If their String Content ...
                var stringContent = Encoding.UTF8.GetString (contentBytes);

                //
                // TODO: here we can change String Contents ...

                //
                // Writing new Content to Response ...
                await context.Response
                    .WriteAsync (
                        stringContent,
                        Encoding.UTF8
                    );
            } else {
                //
                // if they have non string content ...
                await context.Response.Body
                    .WriteAsync (
                        buffer: contentBytes,
                        offset: 0,
                        count: contentBytes.Length
                    );
            }

            //
            SendLog ($"Response Content Processed ...", LogLevel.Information);
        }

        /// <summary>
        /// Check Content Type of Specific Response ...
        /// </summary>
        /// <param name="response"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private bool IsContentOfType (
            HttpResponseMessage response,
            string type
        ) {
            //
            // Create EMpty Result ...
            var result = false;

            //
            // Retrieve and Check Content Type of Response ...
            if (response.Content?.Headers?.ContentType != null) {
                result = response.Content.Headers.ContentType.MediaType == type;
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve and Extract Route Descriptor ...
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private XProxyRouteDescriptor GetRouteDescriptor (HttpRequest request) {
            //
            // Validate Args ...
            if (
                CONFIGURATION.IsNull () ||
                !CONFIGURATION.Routes.HasChild ()
            ) {
                return null;
            }

            //
            var result = CONFIGURATION.Routes
                .FirstOrDefault (rd => !rd.Route.IsNullOrEmpty () &&
                    request.Path
                    .StartsWithSegments (rd.Route
                        .ToNormalString ()
                    )
                );

            //
            return result;
        }
        #endregion 
    }

    /// <summary>
    /// Provide all requirements for Dependency Injection Handler ...
    /// </summary>
    public static class XDIHelperExtension {
        /// <summary>
        /// Retrieve XProxy Middelware Configuration from Configuration ...
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        public static XProxyConfiguration GetXProxyConfiguration (this IConfiguration config) {
            //
            var xProxyConfiguration = config.GetSection (ConfigurationNodeNames.XPROXY_CONFIGURATION_NODE_NAME);
            return xProxyConfiguration.Get<XProxyConfiguration> ();
        }

        /// <summary>
        /// Register HTTP Handler for XProxy Server ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="httpHandler"></param>
        public static void AddXProxyHttpHandler (
            this IServiceCollection services,
            IConfiguration configuration,
            HttpClientHandler httpHandler = null
        ) {
            //
            var proxyConfig = configuration.GetXProxyConfiguration ();
            if (proxyConfig.IsNull ()) {
                throw XException.InvalidConfiguration.ToException ();
            }

            //
            services.AddXProxyHttpHandler (
                httpHandler: httpHandler,
                configuration: proxyConfig
            );
        }

        /// <summary>
        /// Register HTTP Handler for XProxy Server ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="httpHandler"></param>
        public static void AddXProxyHttpHandler (
            this IServiceCollection services,
            XProxyConfiguration configuration,
            HttpClientHandler httpHandler = null
        ) {
            //
            if (configuration.IsNull ()) {
                throw XException.InvalidConfiguration.ToException ();
            }

            //
            if (httpHandler.IsNull ()) {
                httpHandler = new HttpClientHandler ();
            }

            //
            httpHandler.AllowAutoRedirect = configuration.AllowAutoRedirect;

            //
            if (configuration.DisableSSLCheck) {
                httpHandler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
            }

            //
            services
                .AddHttpClient (XProxyConstants.XPROXY_HTTP_CLIENT)
                .ConfigurePrimaryHttpMessageHandler (() => {
                    return httpHandler;
                });
        }

        /// <summary>
        /// Register XProxy On Server ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="httpHandler"></param>
        public static void AddXProxyServer (
            this IServiceCollection services,
            IConfiguration configuration,
            HttpClientHandler httpHandler = null
        ) {
            //
            var proxyConfig = configuration.GetXProxyConfiguration ();

            //
            services.AddXProxyServer (
                httpHandler: httpHandler,
                configuration: proxyConfig
            );
        }

        /// <summary>
        /// Register XProxy On Server ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="httpHandler"></param>
        public static void AddXProxyServer (
            this IServiceCollection services,
            XProxyConfiguration configuration,
            HttpClientHandler httpHandler = null
        ) {
            //
            // Validate Args ...
            if (configuration.IsNull ()) {
                throw XException.InvalidConfiguration.ToException ();
            }

            //
            // Register Proxy Configuration ...
            services.AddSingleton<XProxyConfiguration> (configuration);

            //
            // Regiter Proxy Handler ...
            services.AddXProxyHttpHandler (
                httpHandler: httpHandler,
                configuration: configuration
            );
        }

        /// <summary>
        /// Register XProxy On Server ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXProxyClient (
            this IServiceCollection services,
            IConfiguration configuration
        ) {
            //
            var proxyConfig = configuration.GetXProxyConfiguration ();

            //
            services.AddXProxyClient (
                configuration: proxyConfig
            );
        }

        /// <summary>
        /// Register XProxy On Client ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXProxyClient (
            this IServiceCollection services,
            XProxyConfiguration configuration
        ) {
            //
            // Validate Args ...
            if (configuration.IsNull ()) {
                throw XException.InvalidConfiguration.ToException ();
            }

            //
            // Register Proxy Configuration ...
            services.AddSingleton<XProxyConfiguration> (configuration);

            //
            // Register IXProxyHelper ...
            services.AddSingleton<IXProxyHelper, XProxyHelper> ();
        }

        /// <summary>
        /// Adding XProxy Middleware to Applications ...
        /// </summary>
        /// <param name="app"></param>
        public static void UseXProxy (this IApplicationBuilder app) {
            app.UseMiddleware<XProxyMiddleware> ();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Models\XBaseRestResponse.cs

using RestSharp;

namespace xIdentityService.Models
{
    public class XBaseRestResponse<T>
    {
        public T Model { get; set; }
        public IRestResponse Response { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Partial\XIdentityProvider+Admin.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using xCommons.Extensions;
using xHttpService.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityService.Constants;

namespace xIdentityService.Providers {
    public partial class XIdentityProvider {
        //
        #region Admin ...
        /// <summary>
        /// Ban Specific Users
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represents user identifier list to Ban</param>
        /// <returns>a list of banned users identifiers</returns>
        public async Task<IEnumerable<string>> Ban (
            XTokenResponse tokens,
            XUserNameIdRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (
                    tokens,
                    model
                )
                .AddNotEmpty (tokens.AccessToken)
                .AddNotZeroChilds (model.Ids)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.Ban);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<IEnumerable<string>> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// UnBann Specific Users 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represents user identifier list to Ban</param>
        /// <returns>a list of unbanned users identifiers</returns>
        public async Task<IEnumerable<string>> UnBan (
            XTokenResponse tokens,
            XUserNameIdRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (
                    tokens,
                    model
                )
                .AddNotEmpty (tokens.AccessToken)
                .AddNotZeroChilds (model.Ids)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.UnBan);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<IEnumerable<string>> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Check Specific User is Banned or not
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="userSelectByParam">specified user's identifier</param>
        /// <returns>a boolean value which represent user banned or not</returns>
        public async Task<bool> IsBanned (
            XTokenResponse tokens,
            string userSelectByParam
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotEmpty (
                    userSelectByParam,
                    tokens.AccessToken
                )
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.IsBanned,
                @params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam } }
            );

            //
            var response = await RunRestRequest<bool> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Partial\XIdentityProvider+Authentication.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using IdentityModel.Client;
using xCommons.Extensions;
using xExceptions.Constants;
using xHttpService.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityService.Constants;

namespace xIdentityService.Providers {
    public partial class XIdentityProvider {
        //
        #region Authentication Handlers ...
        /// <summary>
        /// Request for Discovery Document 
        /// </summary>
        /// <returns>an instance of DiscoveryDocumentResponse</returns>
        public async Task<DiscoveryDocumentResponse> RequestDiscoveryDocument () {
            //
            var httpClient = GetHttpClient ();

            //
            try {
                //
                var result = httpClient
                    .GetDiscoveryDocumentAsync (identityConfiguration.Authority)
                    .ContinueWith (docTask => {
                        //
                        httpClient.Dispose ();
                        return docTask.Result;
                    });

                //
                return await result;
            } catch {
                throw XException.ActionFailed.ToException ();
            }
        }

        /// <summary>
        /// Request AccessToken for Specific XApiScope
        /// </summary>
        /// <param name="scope">a member of <see>XApiScope</see></param>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        public async Task<XTokenResponse> RequestScopeAccessToken (string scope) {
            //
            // Validate Args ...
            var scopeName = string.Empty;
            try {
                scopeName = scope; // scope.GetStringValue ();
            } catch { }
            if (scopeName.IsNullOrEmpty ()) {
                XException.InvalidArgs.Throw ();
            }

            //
            var client = GetRestClient ();
            var request = GetRestRequet (
                XApiAccountEndpoint.RequestScopeAccessToken,
                headers : new Dictionary<string, string> { { XParam.XScope.GetStringValue (), scope.ToString () } });

            //
            var response = await RunRestRequest<XTokenResponse> (
                client,
                request,
                XHttpMethod.POST
            );

            //
            // Save Token ...
            if (!response.IsNull ()) {
                await tokenProvider.AddOrUpdateToken (response);
            }

            //
            return response;
        }

        /// <summary>
        /// Validate a token
        /// </summary>
        /// <param name="model">Authentication Tokens</param>
        /// <returns>an instance of TokenIntrospectionResponse</returns>
        public async Task<TokenIntrospectionResponse> Introspection (XTokenResponse model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (model)
                .AddNotEmpty (model.AccessToken)
                .ValidateGroupAsync ();

            //
            var httpClient = GetHttpClient ();

            //
            try {
                //
                var discoDoc = await RequestDiscoveryDocument ();
                if (discoDoc.IsError) {
                    XException.ActionFailed.Throw ();
                }

                //
                var response = await httpClient.IntrospectTokenAsync (new TokenIntrospectionRequest {
                    //
                    Address = discoDoc.IntrospectionEndpoint,
                        ClientId = identityConfiguration.ClientId,
                        ClientSecret = identityConfiguration.ClientSecret,

                        //
                        Token = model.AccessToken
                });
                if (response.IsError) {
                    throw new Exception (response.Error);
                }

                //
                return response;
            } catch {
                throw XException.ActionFailed.ToException ();
            }
        }

        /// <summary>
        /// Authenticate a User
        /// </summary>
        /// <param name="model">User Login Required Info, an instance of <see>XLoginRequest</see></param>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        public async Task<XTokenResponse> Authenticate (XLoginRequest model) {
            //
            // Validate Args ...
            validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (model)
                .AddNotEmpty (
                    model.UserSelectBy,
                    model.Password
                )
                .ValidateGroup ();

            //
            var client = GetRestClient ();
            var request = GetRestRequet (XApiAccountEndpoint.Authenticate);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XTokenResponse> (
                client,
                request,
                XHttpMethod.POST
            );

            //
            // Save Token ...
            if (!response.IsNull ()) {
                await tokenProvider.AddOrUpdateToken (response);
            }

            //
            return response;
        }

        /// <summary>
        /// Do Login based on XLoginRequest
        /// </summary>
        /// <param name="model">User Login Required Info, an instance of <see>XLoginRequest</see></param>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        public async Task<XLoginResponse> Login (XLoginRequest model) {
            //
            // Validate Args ...
            validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (model, model.Device)
                .AddNotEmpty (
                    model.UserSelectBy,
                    model.Password
                )
                .ValidateGroup ();

            //
            var client = GetRestClient ();
            var request = GetRestRequet (XApiAccountEndpoint.Login);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XLoginResponse> (
                client,
                request,
                XHttpMethod.POST
            );

            //
            if (!response.IsNull ()) {
                //
                var tokens = response.ToXTokenResponse ();
                await tokenProvider.AddOrUpdateToken (tokens);
            }

            //
            return response;
        }

        /// <summary>
        /// Logout from System
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task Logout (XTokenResponse model) {
            //
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (model)
                .AddNotEmpty (model.AccessToken)
                .ValidateGroupAsync ();

            //
            var isExists = await tokenProvider
                .IsTokenExists (model.AccessToken);
            if (isExists) {
                await tokenProvider
                    .RemoveToken (model.AccessToken);
            }
        }

        /// <summary>
        /// Refresh Tokens 
        /// </summary>
        /// <param name="model">Authentication Tokens</param>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        public async Task<XTokenResponse> RefreshTokens (XTokenResponse model) {
            //
            // Validate Args ...
            validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (model)
                .AddNotEmpty (
                    model.AccessToken,
                    model.RefreshToken
                )
                .ValidateGroup ();

            //
            var client = GetRestClient (model);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.RefreshTokens,
                headers : model.ToHeaderDictionary ());
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XTokenResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            if (!response.IsNull ()) {
                await tokenProvider.UpdateToken (response);
            }

            //
            return response;
        }
        #endregion

        //
        #region Password Actions Handlers ...
        /// <summary>
        /// Change Password
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        public async Task ChangePassword (
            XTokenResponse tokens,
            XActionRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens, model)
                .AddNotEmpty (
                    model.Lang,
                    model.Password,
                    model.NewPassword,
                    model.ReturnUrl)
                .AddNotNull (model.Device)
                .ValidateGroupAsync ();

            //
            // Validate User Select By Param ...
            var userSelectByParam = GetUserSelectByParam (
                model,
                forceNotNull : true,
                excludes : null);

            //
            var client = GetRestClient (tokens);
            var request = GetRestRequet (
                XApiAccountEndpoint.ChangePassword,
                headers : tokens.ToHeaderDictionary ());
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<Object> (
                client,
                request,
                XHttpMethod.POST
            );
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Partial\XIdentityProvider+Friendship.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using xCommons.Extensions;
using xHttpService.Constants;
using xHttpService.Extensions;
using xIdentityModels.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
using xIdentityService.Constants;
using xModels.Dtos;

namespace xIdentityService.Providers
{
    public partial class XIdentityProvider
    {
        //
        #region Friendship ...
        /// <summary>
        /// Follow a User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        public async Task<XFriendshipFollowing> Follow(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.Follow,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipFollowing>(
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Cancel Following Request 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> Cancel(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.Cancel,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<bool>(
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Unfollow a Follower
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns></returns>
        public async Task UnFollowFollower(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.UnFollowFollower,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<object>(
                client,
                request,
                XHttpMethod.POST
            );
        }

        /// <summary>
        /// Unfollow Following
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns></returns>
        public async Task UnFollowFollowing(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.UnFollowFollowing,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<object>(
                client,
                request,
                XHttpMethod.POST
            );
        }

        /// <summary>
        /// Block a Follower
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        public async Task<XFriendshipFollowing> Block(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.Block,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipFollowing>(
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Unblock a Blocked User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        public async Task<XFriendshipFollowing> UnBlock(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.UnBlock,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipFollowing>(
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Accept a Following Request 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        public async Task<XFriendshipFollower> AcceptRequest(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.AcceptRequest,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipFollower>(
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Reject a Following Request
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        public async Task<XFriendshipFollower> RejectRequest(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.RejectRequest,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipFollower>(
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Get Friendship Info Model between Specific User and Current User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipInfoDto</see></returns>
        public async Task<XFriendshipInfoDto> GetFriendshipInfo(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.FriendshipInfo,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipInfoDto>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Check a User IsFollower of Requested User 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsFollower(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.IsFollower,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<bool>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get Specific Follower 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        public async Task<XFriendshipFollower> GetFollower(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.Follower,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipFollower>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get Follower State of a User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipState</see></returns>
        public async Task<XFriendshipState> GetFollowerState(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.FollowerState,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipState>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get Followers List Of Current User 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <returns>a collection of <see>XFriendshipFollower</see></returns>
        public async Task<IEnumerable<XFriendshipFollower>> GetFollowers(
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.Followers);

            //
            var response = await RunRestRequest<IEnumerable<XFriendshipFollower>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get All Followers List Includes Blocked, Requested and etc 
        /// of Current User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <returns>a collection of <see>XFriendshipFollower</see></returns>
        public async Task<IEnumerable<XFriendshipFollower>> GetAllFollowers(
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.AllFollowers);

            //
            var response = await RunRestRequest<IEnumerable<XFriendshipFollower>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Return Followers UserName's List of Current User 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <returns>a collection of UserNames</returns>
        public async Task<IEnumerable<string>> GetFollowersList(
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.FollowersList);

            //
            var response = await RunRestRequest<IEnumerable<string>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Retrieve All User's Followers based on Query Model ...
        /// </summary>
        /// <param name="query">Query Model Descriptor</param>
        /// <param name="destUser">Dest User for Reading Followers</param>
        /// <param name="tokens">Requester User's Descriptor</param>
        /// <returns></returns>
        public async Task<XQueryResult<XFriendDto>> QueryFollowers(
            XQuery query,
            string destUser,
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(destUser)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.QueryFollowers);

            //
            // Attach XQuery to Request ...
            request = request.AttachXQuery(query);
            request = request.AttachDestUser(destUser);

            //
            var response = await RunRestRequest<XQueryResult<XFriendDto>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Check a User is in Followings of Current User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsFollowing(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.IsFollowing,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<bool>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get Specific Following Model
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        public async Task<XFriendshipFollowing> GetFollowing(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.Following,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipFollowing>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get Following State Relation between Specific User 
        /// and Current User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipState</see></returns>
        public async Task<XFriendshipState> GetFollowingState(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.FollowingState,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipState>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get Followings of Current User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <returns>a collection of <see>XFriendshipFollowing</see></returns>
        public async Task<IEnumerable<XFriendshipFollowing>> GetFollowings(
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.Followings);

            //
            var response = await RunRestRequest<IEnumerable<XFriendshipFollowing>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get All Following List Includes Blocked, Requested and etc 
        /// of Current User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <returns>a collection of <see>XFriendshipFollowing</see></returns>
        public async Task<IEnumerable<XFriendshipFollowing>> GetAllFollowings(
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.AllFollowings);

            //
            var response = await RunRestRequest<IEnumerable<XFriendshipFollowing>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Return Following UserName's List of Current User 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <returns>a collection of UserNames</returns>
        public async Task<IEnumerable<string>> GetFollowingList(
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.FollowingsList);

            //
            var response = await RunRestRequest<IEnumerable<string>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Retrieve All User's Followings based on Query Model ...
        /// </summary>
        /// <param name="query">Query Model Descriptor</param>
        /// <param name="destUser">Dest User for Reading Followers</param>
        /// <param name="tokens">Requester User's Descriptor</param>
        /// <returns></returns>
        public async Task<XQueryResult<XFriendDto>> QueryFollowings(
            XQuery query,
            string destUser,
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(destUser)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.QueryFollowings);

            //
            // Attach XQuery to Request ...
            request = request.AttachXQuery(query);
            request = request.AttachDestUser(destUser);

            //
            var response = await RunRestRequest<XQueryResult<XFriendDto>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Partial\XIdentityProvider+Open.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using MongoDB.Bson;
using xCommons.Constants;
using xCommons.Extensions;
using xExceptions.Constants;
using xHttpService.Constants;
using xIdentityModels.Dtos;
using xIdentityService.Constants;
using xModels.Dtos;

namespace xIdentityService.Providers
{
    public partial class XIdentityProvider
    {
        /// <summary>
        /// Prepare API Based Device to Open Actions ...
        /// </summary>
        /// <returns></returns>
        public  XDeviceDto GetDevice()
        {
            //
            var os = "XSaherElmOS";
            bool isOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
            bool isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
            bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
            if (isOSX)
            {
                os = "MacOs";
            }
            else if (isLinux)
            {
                os = "Linux";
            }
            else if (isWindows)
            {
                os = "Windows";
            }
            var agent = RuntimeInformation.FrameworkDescription;
            if (agent.IsNullOrEmpty())
            {
                agent = "XSaherElmOSAgent";
            }
            var version = RuntimeInformation.OSArchitecture + ", " + RuntimeInformation.OSDescription;
            if (version.IsNullOrEmpty())
            {
                version = "XSaherElmOSVersion";
            }
            var browser = "XSaherElmBrowser_" + RevisionSecretKey.ToMd5String();

            //
            var result = new XDeviceDto
            {
                Os = os,
                Browser = browser,
                UserAgent = agent,
                OsVersion = version,
                DeviceType = XDeviceType.Desktop,
            };

            //
            return result;
        }

        //
        #region OpenGet ...
        public async Task<XOpenActionInnerDto> OpenGet(
            XOpenActionInnerDto model
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(model)
                .AddNotEmpty(model.Token)
                .AddNotEmpty(model.Payload)
                .ValidateGroupAsync();

            //
            var result = await OpenGet(
                token: model.Token,
                actionRequest: model.Payload
            );

            //
            return result;
        }
        public async Task<XOpenActionInnerDto> OpenGet(
            string token,
            string actionRequest
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(token)
                .AddNotEmpty(actionRequest)
                .ValidateGroupAsync();

            //
            // Retrieve Rest Client ...
            var client = GetRestClient();

            //
            // Prepare Rest Request ...
            var request = GetRestRequet(
                XApiAccountEndpoint.Open,
                headers: new Dictionary<string, string>
                {
                    { XAuthentication.TOKEN, token}
                },
                queryStrings: new Dictionary<string, string>
                {
                    { XParam.XRequest.GetStringValue(), actionRequest }
                }
            );

            //
            // Run Request and Retrieve Response ...
            var response = await RunRestRequestByResponse<string>(
                client,
                request,
                XHttpMethod.GET
            );

            //
            // Now we Have to Validate the recieved response ...

            //
            // Read token from Headers ...
            var responseToken = response.Response.Headers
                .First(h => h.Name == XAuthentication.TOKEN).Value.ToString();
            if (responseToken.IsNullOrEmpty())
            {
                XException.ActionFailed.Throw();
            }

            //
            // Decript Recieve Response ...
            var responseJson = response.Model; // SecurityProvider.Decrypt(response.Model);
            if (responseJson.IsNullOrEmpty())
            {
                XException.ActionFailed.Throw();
            }

            //
            var result = new XOpenActionInnerDto
            {
                Token = responseToken,
                Payload = responseJson
            };

            //
            // Retrieve Model and Validate it ...
            var responseModel = responseJson.FromJSON<XOpenActionRequestDto>();
            if (responseModel.IsNull() ||
                responseModel.Payload.IsNullOrEmpty() ||
                responseToken != responseModel.Checksum ||
                responseModel.Timestamp.FromTimestamp().IsExPired())
            {
                XException.ActionFailed.Throw();
            }

            //
            return result;
        }
        #endregion

        //
        #region GetUserInfo ...
        public async Task<XOpenActionUserInfoDto> GetUserInfo(
            XDeviceDto device,
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            validationProvider.NotNull(device);
            validationProvider.NotEmpty(userSelectByParam);

            //
            // Prepare Open Action Model ...
            var opaModel = new XOpenActionRequestDto
            {
                Device = device,
                Payload = userSelectByParam,
                Action = XOpenActions.GetUserInfo,
                Timestamp = DateTime.UtcNow.AddMinutes(5).ToTimestamp().ToString()
            };
            if (!opaModel.Validate())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Fill Checksum Filed ...
            var token = opaModel.ToOpenActionToken();
            opaModel.Checksum = token;

            //
            // Prepare Request ...
            var opaJson = opaModel.ToJson();
            var requestString = SecurityProvider.Encrypt(opaJson);

            //
            return await GetUserInfo(
                token: token,
                request: requestString
            );
        }

        public async Task<XOpenActionUserInfoDto> GetUserInfo(
            XOpenActionInnerDto dto
        )
        {
            //
            return await GetUserInfo(
                token: dto.Token,
                request: dto.Payload
            );
        }

        public async Task<XOpenActionUserInfoDto> GetUserInfo(
            string token,
            string request
        )
        {
            //
            // Validate Args ...
            validationProvider.NotEmpty(token);
            validationProvider.NotEmpty(request);

            //
            // Retrieve and Validate Response ...
            var response = await OpenGet(
                token: token,
                actionRequest: request
            );
            if (response.IsNull() ||
                response.Token.IsNullOrEmpty() ||
                response.Payload.IsNullOrEmpty())
            {
                XException.ActionFailed.Throw();
            }

            //
            // Now we Have to Converts Repose Payload to Result Model ...
            // Note that the respose Model's payload here is Decrypted and
            // actually is Json Representation of Result Model ...
            var requestModel = response.Payload.FromJSON<XOpenActionRequestDto>();
            if (requestModel.IsNull())
            {
                XException.ActionFailed.Throw();
            }

            //
            var resultJson = SecurityProvider.Decrypt(requestModel.Payload);
            var result = resultJson.FromJSON<XOpenActionUserInfoDto>();
            if (result.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            return result;
        }
        #endregion

        //
        #region GetUserInfos ...
        public async Task<IEnumerable<XOpenActionUserInfoDto>> GetUserInfos(
            XDeviceDto device,
            string ids
        )
        {
            //
            // Validate Args ...
            validationProvider.NotNull(device);
            validationProvider.NotEmpty(ids);

            //
            // Prepare Open Action Model ...
            var opaModel = new XOpenActionRequestDto
            {
                Payload = ids,
                Device = device,
                Action = XOpenActions.GetUserInfos,
                Timestamp = DateTime.UtcNow.AddMinutes(5).ToTimestamp().ToString()
            };
            if (!opaModel.Validate())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Fill Checksum Filed ...
            var token = opaModel.ToOpenActionToken();
            opaModel.Checksum = token;

            //
            // Prepare Request ...
            var opaJson = opaModel.ToJson();
            var requestString = SecurityProvider.Encrypt(opaJson);

            //
            return await GetUserInfos(
                token: token,
                request: requestString
            );
        }

        public async Task<IEnumerable<XOpenActionUserInfoDto>> GetUserInfos(
            XOpenActionInnerDto dto
        )
        {
            //
            return await GetUserInfos(
                token: dto.Token,
                request: dto.Payload
            );
        }

        public async Task<IEnumerable<XOpenActionUserInfoDto>> GetUserInfos(
            string token,
            string request
        )
        {
            //
            // Validate Args ...
            validationProvider.NotEmpty(token);
            validationProvider.NotEmpty(request);

            //
            // Retrieve and Validate Response ...
            var response = await OpenGet(
                token: token,
                actionRequest: request
            );
            if (response.IsNull() ||
                response.Token.IsNullOrEmpty() ||
                response.Payload.IsNullOrEmpty())
            {
                XException.ActionFailed.Throw();
            }

            //
            // Now we Have to Converts Repose Payload to Result Model ...
            // Note that the respose Model's payload here is Decrypted and
            // actually is Json Representation of Result Model ...
            var requestModel = response.Payload.FromJSON<XOpenActionRequestDto>();
            if (requestModel.IsNull())
            {
                XException.ActionFailed.Throw();
            }

            //
            var resultJson = SecurityProvider.Decrypt(requestModel.Payload);
            var result = resultJson.FromJSON<IEnumerable<XOpenActionUserInfoDto>>();
            if (result.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Partial\XIdentityProvider+Profile.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using xCommons.Extensions;
using xHttpService.Constants;
using xHttpService.Extensions;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
using xIdentityService.Constants;
using xModels.Dtos;

namespace xIdentityService.Providers {
    public partial class XIdentityProvider {
        //
        #region User Actions ...
        /// <summary>
        /// Retrieve User Names based on UserIds
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="ids">a comma seperated list of UserIds</param>
        /// <returns>a collection of UserNames</returns>
        public async Task<IEnumerable<string>> GetUserNames (
            XTokenResponse tokens,
            string ids
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotEmpty (ids, tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);
            var request = GetRestRequet (
                XApiAccountEndpoint.GetNames,
                @params : new Dictionary<string, string> { { XParam.XIds.GetStringValue (), ids } }
            );

            //
            var response = await RunRestRequest<IEnumerable<string>> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// get user ids and retrieve corresponding user names
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represent required UserIds collection</param>
        /// <returns>a collection of <see>XUserNameIdResponse</see> instance</returns>
        public async Task<IEnumerable<XUserNameIdResponse>> GetUserNameIds (
            XTokenResponse tokens,
            XUserNameIdRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (model, tokens)
                .AddNotZeroChilds (model.Ids)
                .AddNotEmpty (tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);
            var request = GetRestRequet (XApiAccountEndpoint.GetNameIds);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<IEnumerable<XUserNameIdResponse>> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }
        #endregion

        //
        #region Profile Actions ...
        /// <summary>
        /// Get Profile Object of Specific User 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> GetUserProfile (
            XTokenResponse tokens,
            string userSelectByParam
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotEmpty (userSelectByParam, tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.GetProfile,
                @params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam } }
            );

            //
            var response = await RunRestRequest<XUserProfileDto> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Retrieve Users Based On Query
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        public async Task<XQueryResult<XUserProfileDto>> QueryUsers (
            XTokenResponse tokens,
            XQuery query
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens, query)
                .AddNotEmpty (tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.QueryProfiles);

            //
            // Attach XQuery to Request ...
            request = request.AttachXQuery (query);

            //
            var response = await RunRestRequest<XQueryResult<XUserProfileDto>> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Retrieve Users Based On Query and Specified role
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="role">an string which represent user role</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <param name="forceRole">if it's true the user must has exact role, otherwise top level users also listed</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        public async Task<XQueryResult<XUserProfileDto>> QueryInRoleUsers (
            XTokenResponse tokens,
            string role,
            XQuery query,
            bool forceRole = false
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens, query)
                .AddNotEmpty (tokens.AccessToken, role)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.QueryProfiles,
                headers : new Dictionary<string, string> { { XParam.XRole.GetStringValue (), role },
                    { XParam.XForceRole.GetStringValue (), forceRole.AsHttpParamString () }
                }
            );

            //
            // Attach XQuery to Request ...
            request = request.AttachXQuery (query);

            //
            var response = await RunRestRequest<XQueryResult<XUserProfileDto>> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Query Specified User's Profile Images
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XProfileImage</see></returns>
        public async Task<XQueryResult<XProfileImage>> QueryAvatars (
            XTokenResponse tokens,
            string userSelectByParam,
            XQuery query
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens, query)
                .AddNotEmpty (tokens.AccessToken, userSelectByParam)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.QueryAvatars,
                @params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam }
                }
            );

            //
            // Attach XQuery to Request ...
            request = request.AttachXQuery (query);

            //
            var response = await RunRestRequest<XQueryResult<XProfileImage>> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Update User Profile based on <see>XProfileUpdateRequest</see> (FirstName/LastName/DateOfBirth)
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <param name="model">user update info, an instance of <see>XProfileUpdateRequest</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> ProfileUpdateAsync (
            XTokenResponse tokens,
            string userSelectByParam,
            XProfileUpdateRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens, model)
                .AddNotEmpty (tokens.AccessToken, userSelectByParam)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.UpdateProfile,
                @params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam }
                }
            );
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XUserProfileDto> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Update a User Profile based on <see>XProfileUpdateRequest</see> Full
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <param name="model">user update info, an instance of <see>XProfileUpdateRequest</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> FullProfileUpdateAsync (
            XTokenResponse tokens,
            string userSelectByParam,
            XProfileUpdateRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens, model)
                .AddNotEmpty (tokens.AccessToken, userSelectByParam)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.FullUpdateProfile,
                @params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam }
                }
            );
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XUserProfileDto> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Add a New Profile Image
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="file">an specific File to upload, <see>IFormFile</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> AddAvatar (
            XTokenResponse tokens,
            IFormFile file
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens, file)
                .AddNotEmpty (tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.AddAvatar);
            request.AlwaysMultipartFormData = true;
            request.AddFileBytes (
                XParam.XFile.GetStringValue (),
                file.ToByteArray (),
                file.FileName,
                file.ContentType
            );

            //
            var response = await RunRestRequest<XUserProfileDto> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Add a New Collection of Profile Images
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="files">a collection of Files to upload, <see>IFormFileCollection</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> AddAvatars (
            XTokenResponse tokens,
            IFormFileCollection files
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotZeroChilds (files)
                .AddNotEmpty (tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.AddAvatars);
            request.AlwaysMultipartFormData = true;

            //
            // Add Files ...
            foreach (var file in files) {
                //
                // Add Single file ...
                request.AddFileBytes (
                    XParam.XFiles.GetStringValue (),
                    file.ToByteArray (),
                    file.FileName,
                    file.ContentType
                );
            }

            //
            var response = await RunRestRequest<XUserProfileDto> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// set Specified Profile Image as Avatar
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="id">an integer which reperesent AvatarId to set as current Avatar</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> SetAvatar (
            XTokenResponse tokens,
            int id
        ) {
            //
            // Validate Args ...
            id.ValidateIntId ();

            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotEmpty (tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.SetAvatar,
                @params : new Dictionary<string, string> { { XParam.XId.GetStringValue (), id.ToString () }
                }
            );

            //
            var response = await RunRestRequest<XUserProfileDto> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Remove Profile Images
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="avatarIds">a comma seperated list of avatarIds to remove</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> RemoveAvatars (
            XTokenResponse tokens,
            string avatarIds
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotEmpty (avatarIds, tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.RemoveAvatars,
                @params : new Dictionary<string, string> { { XParam.XIds.GetStringValue (), avatarIds }
                }
            );

            //
            var response = await RunRestRequest<XUserProfileDto> (
                client,
                request,
                XHttpMethod.DELETE
            );
            return response;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Partial\XIdentityProvider+Registration.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using xCommons.Extensions;
using xExceptions.Constants;
using xHttpService.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityService.Constants;

namespace xIdentityService.Providers {
    public partial class XIdentityProvider {
        //
        #region Registration ...
        /// <summary>
        /// Check a User Selector is Available for Registration or Not
        /// </summary>
        /// <param name="userSelectByParam">an string value which reperesent a user</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> CanRegister (string userSelectByParam) {
            //
            // Validate ARgs ...
            validationProvider.NotEmpty (userSelectByParam);

            //
            var client = GetRestClient ();

            //
            // Check Endpoint ...
            var endpoint = XApiAccountEndpoint.CanRegisterUserName;
            var @params = new Dictionary<string, string> { { XParam.XUserName.GetStringValue (), userSelectByParam } };

            //
            // Check UserSelectByType ...
            var type = userSelectByParam.GetUserSelectByType ();
            switch (type) {
                //
                case XUserSelectBy.Username:
                    break;

                    //
                case XUserSelectBy.MobileNumber:
                    //
                    endpoint = XApiAccountEndpoint.CanRegisterMobileNumber;
                    @params = new Dictionary<string, string> { { XParam.XMobileNumber.GetStringValue (), userSelectByParam } };
                    break;

                    //
                case XUserSelectBy.Email:
                    //
                    endpoint = XApiAccountEndpoint.CanRegisterEmail;
                    @params = new Dictionary<string, string> { { XParam.XEmail.GetStringValue (), userSelectByParam } };
                    break;

                    //
                default:
                    throw XException.InvalidData.ToException ();
            }

            //
            var request = GetRestRequet (
                endpoint,
                @params: @params
            );

            //
            var response = await RunRestRequest<bool> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Invite a User to Register on Dashboard
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> InviteUser (
            XTokenResponse tokens,
            XActionRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (
                    tokens,
                    model,
                    model.Device)
                .AddNotEmpty (
                    tokens.AccessToken,
                    model.Lang,
                    model.Email,
                    model.ReturnUrl)
                .AddEmailAddress (model.Email)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.InviteUser);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Recieve some Basic Informations and Start Registration Proccess
        /// if they Valid 
        /// 
        /// Registration Proccess Starts with Invoking this Action
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> RequestRegistration (
            XActionRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (
                    model,
                    model.Device,
                    model.DateOfBirth)
                .AddNotEmpty (
                    model.Lang,
                    model.FirstName,
                    model.LastName)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.RequestRegistration);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Add User Account Informations
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> AddAccountInfo (
            XActionRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (
                    model,
                    model.Device)
                .AddNotEmpty (
                    model.Lang,
                    model.UserName,
                    model.Password,
                    model.ActionToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.AddAccountInfo);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Upload and Attach a Profile Image for User. this is an Optional Step
        /// </summary>
        /// <param name="actionToken">user's requested action token</param>
        /// <param name="file">an instance of <see>IFormFile</see> for user's Avatar</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> AttachProfileImage (
            string actionToken,
            IFormFile file
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (file)
                .AddNotEmpty (actionToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.AttachProfileImage);

            //
            // Prepare Request Data ...
            request.AddParameter (XParam.XActionToken.GetStringValue (), actionToken);
            request.AddFileBytes (
                XParam.XFile.GetStringValue (),
                file.ToByteArray (),
                file.FileName,
                file.ContentType
            );

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Finish Registrationn Proccess 
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        public async Task FinishRegistration (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.Password,
                    model.ReturnUrl)
                .AddNotNull (model.Device)
                .AddUrl (model.ReturnUrl)
                .ValidateGroupAsync ();

            //
            // Create Http Client ...
            var client = GetRestClient ();

            //
            // Create Request ...
            var request = GetRestRequet (XApiAccountEndpoint.FinishRegistration);

            //
            // Prepare Request Data ...
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<object> (
                client,
                request,
                XHttpMethod.POST
            );
        }

        /// <summary>
        /// Check User is Confirmed Email or not
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="userSelectByParam">an string value which reperesent a user</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsConfirmedEmail (
            XTokenResponse tokens,
            string userSelectByParam
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotEmpty (
                    tokens.AccessToken,
                    userSelectByParam)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.IsConfirmedEmail);

            //
            var response = await RunRestRequest<bool> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Check User is Confirmed Mobile or not
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="userSelectByParam">an string value which reperesent a user</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsConfirmedMobile (
            XTokenResponse tokens,
            string userSelectByParam
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotEmpty (
                    tokens.AccessToken,
                    userSelectByParam)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.IsConfirmedMobile);

            //
            var response = await RunRestRequest<bool> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Request Registration Confirm
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        public async Task RequestConfirmRegistration (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.Password,
                    model.ReturnUrl)
                .AddNotNull (model.Device)
                .AddUrl (model.ReturnUrl)
                .ValidateGroupAsync ();

            //
            // Get UserSelect By Param ...
            var userSelectByParam = model.GetUserSelectByParam ();
            validationProvider.NotEmpty (userSelectByParam);

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.RequestConfirmRegistration);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<object> (
                client,
                request,
                XHttpMethod.POST
            );
        }

        /// <summary>
        /// Confirm Registration
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        public async Task ConfirmRegistration (
            XActionRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.ActionToken,
                    model.ReturnUrl
                )
                .AddNotNull (model.Device)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.ConfirmRegistration);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<object> (
                client,
                request,
                XHttpMethod.POST
            );
        }

        /// <summary>
        /// Request For Mobile Number Change/Confirm 
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> RequestConfirmMobile (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.Password,
                    model.MobileNumber
                )
                .AddNotNull (model.Device)
                .AddMobileNumber (model.MobileNumber)
                .ValidateGroupAsync ();

            //
            // Get UserSelect By Param ...
            var userSelectByParam = GetUserSelectByParam (
                model,
                excludes : new List<XUserSelectBy> {
                    XUserSelectBy.Email,
                    XUserSelectBy.MobileNumber
                });

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.RequestConfirmMobile);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Confirm Requested Mobile Number
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> ConfirmMobileNumber (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.ActionToken,
                    model.MobileVerificationCode
                )
                .AddNotNull (model.Device)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.ConfirmMobileNumber);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Request For Email Address Change/Confirm 
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> RequestConfirmEmail (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.Email,
                    model.Password)
                .AddNotNull (model.Device)
                .AddEmailAddress (model.Email)
                .ValidateGroupAsync ();

            //
            // Get UserSelect By Param ...
            var userSelectByParam = GetUserSelectByParam (
                model,
                excludes : new List<XUserSelectBy> {
                    XUserSelectBy.Email,
                    XUserSelectBy.MobileNumber
                });

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.RequestConfirmEmail);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Confirm Requested Email Address
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> ConfirmEmailAddress (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.ActionToken,
                    model.EmailVerificationCode
                )
                .AddNotNull (model.Device)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.ConfirmEmailAddress);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Request Reset Password Action
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> RequestResetPassword (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.ReturnUrl)
                .AddNotNull (model.Device)
                .AddUrl (model.ReturnUrl)
                .ValidateGroupAsync ();

            //
            // Get UserSelect By Param ...
            var userSelectByParam = GetUserSelectByParam (
                model,
                excludes : new List<XUserSelectBy> {
                    XUserSelectBy.Email,
                    XUserSelectBy.MobileNumber
                });

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.RequestResetPassword);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Reset a User's Password
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        public async Task ResetPassword (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (model)
                .AddNotEmpty (
                    model.Lang,
                    model.ActionToken,
                    model.NewPassword,
                    model.ReturnUrl)
                .AddNotNull (model.Device)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.ResetPassword);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<object> (
                client,
                request,
                XHttpMethod.POST
            );
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Partial\XIdentityProvider+Search.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using xHttpService.Constants;
using xHttpService.Extensions;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityService.Constants;
using xModels.Dtos;

namespace xIdentityService.Providers
{
    public partial class XIdentityProvider
    {
        //
        #region Actions ...
        /// <summary>
        /// Query Open To Search User Profiles ...
        /// </summary>
        /// <param name="tokens">requested user's identifiers</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        public async Task<XQueryResult<XUserProfileDto>> QueryOpenToSearchUsers(
            XTokenResponse tokens,
            XQuery query
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens, query)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.QueryOpenToSearchProfiles);

            //
            // Attach XQuery to Request ...
            request = request.AttachXQuery(query);

            //
            var response = await RunRestRequest<XQueryResult<XUserProfileDto>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Providers\XBaseIdentityHttpProvider.cs

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using RestSharp;
using RestSharp.Authenticators;
using xCommons.Constants;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xHttpService.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityService.Constants;
using xIdentityService.Interfaces;
using xIdentityService.Models;
using xIdentityService.Extensions;
using System.Diagnostics.Tracing;
using MySqlX.XDevAPI.Common;

namespace xIdentityService.Providers
{
    /// <summary>
    /// an abstraction Implementation for Identity Provided Http Based Services ...
    /// </summary>
    public abstract class XBaseIdentityHttpProvider : IXBaseIdentityHttpProvider
    {
        /// <summary>
        /// Client Base Url ...
        /// </summary>
        /// <value></value>
        public string BaseUrl { get; }

        /// <summary>
        /// Logger ...
        /// </summary>
        /// <value></value>
        public ILogger Logger { get; }

        /// <summary>
        /// Powered Value ...
        /// </summary>
        /// <value></value>
        public string XPoweredValue { get; }

        /// <summary>
        /// Default Client Timeout ...
        /// </summary>
        /// <value></value>
        public int DefaultClientTimeout { get; }

        /// <summary>
        /// Default Buffering Chunk Size ...
        /// </summary>
        /// <value></value>
        public int DefaultBufferingChunckSize { get; }

        /// <summary>
        /// Validation Provider ...
        /// </summary>
        /// <value></value>
        public XValidationProvider ValidationProvider { get; }

        /// <summary>
        /// Token Provider ...
        /// </summary>
        private readonly IXTokenProvider tokenProvider;

        /// <summary>
        /// Identity Provider ...
        /// </summary>
        private readonly IXIdentityProvider identityProvider;

        public XBaseIdentityHttpProvider(
            string baseUrl,
            ILogger logger,
            string poweredValue,
            int defaultClientTimeout,
            IXTokenProvider tokenProvider,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            int defaultBufferingChunckSize = 8192
        )
        {
            //
            Logger = logger;
            BaseUrl = baseUrl;
            XPoweredValue = poweredValue;
            this.tokenProvider = tokenProvider;
            ValidationProvider = validationProvider;
            this.identityProvider = identityProvider;
            DefaultClientTimeout = defaultClientTimeout;
            DefaultBufferingChunckSize = defaultBufferingChunckSize;
        }

        //
        #region Tools ...
        /// <summary>
        /// Get an Instance of Http Client 
        /// </summary>
        /// <returns></returns>
        public HttpClient GetHttpClient(XTokenResponse tokens = null)
        {
            //
            HttpClient httpClient = null;

            //
            // httpClient = new HttpClient ();
            var httpClientHandler = new HttpClientHandler()
            {
                ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) =>
                {
                    //
                    Logger.LogInformation(
                        $"XSSL Handler: {Environment.NewLine}, sender: {sender}, {Environment.NewLine} cert: {cert}, {Environment.NewLine} chain: {chain}, {Environment.NewLine} sslPolicyErrors: {sslPolicyErrors}"
                    );

                    //
                    return true;
                },
                ClientCertificateOptions = ClientCertificateOption.Manual,
            };
            httpClient = new HttpClient(httpClientHandler);

            //
            // Set Authenticator ...
            if (!tokens.IsNull() &&
                !tokens.AccessToken.IsNullOrEmpty())
            {
                //
                httpClient.DefaultRequestHeaders
                    .Add(
                        XAuthorization.Header,
                        $"{XAuthentication.BEARER} {tokens.AccessToken}");
            }

            //
            // Refresh Token ...
            if (!tokens.IsNull() &&
                !tokens.RefreshToken.IsNullOrEmpty())
            {
                //
                httpClient.DefaultRequestHeaders
                    .Add(
                        XAuthorization.RefreshToken,
                        tokens.RefreshToken);
            }

            //
            // ExpiresAt ...
            if (!tokens.IsNull() &&
                tokens.ExpiresAt > 0)
            {
                //
                httpClient.DefaultRequestHeaders
                    .Add(
                        XAuthorization.ExpiresAt,
                        tokens.ExpiresAt.AsHttpParamString());
            }

            //
            // Set Default Timeout ...
            httpClient.Timeout = TimeSpan.FromSeconds(DefaultClientTimeout == -1 ? 10000 : DefaultClientTimeout);

            //
            return httpClient;
        }
        public HttpClient GetHttpClient(XUserClaimsInfoDto userInfo = null)
        {
            //
            XTokenResponse tokens = ToTokenResponse(userInfo);

            //
            return GetHttpClient(tokens);
        }

        /// <summary>
        /// Get an Instance of RestClient
        /// </summary>
        /// <returns></returns>
        public RestClient GetRestClient(XTokenResponse tokens = null)
        {
            //
            var client = new RestClient(BaseUrl);

            //
            // Set Authenticator ...
            if (!tokens.IsNull() &&
                !tokens.AccessToken.IsNullOrEmpty())
            {
                client.Authenticator = new JwtAuthenticator(tokens.AccessToken);
            }

            //
            // Refresh Token ...
            if (!tokens.IsNull() &&
                !tokens.RefreshToken.IsNullOrEmpty())
            {
                client.AddDefaultHeader(XAuthorization.RefreshToken, tokens.RefreshToken);
            }

            //
            // ExpiresAt ...
            if (!tokens.IsNull() &&
                tokens.ExpiresAt > 0)
            {
                client.AddDefaultHeader(XAuthorization.ExpiresAt, tokens.ExpiresAt.AsHttpParamString());
            }

            //
            // Set Default Timeout ...
            client.Timeout = DefaultClientTimeout;

            //
            // SSL Validation Handler ...
            client.RemoteCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) =>
            {
                //
                Logger.LogInformation(
                    $"XSSL Handler: {Environment.NewLine}, sender: {sender}, {Environment.NewLine} cert: {cert}, {Environment.NewLine} chain: {chain}, {Environment.NewLine} sslPolicyErrors: {sslPolicyErrors}"
                );

                //
                return true;
            };

            //
            return client;
        }
        public RestClient GetRestClient(XUserClaimsInfoDto userInfo = null)
        {
            //
            XTokenResponse tokens = ToTokenResponse(userInfo);

            //
            return GetRestClient(tokens);
        }

        /// <summary>
        /// Get an Instance of RestRequest 
        /// </summary>
        /// <param name="endpoint"></param>
        /// <param name="addXPoweredValue"></param>
        /// <param name=""></param>
        /// <param name="headers"></param>
        /// <param name="queryStrings"></param>
        /// <returns></returns>
        public RestRequest GetRestRequet(
            Enum endpoint,
            bool addXPoweredValue = true,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> headers = null,
            IDictionary<string, string> queryStrings = null
        )
        {
            //
            var url = PrepareUrl(
                @params: @params,
                endpoint: endpoint,
                queryStrings: queryStrings
            );

            //
            // Create request ...
            var request = new RestRequest(url, DataFormat.Json);

            //
            if (addXPoweredValue)
            {
                request.AddHeader(XAuthorization.XPoweredBy, XPoweredValue);
            }

            //
            // Add Headers to request ...
            if (!headers.IsNull() && headers.Count > 0)
            {
                //
                var enumerator = headers.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    //
                    var item = enumerator.Current;
                    request.AddHeader(item.Key, item.Value);
                }
            }

            //
            return request;
        }

        /// <summary>
        /// Handle Call Specific Request and retrieve Response
        /// </summary>
        /// <param name="client"></param>
        /// <param name="request"></param>
        /// <param name="method"></param>
        /// <param name="supportRefreshingTokens"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task<T> RunRestRequest<T>(
            RestClient client,
            RestRequest request,
            XHttpMethod method,
            bool supportRefreshingTokens = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var response = await Task.Run(async () =>
            {
                //
                IRestResponse resp = null;

                //
                // Call Endpoint Service using Specified Method ...
                switch (method)
                {
                    //
                    // Get ...
                    case XHttpMethod.GET:
                        resp = client.Get(request);
                        break;

                    //
                    // Put ...
                    case XHttpMethod.PUT:
                        resp = client.Put(request);
                        break;

                    //
                    // Post ...
                    case XHttpMethod.POST:
                        resp = client.Post(request);
                        break;

                    //
                    // Delete ...
                    case XHttpMethod.DELETE:
                        resp = client.Delete(request);
                        break;
                }

                //
                if (!resp.IsSuccessful)
                {
                    //
                    // Log Exception ...
                    Logger.LogError($"Error: {resp.ErrorMessage}");
                    Logger.LogError($"Exception: {resp.ErrorException.ToJSON()}");
                    if (!resp.ErrorMessage.IsNullOrEmpty() &&
                        resp.ErrorMessage.Contains("timed out"))
                    {
                        XException.Timeout.Throw();
                    }

                    //
                    // TODO: Check UnAuthorized Status here for
                    // Refresh Tokens or Issue Correct Exception ...
                    if (supportRefreshingTokens &&
                        resp.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                    {
                        //
                        var isRefreshed = request.Parameters.Any(rp =>
                            rp.Name == XParam.XIsRefreshed.GetStringValue() &&
                            rp.Value.ToString().ToNormalString() == true.ToJSON());

                        //
                        Logger.LogInformation($"isRefreshed: {isRefreshed}");

                        //
                        // Get Access Token ...
                        XTokenResponse tokens = null;
                        var accessToken = request.Parameters.FirstOrDefault(rp =>
                            rp.Name.ToNormalString() == XAuthorization.Header.ToNormalString()).Value.ToString();
                        if (!accessToken.IsNullOrEmpty())
                        {
                            //
                            accessToken = accessToken.Replace(XAuthorization.TokenIdentifier, "");

                            //
                            if (!accessToken.IsNullOrEmpty())
                            {
                                tokens = await tokenProvider.RetrieveToken(accessToken);
                            }
                        }

                        //
                        // Refresh Token and then re do request ...
                        if (!isRefreshed &&
                            !accessToken.IsNullOrEmpty() &&
                            !tokens.IsNull() &&
                            tokens.IsRefreshable())
                        {
                            //
                            request.AddHeader(XParam.XIsRefreshed.GetStringValue(), true.ToJSON());

                            //
                            // Refreshe Tokens ...
                            var refreshedTokens = await identityProvider
                                .RefreshTokens(tokens);

                            //
                            // Renew Rest Client with Refreshed Tokens ...
                            var timeout = client.Timeout;
                            client = GetRestClient(refreshedTokens);
                            client.Timeout = Timeout.Infinite;

                            //
                            // Do Request Again using renew Client ...
                            return await RunRestRequest<T>(
                                client: client,
                                request: request,
                                method: method);
                        }
                    }

                    //
                    var ex = resp.Content.ToXError();
                    if (!ex.IsNull())
                    {
                        throw ex.ToException();
                    }

                    //
                    // UnAuthorized ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                    {
                        XException.NotAuthorized.Throw();
                    }

                    //
                    // NotFound ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.NotFound)
                    {
                        XException.NotFound.Throw();
                    }

                    //
                    XException.ActionFailed.Throw();
                }

                //
                var result = resp.Content.FromJSON<T>();
                return result;
            },
            cancellationToken: cancellationToken);

            //
            return response;
        }

        /// <summary>
        /// Access a Get Request Stream as AsyncEnumerable ... 
        /// </summary>
        /// <param name="endpoint"></param>
        /// <param name="bufferLength"></param>
        /// <param name="addXPoweredValue"></param>
        /// <param name="tokens"></param>
        /// <param name="@params"></param>
        /// <param name="headers"></param>
        /// <param name="queryStrings"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task<Stream> StreamData(
            Enum endpoint,
            int bufferLength = 8194,
            bool addXPoweredValue = true,
            XTokenResponse tokens = null,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> headers = null,
            IDictionary<string, string> queryStrings = null,
            [System.Runtime.CompilerServices.EnumeratorCancellation]
            CancellationToken cancellationToken = default
        )
        {
            //
            var url = PrepareUrl(
                @params: @params,
                endpoint: endpoint,
                attachBaseUrl: true,
                queryStrings: queryStrings
            );
            var client = GetHttpClient(tokens);
            if (addXPoweredValue)
            {
                //
                client.DefaultRequestHeaders
                    .Add(
                        XAuthorization.XPoweredBy,
                        XPoweredValue
                );
            }

            //
            // For SSE, you might want to set the Accept header, though not strictly necessary for just streaming
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept
                .Add(
                    new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("text/event-stream"));

            //
            var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
            response.EnsureSuccessStatusCode();

            //
            var stream = await response.Content.ReadAsStreamAsync();

            //
            return stream;

            // using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellationToken))
            // {
            //     //
            //     int readedBuffers = 0;
            //     response.EnsureSuccessStatusCode();
            //     var buffer = new byte[bufferLength];
            //     var stream = await response.Content.ReadAsStreamAsync();

            //     //
            //     while ((readedBuffers = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
            //     {
            //         //
            //         var content = buffer.FromBytes();
            //         Console.WriteLine(content);
            //     }

            //     // await foreach (var message in stream) {
            //     //     Console.WriteLine(message);
            //     // }

            //     // await foreach (var item in stream.ToAsyncEnumerable<byte[]>(cancellationToken: cancellationToken))
            //     // {
            //     //     //
            //     //     Console.WriteLine(item);

            //     //     // T value = item.IsNull()
            //     //     // ? default(T)
            //     //     // : item.FromBytes().FromJSON<T>();

            //     //     // //
            //     //     // yield return value;
            //     // }
            // }

            ///
            /// 
            /// 
            ///             

            //
            // var eventSource = new EventSource(url);
            // // eventSource.

            // // var client = GetHttpClient(tokens);
            // // if (addXPoweredValue)
            // // {
            // //     //
            // //     client.DefaultRequestHeaders
            // //         .Add(
            // //             XAuthorization.XPoweredBy,
            // //             XPoweredValue);
            // // }

            // // //
            // // // For SSE, you might want to set the Accept header, though not strictly necessary for just streaming
            // // client.DefaultRequestHeaders.Accept.Clear();
            // // client.DefaultRequestHeaders.Accept
            // //     .Add(
            // //         new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("text/event-stream"));

            // // //
            // // using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellationToken))
            // // {
            // //     //
            // //     response.EnsureSuccessStatusCode();
            // //     var stream = await response.Content.ReadAsStreamAsync();
            // //     await foreach (var item in stream.ToAsyncEnumerable<byte[]>(cancellationToken: cancellationToken))
            // //     {
            // //         //
            // //         T value = item.IsNull() 
            // //         ? default(T)
            // //         : item.FromBytes().FromJSON<T>();

            // //         //
            // //         yield return value;
            // //     }
            // // }
        }

        /// <summary>
        /// Handle Call Specified Request and Retrieve XBaseRestResponse<T> ...
        /// </summary>
        /// <param name="client"></param>
        /// <param name="request"></param>
        /// <param name="method"></param>
        /// <param name="supportRefreshingTokens"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns>an instance of XBaseRestResponse<T></returns>
        public async Task<XBaseRestResponse<T>> RunRestRequestByResponse<T>(
            RestClient client,
            RestRequest request,
            XHttpMethod method,
            bool supportRefreshingTokens = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var response = await Task.Run(async () =>
            {
                //
                IRestResponse resp = null;

                //
                // Call Endpoint Service using Specified Method ...
                switch (method)
                {
                    //
                    // Get ...
                    case XHttpMethod.GET:
                        resp = client.Get(request);
                        break;

                    //
                    // Put ...
                    case XHttpMethod.PUT:
                        resp = client.Put(request);
                        break;

                    //
                    // Post ...
                    case XHttpMethod.POST:
                        resp = client.Post(request);
                        break;

                    //
                    // Delete ...
                    case XHttpMethod.DELETE:
                        resp = client.Delete(request);
                        break;
                }

                //
                if (!resp.IsSuccessful)
                {
                    //
                    // Log Exception ...
                    Logger.LogError($"Error: {resp.ErrorMessage}");
                    Logger.LogError($"Exception: {resp.ErrorException.ToJSON()}");
                    if (!resp.ErrorMessage.IsNullOrEmpty() &&
                        resp.ErrorMessage.Contains("timed out"))
                    {
                        XException.Timeout.Throw();
                    }

                    //
                    // TODO: Check UnAuthorized Status here for
                    // Refresh Tokens or Issue Correct Exception ...
                    if (supportRefreshingTokens &&
                        resp.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                    {
                        //
                        var isRefreshed = request.Parameters.Any(rp =>
                            rp.Name == XParam.XIsRefreshed.GetStringValue() &&
                            rp.Value.ToString().ToNormalString() == true.ToJSON());

                        //
                        Logger.LogInformation($"isRefreshed: {isRefreshed}");

                        //
                        // Get Access Token ...
                        XTokenResponse tokens = null;
                        var accessToken = request.Parameters.FirstOrDefault(rp =>
                            rp.Name.ToNormalString() == XAuthorization.Header.ToNormalString()).Value.ToString();
                        if (!accessToken.IsNullOrEmpty())
                        {
                            //
                            accessToken = accessToken.Replace(XAuthorization.TokenIdentifier, "");

                            //
                            if (!accessToken.IsNullOrEmpty())
                            {
                                tokens = await tokenProvider.RetrieveToken(accessToken);
                            }
                        }

                        //
                        // Refresh Token and then re do request ...
                        if (!isRefreshed &&
                            !accessToken.IsNullOrEmpty() &&
                            !tokens.IsNull() &&
                            tokens.IsRefreshable())
                        {
                            //
                            request.AddHeader(XParam.XIsRefreshed.GetStringValue(), true.ToJSON());

                            //
                            // Refreshe Tokens ...
                            var refreshedTokens = await identityProvider
                                .RefreshTokens(tokens);

                            //
                            // Renew Rest Client with Refreshed Tokens ...
                            var timeout = client.Timeout;
                            client = GetRestClient(refreshedTokens);
                            client.Timeout = Timeout.Infinite;

                            //
                            // Do Request Again using renew Client ...
                            return await RunRestRequestByResponse<T>(
                                client: client,
                                request: request,
                                method: method
                            );
                        }
                    }

                    //
                    var ex = resp.Content.ToXError();
                    if (!ex.IsNull())
                    {
                        throw ex.ToException();
                    }

                    //
                    // UnAuthorized ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                    {
                        XException.NotAuthorized.Throw();
                    }

                    //
                    // NotFound ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.NotFound)
                    {
                        XException.NotFound.Throw();
                    }

                    //
                    XException.ActionFailed.Throw();
                }

                //
                var result = new XBaseRestResponse<T>
                {
                    Response = resp,
                    Model = resp.Content.FromJSON<T>()
                };

                //
                return result;
            },
            cancellationToken: cancellationToken);

            //
            return response;
        }

        /// <summary>
        /// Get User SelectBy Param 
        /// </summary>
        /// <param name="model"></param>
        /// <param name="forceNotNull"></param>
        /// <param name="excludes"></param>
        /// <returns></returns>
        public string GetUserSelectByParam(
            XActionRequest model,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(model);

            //
            var id = model.UserId;
            var userName = model.UserName;
            var email = model.Email;
            var phoneNumber = model.MobileNumber;

            //
            if (excludes != null)
            {
                //
                if (excludes.Contains(XUserSelectBy.ID))
                {
                    id = null;
                }
                if (excludes.Contains(XUserSelectBy.Email))
                {
                    email = null;
                }
                if (excludes.Contains(XUserSelectBy.MobileNumber))
                {
                    phoneNumber = null;
                }
                if (excludes.Contains(XUserSelectBy.Username))
                {
                    userName = null;
                }
            }

            var selectByParam =
                id.IsNullOrEmpty() ?
                userName.IsNullOrEmpty() ?
                email.IsNullOrEmpty() ?
                phoneNumber.IsNullOrEmpty() ? null : phoneNumber : email : userName : id;

            //
            // Check result ...
            if (forceNotNull &&
                selectByParam.IsNullOrEmpty())
            {
                XException.InvalidData.Throw();
            }

            //
            return selectByParam;
        }

        /// <summary>
        /// Prepare Url Address of Specified Enum by Filling Params
        /// and Query Strings Attach ...
        /// </summary>
        /// <param name="endpoint"></param>
        /// <param name="attachBaseUrl"></param>
        /// <param name="@params"></param>
        /// <param name="queryStrings"></param>
        /// <returns></returns>
        public string PrepareUrl(
            Enum endpoint,
            bool attachBaseUrl = false,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> queryStrings = null
        )
        {
            //
            // Retrieving Url Template ...
            var url = endpoint.GetStringValue();

            //
            // Filling Parmas and Query Strings of Url ...
            url = PrepareUrl(
                url: url,
                @params: @params,
                queryStrings: queryStrings,
                attachBaseUrl: attachBaseUrl
            );

            //
            return url;
        }

        /// <summary>
        /// Prepare Url Address by Filling Params
        /// and Query Strings Attach ...
        /// </summary>
        /// <param name="url"></param>
        /// <param name="attachBaseUrl"></param>
        /// <param name="@params"></param>
        /// <param name="queryStrings"></param>
        /// <returns></returns>
        public string PrepareUrl(
            string url,
            bool attachBaseUrl = false,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> queryStrings = null
        )
        {
            //
            if (attachBaseUrl)
            {
                //
                var baseUrl = BaseUrl;
                if (!baseUrl.EndsWith("/"))
                {
                    baseUrl = $"{baseUrl}/";
                }

                //
                url = $"{baseUrl}{url}";
            }

            //
            // Add Route Payloads ...
            if (!@params.IsNull() && @params.Count > 0)
            {
                //
                var enumerator = @params.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    //
                    var item = enumerator.Current;

                    //
                    url = url.Replace(item.Key, item.Value.ToUrlEncoded());
                }
            }

            //
            // Add Query Strings ...
            if (!queryStrings.IsNull() && queryStrings.Count > 0)
            {
                //
                url = $"{url}?";
                var enumerator = queryStrings.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    //
                    var item = enumerator.Current;

                    //
                    url += $"{item.Key}={item.Value.ToUrlEncoded()}&";
                }

                //
                // remove lates & ...
                if (url.EndsWith("&"))
                {
                    url = url.Substring(0, url.Length - 1);
                }
            }

            //
            return url;
        }

        /// <summary>
        /// Converts UserInfo to TokenResponse model ...
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public XTokenResponse ToTokenResponse(XUserClaimsInfoDto userInfo = null)
        {
            //
            XTokenResponse result = null;

            //
            if (!userInfo.IsNull())
            {
                //
                result = new XTokenResponse
                {
                    AccessToken = userInfo.AccessToken.IsNullOrEmpty()
                        ? ""
                        : userInfo.AccessToken,
                    RefreshToken = userInfo.RefreshToken.IsNullOrEmpty()
                        ? ""
                        : userInfo.RefreshToken,
                    ExpiresAt = userInfo.ExpiresAt,
                };

                //
                if (userInfo.AccessToken.IsNullOrEmpty())
                {
                    result = null;
                }
            }

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Providers\XIdentityProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using RestSharp;
using RestSharp.Authenticators;
using xCommons.Constants;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xHttpService.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityService.Configuration;
using xIdentityService.Constants;
using xIdentityService.Interfaces;
using xIdentityService.Models;

namespace xIdentityService.Providers {
    public partial class XIdentityProvider : IXIdentityProvider {
        private readonly IXTokenProvider tokenProvider;
        private readonly IHostingEnvironment environment;
        private JsonSerializerSettings jsonSerializerSettings;
        private readonly XValidationProvider validationProvider;
        private readonly XIdentityServiceConfiguration identityConfiguration;

        public ILogger<XIdentityProvider> Logger { get; }
        public IXSecurityProvider SecurityProvider { get; }

        public string BaseUrl { get; }
        public string RevisionSecretKey { get; }
        public bool ReadResponseAsString { get; set; }

        public XIdentityProvider (
            IXTokenProvider tokenProvider,
            IHostingEnvironment environment,
            ILogger<XIdentityProvider> logger,
            IXSecurityProvider securityProvider,
            XIdentityServiceConfiguration identityConfiguration,
            XValidationProvider validationProvider
        ) {
            //
            BaseUrl = identityConfiguration.Authority;
            RevisionSecretKey = identityConfiguration.XRevisionSecretKey;

            //
            this.environment = environment;
            Logger = logger;
            SecurityProvider = securityProvider;

            //
            this.identityConfiguration = identityConfiguration;
            this.validationProvider = validationProvider;
            this.jsonSerializerSettings = new JsonSerializerSettings {
                ContractResolver = new CamelCasePropertyNamesContractResolver ()
            };

            //
            this.tokenProvider = tokenProvider;
        }

        //
        #region Tools ...
        /// <summary>
        /// Get an Instance of Http Client 
        /// </summary>
        /// <returns></returns>
        public HttpClient GetHttpClient () {
            //
            HttpClient httpClient = null;

            //
            // httpClient = new HttpClient ();
            var httpClientHandler = new HttpClientHandler () {
                ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => {
                        //
                        Logger.LogInformation (
                            $"XSSL Handler: {Environment.NewLine}, sender: {sender}, {Environment.NewLine} cert: {cert}, {Environment.NewLine} chain: {chain}, {Environment.NewLine} sslPolicyErrors: {sslPolicyErrors}"
                        );

                        //
                        return true;
                    },
                    ClientCertificateOptions = ClientCertificateOption.Manual,
            };
            httpClient = new HttpClient (httpClientHandler);

            //
            // Set Timeout ...
            // TODO: Fix this ...
            // httpClient.Timeout = TimeSpan
            //     .FromSeconds (identityConfiguration.DefaultClientTimeout);

            //
            return httpClient;
        }

        /// <summary>
        /// Get an Instance of RestClient
        /// </summary>
        /// <returns></returns>
        public RestClient GetRestClient (XTokenResponse tokens = null) {
            //
            var client = new RestClient (BaseUrl);

            //
            // Set Authenticator ...
            if (!tokens.IsNull () &&
                !tokens.AccessToken.IsNullOrEmpty ()) {
                client.Authenticator = new JwtAuthenticator (tokens.AccessToken);
            }

            //
            // Refresh Token ...
            if (!tokens.IsNull () &&
                !tokens.RefreshToken.IsNullOrEmpty ()) {
                client.AddDefaultHeader (XAuthorization.RefreshToken, tokens.RefreshToken);
            }

            //
            // ExpiresAt ...
            if (!tokens.IsNull () &&
                tokens.ExpiresAt > 0) {
                client.AddDefaultHeader (XAuthorization.ExpiresAt, tokens.ExpiresAt.AsHttpParamString ());
            }

            //
            // Set Default Timeout ...
            client.Timeout = identityConfiguration.DefaultClientTimeout;

            //
            // SSL Validation Handler ...
            client.RemoteCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => {
                //
                Logger.LogInformation (
                    $"XSSL Handler: {Environment.NewLine}, sender: {sender}, {Environment.NewLine} cert: {cert}, {Environment.NewLine} chain: {chain}, {Environment.NewLine} sslPolicyErrors: {sslPolicyErrors}"
                );

                //
                return true;
            };

            //
            return client;
        }

        /// <summary>
        /// Get an Instance of RestRequest 
        /// </summary>
        public RestRequest GetRestRequet (
            XApiAccountEndpoint endpoint,
            bool addXPoweredValue = true,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> headers = null,
            IDictionary<string, string> queryStrings = null
        ) {
            //
            var url = endpoint.GetStringValue ();

            //
            // Add Route Payloads ...
            if (!@params.IsNull () && @params.Count > 0) {
                //
                var enumerator = @params.GetEnumerator ();
                while (enumerator.MoveNext ()) {
                    //
                    var item = enumerator.Current;

                    //
                    url = url.Replace (item.Key, item.Value.ToUrlEncoded ());
                }
            }

            //
            // Add Query Strings ...
            if (!queryStrings.IsNull () && queryStrings.Count > 0) {
                //
                url = $"{url}?";
                var enumerator = queryStrings.GetEnumerator ();
                while (enumerator.MoveNext ()) {
                    //
                    var item = enumerator.Current;

                    //
                    url += $"{item.Key}={item.Value.ToUrlEncoded ()}&";
                }

                //
                // remove lates & ...
                if (url.EndsWith ("&")) {
                    url = url.Substring (0, url.Length - 1);
                }
            }

            //
            // Create request ...
            var request = new RestRequest (url, DataFormat.Json);

            //
            if (addXPoweredValue) {
                request.AddHeader (XAuthorization.XPoweredBy, identityConfiguration.XPoweredValue);
            }

            //
            // Add Headers to request ...
            if (!headers.IsNull () && headers.Count > 0) {
                //
                var enumerator = headers.GetEnumerator ();
                while (enumerator.MoveNext ()) {
                    //
                    var item = enumerator.Current;
                    request.AddHeader (item.Key, item.Value);
                }
            }

            //
            return request;
        }

        /// <summary>
        /// Handle Call Specific Request and retrieve Response
        /// </summary>
        /// <param name="client"></param>
        /// <param name="request"></param>
        /// <param name="method"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task<T> RunRestRequest<T> (
            RestClient client,
            RestRequest request,
            XHttpMethod method,
            bool supportRefreshingTokens = true
        ) {
            //
            var response = await Task.Run (async () => {
                //
                IRestResponse resp = null;

                //
                // Call Endpoint Service using Specified Method ...
                switch (method) {
                    //
                    // Get ...
                    case XHttpMethod.GET:
                        resp = client.Get (request);
                        break;

                        //
                        // Put ...
                    case XHttpMethod.PUT:
                        resp = client.Put (request);
                        break;

                        //
                        // Post ...
                    case XHttpMethod.POST:
                        resp = client.Post (request);
                        break;

                        //
                        // Delete ...
                    case XHttpMethod.DELETE:
                        resp = client.Delete (request);
                        break;
                }

                //
                if (!resp.IsSuccessful) {
                    //
                    // Log Exception ...
                    Logger.LogError ($"Error: {resp.ErrorMessage}");
                    Logger.LogError ($"Exception: {resp.ErrorException.ToJSON()}");
                    if (!resp.ErrorMessage.IsNullOrEmpty () &&
                        resp.ErrorMessage.Contains ("timed out")) {
                        XException.Timeout.Throw ();
                    }

                    //
                    // TODO: Check UnAuthorized Status here for
                    // Refresh Tokens or Issue Correct Exception ...
                    if (supportRefreshingTokens &&
                        resp.StatusCode == System.Net.HttpStatusCode.Unauthorized) {
                        //
                        var isRefreshed = request.Parameters.Any (rp =>
                            rp.Name == XParam.XIsRefreshed.GetStringValue () &&
                            rp.Value.ToString ().ToNormalString () == true.ToJSON ());

                        //
                        Logger.LogInformation ($"isRefreshed: {isRefreshed}");

                        //
                        // Get Access Token ...
                        XTokenResponse tokens = null;
                        var accessToken = request.Parameters.FirstOrDefault (rp =>
                            rp.Name.ToNormalString () == XAuthorization.Header.ToNormalString ()).Value.ToString ();
                        if (!accessToken.IsNullOrEmpty ()) {
                            //
                            accessToken = accessToken.Replace (XAuthorization.TokenIdentifier, "");

                            //
                            if (!accessToken.IsNullOrEmpty ()) {
                                tokens = await tokenProvider.RetrieveToken (accessToken);
                            }
                        }

                        //
                        // Refresh Token and then re do request ...
                        if (!isRefreshed &&
                            !accessToken.IsNullOrEmpty () &&
                            !tokens.IsNull () &&
                            tokens.IsRefreshable ()) {
                            //
                            request.AddHeader (XParam.XIsRefreshed.GetStringValue (), true.ToJSON ());

                            //
                            // Refreshe Tokens ...
                            var refreshedTokens = await RefreshTokens (tokens);

                            //
                            // Renew Rest Client with Refreshed Tokens ...
                            var timeout = client.Timeout;
                            client = GetRestClient (refreshedTokens);
                            client.Timeout = Timeout.Infinite;

                            //
                            // Do Request Again using renew Client ...
                            return await RunRestRequest<T> (
                                client: client,
                                request: request,
                                method: method);
                        }
                    }

                    //
                    var ex = resp.Content.ToXError ();
                    if (!ex.IsNull ()) {
                        throw ex.ToException ();
                    }

                    //
                    // UnAuthorized ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.Unauthorized) {
                        XException.NotAuthorized.Throw ();
                    }

                    //
                    // NotFound ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.NotFound) {
                        XException.NotFound.Throw ();
                    }

                    //
                    XException.ActionFailed.Throw ();
                }

                //
                var result = resp.Content.FromJSON<T> ();
                return result;
            });

            //
            return response;
        }
        public async Task<XBaseRestResponse<T>> RunRestRequestByResponse<T> (
            RestClient client,
            RestRequest request,
            XHttpMethod method,
            bool supportRefreshingTokens = true
        ) {
            //
            var response = await Task.Run (async () => {
                //
                IRestResponse resp = null;

                //
                // Call Endpoint Service using Specified Method ...
                switch (method) {
                    //
                    // Get ...
                    case XHttpMethod.GET:
                        resp = client.Get (request);
                        break;

                        //
                        // Put ...
                    case XHttpMethod.PUT:
                        resp = client.Put (request);
                        break;

                        //
                        // Post ...
                    case XHttpMethod.POST:
                        resp = client.Post (request);
                        break;

                        //
                        // Delete ...
                    case XHttpMethod.DELETE:
                        resp = client.Delete (request);
                        break;
                }

                //
                if (!resp.IsSuccessful) {
                    //
                    // Log Exception ...
                    Logger.LogError ($"Error: {resp.ErrorMessage}");
                    Logger.LogError ($"Exception: {resp.ErrorException.ToJSON()}");
                    if (!resp.ErrorMessage.IsNullOrEmpty () &&
                        resp.ErrorMessage.Contains ("timed out")) {
                        XException.Timeout.Throw ();
                    }

                    //
                    // TODO: Check UnAuthorized Status here for
                    // Refresh Tokens or Issue Correct Exception ...
                    if (supportRefreshingTokens &&
                        resp.StatusCode == System.Net.HttpStatusCode.Unauthorized) {
                        //
                        var isRefreshed = request.Parameters.Any (rp =>
                            rp.Name == XParam.XIsRefreshed.GetStringValue () &&
                            rp.Value.ToString ().ToNormalString () == true.ToJSON ());

                        //
                        Logger.LogInformation ($"isRefreshed: {isRefreshed}");

                        //
                        // Get Access Token ...
                        XTokenResponse tokens = null;
                        var accessToken = request.Parameters.FirstOrDefault (rp =>
                            rp.Name.ToNormalString () == XAuthorization.Header.ToNormalString ()).Value.ToString ();
                        if (!accessToken.IsNullOrEmpty ()) {
                            //
                            accessToken = accessToken.Replace (XAuthorization.TokenIdentifier, "");

                            //
                            if (!accessToken.IsNullOrEmpty ()) {
                                tokens = await tokenProvider.RetrieveToken (accessToken);
                            }
                        }

                        //
                        // Refresh Token and then re do request ...
                        if (!isRefreshed &&
                            !accessToken.IsNullOrEmpty () &&
                            !tokens.IsNull () &&
                            tokens.IsRefreshable ()) {
                            //
                            request.AddHeader (XParam.XIsRefreshed.GetStringValue (), true.ToJSON ());

                            //
                            // Refreshe Tokens ...
                            var refreshedTokens = await RefreshTokens (tokens);

                            //
                            // Renew Rest Client with Refreshed Tokens ...
                            var timeout = client.Timeout;
                            client = GetRestClient (refreshedTokens);
                            client.Timeout = Timeout.Infinite;

                            //
                            // Do Request Again using renew Client ...
                            return await RunRestRequestByResponse<T> (
                                client: client,
                                request: request,
                                method: method
                            );
                        }
                    }

                    //
                    var ex = resp.Content.ToXError ();
                    if (!ex.IsNull ()) {
                        throw ex.ToException ();
                    }

                    //
                    // UnAuthorized ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.Unauthorized) {
                        XException.NotAuthorized.Throw ();
                    }

                    //
                    // NotFound ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.NotFound) {
                        XException.NotFound.Throw ();
                    }

                    //
                    XException.ActionFailed.Throw ();
                }

                //
                var result = new XBaseRestResponse<T>
                {
                    Response = resp,
                    Model = resp.Content.FromJSON<T> ()
                };

                //
                return result;
            });

            //
            return response;
        }

        /// <summary>
        /// Get User SelectBy Param 
        /// </summary>
        /// <param name="model"></param>
        /// <param name="forceNotNull"></param>
        /// <param name="excludes"></param>
        /// <returns></returns>
        public string GetUserSelectByParam (
            XActionRequest model,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        ) {
            //
            // Validate Args ...
            validationProvider.NotNull (model);

            //
            var id = model.UserId;
            var userName = model.UserName;
            var email = model.Email;
            var phoneNumber = model.MobileNumber;

            //
            if (excludes != null) {
                //
                if (excludes.Contains (XUserSelectBy.ID)) {
                    id = null;
                }
                if (excludes.Contains (XUserSelectBy.Email)) {
                    email = null;
                }
                if (excludes.Contains (XUserSelectBy.MobileNumber)) {
                    phoneNumber = null;
                }
                if (excludes.Contains (XUserSelectBy.Username)) {
                    userName = null;
                }
            }

            var selectByParam =
                id.IsNullOrEmpty () ?
                userName.IsNullOrEmpty () ?
                email.IsNullOrEmpty () ?
                phoneNumber.IsNullOrEmpty () ? null : phoneNumber : email : userName : id;

            //
            // Check result ...
            if (forceNotNull &&
                selectByParam.IsNullOrEmpty ()) {
                XException.InvalidData.Throw ();
            }

            //
            return selectByParam;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Providers\XInMemoryTokenProvider.cs

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using xCommons.Extensions;
using xIdentityModels.Models;
using xIdentityService.Interfaces;

namespace xIdentityService.Providers {
    public partial class XInMemoryTokenProvider : IXTokenProvider {
        private IDictionary<string, XTokenResponse> DbContext;

        public XInMemoryTokenProvider () {
            //
            this.DbContext = new Dictionary<string, XTokenResponse> ();
        }

        public async Task<bool> IsTokenExists (string accessToken) {
            //
            // Validate Args ...
            if (accessToken.IsNullOrEmpty ()) {
                return false;
            }

            //
            // Process Result ...
            var result = DbContext.Keys.Any (k => k == accessToken);
            return await Task.FromResult (result);
        }

        public async Task<bool> IsTokenExists (XTokenResponse tokens) {
            //
            // Validate Args ...
            if (tokens.IsNull () ||
                tokens.AccessToken.IsNullOrEmpty () ||
                !await IsTokenExists (tokens.AccessToken)) {
                return false;
            };

            //
            // Process Result ...
            var result = await IsTokenExists (tokens.AccessToken);
            return result;
        }

        public async Task<bool> RemoveToken (string accessToken) {
            //
            // Validate Args ...
            if (accessToken.IsNullOrEmpty ()) {
                return false;
            }

            //
            // Process Result ...
            var result = DbContext.Remove (accessToken);
            return await Task.FromResult (result);
        }

        public async Task<bool> RemoveToken (XTokenResponse tokens) {
            //
            // Validate Args ...
            if (tokens.IsNull () ||
                tokens.AccessToken.IsNullOrEmpty () ||
                !await IsTokenExists (tokens.AccessToken)) {
                return false;
            };

            //
            // Process Result ...
            var result = await RemoveToken (tokens.AccessToken);
            return result;
        }

        public async Task<XTokenResponse> RetrieveToken (string accessToken) {
            //
            // Validate Args ...
            if (accessToken.IsNullOrEmpty () ||
                !await IsTokenExists (accessToken)) {
                return null;
            }

            //
            // Process Result ...
            var result = DbContext[accessToken];
            return result;
        }

        public async Task<bool> AddToken (XTokenResponse tokens) {
            //
            // Validate Args ...
            if (tokens.IsNull () ||
                tokens.AccessToken.IsNullOrEmpty () ||
                await IsTokenExists (tokens.AccessToken)) {
                return false;
            };

            //
            // Process Result ...
            try {
                //
                DbContext.Add (tokens.AccessToken, tokens);
                return true;
            } catch {
                return false;
            }
        }

        public async Task<bool> UpdateToken (XTokenResponse tokens) {
            //
            // Validate Args ...
            if (tokens.IsNull () ||
                tokens.AccessToken.IsNullOrEmpty () ||
                !await IsTokenExists (tokens.AccessToken)) {
                return false;
            };

            //
            // Process Result ...
            try {
                //
                DbContext[tokens.AccessToken] = tokens;
                return true;
            } catch {
                return false;
            }
        }

        public async Task<bool> AddOrUpdateToken (XTokenResponse tokens) {
            //
            // Validate Args ...
            if (tokens.IsNull () ||
                tokens.AccessToken.IsNullOrEmpty ()
            ) {
                return false;
            };

            //
            // Process Result ...
            try {
                //
                var isExists = await IsTokenExists (tokens);
                if (isExists) {
                    return await UpdateToken (tokens);
                } else {
                    return await AddToken (tokens);
                }
            } catch {
                return false;
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Providers\XProxyHelper.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityService.Configuration;
using xIdentityService.Interfaces;

namespace xIdentityService.Providers {
    public class XProxyHelper : IXProxyHelper {
        //
        #region Props ...
        public XProxyConfiguration Configuration { get; }
        #endregion

        //
        #region Constructor ...
        public XProxyHelper (XProxyConfiguration configuration) {
            this.Configuration = configuration;
        }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// Validate XProxy Configuration for Client ...
        /// </summary>
        /// <returns></returns>
        public bool ValidateConfiguration () {
            //
            var result = !Configuration.IsNull () &&
                !Configuration.Host.IsNullOrEmpty () &&
                Configuration.Host.IsValidUrl () &&
                Configuration.Routes.HasChild ();

            //
            return result;
        }

        /// <summary>
        /// retrie Normalize Host ...
        /// </summary>
        /// <returns></returns>
        public string NormalizeHost () {
            //
            var result = string.Empty;

            //
            if (!Configuration.IsNull () &&
                !Configuration.Host.IsNullOrEmpty () &&
                Configuration.Host.IsValidUrl ()
            ) {
                //
                result = Configuration.Host
                    .ToNormalString ();

                //
                if (result.EndsWith ("/")) {
                    result = result.Substring (0, result.Length - 1);
                }
            }

            //
            return result;
        }

        /// <summary>
        /// retrieve all registred Routes ...
        /// </summary>
        /// <returns></returns>
        public IEnumerable<XProxyRouteDescriptor> GetRoutes () {
            //
            // Validate Args ...
            if (Configuration.IsNull ()) {
                return null;
            }

            //
            return Configuration.Routes;
        }

        /// <summary>
        /// Retrieve all Prepared url of Routes ...
        /// </summary>
        /// <returns></returns>
        public IEnumerable<string> GetRouteUrls () {
            //
            var normalHost = NormalizeHost ();
            if (normalHost.IsNullOrEmpty ()) {
                return null;
            }

            //
            var result = GetRoutes ()
                .Select (r => $"{normalHost}{r.Route}");

            //
            return result;
        }

        /// <summary>
        /// Find an Specific Route ...
        /// </summary>
        /// <param name="whereClause"></param>
        /// <returns></returns>
        public XProxyRouteDescriptor FindRoute (Expression<Func<XProxyRouteDescriptor, bool>> whereClause) {
            //
            // Validate Arg ...
            if (whereClause.IsNull ()) {
                return null;
            }

            //
            var whereFunc = whereClause
                .Compile ();

            //
            var result = GetRoutes ()
                .FirstOrDefault (whereFunc);

            //
            return result;
        }

        /// <summary>
        /// Prepare a request url for a Proxy Route ...
        /// </summary>
        /// <param name="url"></param>
        /// <param name="descriptor"></param>
        /// <returns></returns>
        public string PrepareActionUrlForXProxyRoute (
            string url,
            XProxyRouteDescriptor descriptor
        ) {
            //
            if (!url.IsValidUrl () ||
                url.IsNullOrEmpty () ||
                !ValidateConfiguration ()
            ) {
                throw XException.InvalidArgs.ToException ();
            }

            //
            // find Route ...
            var routeDescriptor = GetRoutes ()
                .FirstOrDefault (r => r
                    .IsSameContent (descriptor)
                );

            //
            // Validate Route Descriptor ...
            if (
                routeDescriptor.IsNull () ||
                routeDescriptor.Route.IsNullOrEmpty ()
            ) {
                throw XException.InvalidArgs.ToException ();
            }

            //
            // Retrieve and Validate Host Address ...
            var host = NormalizeHost ();
            if (!host.IsValidUrl () ||
                host.IsNullOrEmpty ()
            ) {
                throw XException.InvalidArgs.ToException ();
            }

            //
            url = $"{host}{routeDescriptor.Route}/{HttpUtility.UrlEncode(url)}";

            //
            return url;
        }

        /// <summary>
        /// Prepare a request url for a Selected Proxy Route ...
        /// </summary>
        /// <param name="url"></param>
        /// <param name="whereClause"></param>
        /// <returns></returns>
        public string PrepareActionUrlForXProxyRoute (
            string url,
            Expression<Func<XProxyRouteDescriptor, bool>> whereClause
        ) {
            //
            if (!url.IsValidUrl () ||
                url.IsNullOrEmpty () ||
                whereClause.IsNull () ||
                !ValidateConfiguration ()
            ) {
                throw XException.InvalidArgs.ToException ();
            }

            //
            var descriptor = FindRoute (whereClause);

            //
            // find Route ...
            var result = PrepareActionUrlForXProxyRoute (
                url: url,
                descriptor: descriptor
            );

            //
            return result;
        }
        #endregion

        //
        #region Private ...
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Security\XSecurityProvider.cs

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using xCommons.Extensions;
using xCommons.Helpers;
using xCommons.Providers;
using xIdentityService.Configuration;
using xIdentityService.Interfaces;

namespace xIdentityService.Security {
    public partial class XSecurityProvider : IXSecurityProvider {
        private readonly string secretKey;
        private readonly byte[] iv;
        private readonly byte[] key;
        private readonly XValidationProvider validationProvider;

        public XSecurityProvider (
            XIdentityServiceConfiguration identityConfiguration,
            XValidationProvider validationProvider
        ) {
            //
            this.secretKey = identityConfiguration.XRevisionSecretKey.ToMd5String ();
            this.validationProvider = validationProvider;

            //
            var ivBytes = new byte[16];
            var keyBytes = new byte[32];
            var secretBytes = Encoding.UTF8.GetBytes (this.secretKey);

            //
            Array.Copy (
                secretBytes,
                ivBytes,
                secretBytes.Length < ivBytes.Length ?
                secretBytes.Length :
                ivBytes.Length
            );
            this.iv = ivBytes;

            //
            Array.Copy (
                secretBytes,
                keyBytes,
                secretBytes.Length < keyBytes.Length ?
                secretBytes.Length :
                keyBytes.Length
            );
            this.key = keyBytes;

            // Encoding.UTF8.GetBytes (this.secretKey);
        }

        public string Encrypt (string plainText) {
            //
            validationProvider.NotEmpty (plainText);

            //
            var textBytes = Encoding.UTF8.GetBytes (plainText);
            var result = EncryptFromBytes (textBytes);

            //
            return result;
        }

        public string Decrypt (string cipherText) {
            //
            validationProvider.NotEmpty (cipherText);

            //
            var cipherBytes = Convert.FromBase64String (cipherText);
            var result = DecryptFromBytes (cipherBytes);

            //
            return result;
        }

        public string EncryptFromBytes (byte[] textBytes) {
            //
            // Validate Args ...
            validationProvider.NotNull (textBytes);

            // Declare the string used to hold
            // the decrypted text.
            byte[] encryptedBytes = null;

            // Create an RijndaelManaged object
            // with the specified key and IV.
            using (var rijAlg = new RijndaelManaged ()) {
                //Settings
                rijAlg.Mode = CipherMode.CBC;
                rijAlg.Padding = PaddingMode.PKCS7;
                // rijAlg.FeedbackSize = 128;

                rijAlg.Key = key;
                rijAlg.IV = iv;

                //
                using (var encryptor = rijAlg.CreateEncryptor (rijAlg.Key, rijAlg.IV)) {
                    encryptedBytes = encryptor.TransformFinalBlock (textBytes, 0, textBytes.Length);
                }
            }

            //
            return Convert.ToBase64String (encryptedBytes);
        }

        public string DecryptFromBytes (byte[] cipherBytes) {
            //
            // Validate Args ...
            validationProvider.NotNull (cipherBytes);

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an RijndaelManaged object
            // with the specified key and IV.
            using (var rijAlg = new RijndaelManaged ()) {
                //Settings
                rijAlg.Mode = CipherMode.CBC;
                rijAlg.Padding = PaddingMode.PKCS7;
                // rijAlg.FeedbackSize = 128;

                rijAlg.Key = key;
                rijAlg.IV = iv;

                // Create a decrytor to perform the stream transform.
                var decryptor = rijAlg.CreateDecryptor (rijAlg.Key, rijAlg.IV);

                // Create the streams used for decryption.
                using (var msDecrypt = new MemoryStream (cipherBytes)) {
                    using (var csDecrypt = new CryptoStream (msDecrypt, decryptor, CryptoStreamMode.Read)) {
                        using (var srDecrypt = new StreamReader (csDecrypt)) {
                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd ();
                        }
                    }
                }
            }

            //
            return plaintext;
        }
    }
}
