### 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 { /// /// XProxy Middleware Configuration ... /// public class XProxyConfiguration { /// /// Proxy Host Address for Clients Which Use XProxy Server ... /// /// public string Host { get; set; } /// /// if EnableXPoweredByAthorization property setted to true, this property determines /// the header must be this value ... /// /// public string XPoweredValue { get; set; } /// /// Determines Proxy Http Handler Check SSL or not ... /// /// public bool DisableSSLCheck { get; set; } /// /// Determines Http Client Handler Allow Auto Redirect or not ... /// /// public bool AllowAutoRedirect { get; set; } /// /// Determines Proxy Server Log Received Requests or not ... /// /// public bool EnableLogging { get; set; } /// /// DefineRoutes for Handling ... /// /// public HashSet Routes { get; set; } } /// /// Describe a Proxy Route ... /// public class XProxyRouteDescriptor : XBaseDescriptor { /// /// Determines which route can handled for Proxyfing ... /// /// public string Route { get; set; } /// /// Determines Proxy Server Handle Athorization or not ... /// /// public bool EnableAuthorization { get; set; } /// /// Determines Which Scopes allowed to this route if authorizations enabled ... /// /// public HashSet AllowedScopes { get; set; } /// /// Determines Which Roles allowed to this route if authorizations enabled ... /// /// public HashSet AllowedRoles { get; set; } /// /// Determines XProxy Can Check XPowered By Authorization or not ... /// /// 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 { /// /// All Available Headers ... /// public enum XHeader { /// /// Hub Connection ID Header Keys ... /// [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 { /// /// Base Identity Api Controller /// [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 { /// /// Base Identity Api V1 Controller /// [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 ... /// /// Retrieve Connection ID for Hubs ... /// /// [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; } /// /// Retrieve User Identifier Base on XActionRequest /// /// /// /// /// [NonAction] public string GetUserSelectByParam( XActionRequest model, bool forceNotNull = true, ICollection excludes = null ) { // // Validate Args ... ValidationProvider.NotNull(model); // var result = IdentityProvider.GetUserSelectByParam( model, forceNotNull, excludes ); // return result; } /// /// Retrieve Access Token /// /// [NonAction] public async Task 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; } /// /// Retrieve Refresh Token /// /// [NonAction] public async Task GetRefreshToken() { // var refreshToken = Request.Headers[XAuthorization.RefreshToken].ToString(); if (refreshToken.IsNullOrEmpty()) { // refreshToken = await HttpContext .GetTokenAsync(XAuthorization.RefreshToken); } // return refreshToken; } /// /// Retrieve Access Token Expiration Date /// /// [NonAction] public async Task GetTokenExpiresAt() { // var expiresAtStr = Request.Headers[XAuthorization.ExpiresAt].ToString(); if (expiresAtStr.IsNullOrEmpty()) { // expiresAtStr = await HttpContext .GetTokenAsync(XAuthorization.ExpiresAt); } // var expiresAt = expiresAtStr.ConvertTo(); // return expiresAt; } /// /// Retrieve All Required Tokens /// /// [NonAction] public async Task RetrieveTokensAsXLoginResponse() { // var accessToken = await GetAccessToken(); var refreshToken = await GetRefreshToken(); var expiresAt = await GetTokenExpiresAt(); // return new XLoginResponse { AccessToken = accessToken, RefreshToken = refreshToken, ExpiresAt = expiresAt }; } /// /// Retrieve All Required Tokens /// /// [NonAction] public async Task RetrieveTokensAsXTokenResponse() { // var accessToken = await GetAccessToken(); var refreshToken = await GetRefreshToken(); var expiresAt = await GetTokenExpiresAt(); // return new XTokenResponse { AccessToken = accessToken, RefreshToken = refreshToken, ExpiresAt = expiresAt }; } /// /// Retrive UserInfo /// /// [NonAction] public async Task 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; } /// /// Validate User Authenticated and Retrieve User Info /// /// [NonAction] public async Task 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 { /// /// Extract Module Configuration Structure from IConfiguration interface /// /// /// public static XIdentityServiceConfiguration GetXIdentityServiceConfiguration (this IConfiguration config) { // var xIdentityServiceConfigSection = config.GetSection (ConfigurationNodeNames.IDENTITY_SERVICE_NODE_NAME); return xIdentityServiceConfigSection.Get (); } /// /// Register Service and All it's Requirements /// /// /// public static void AddXIdentityService ( this IServiceCollection services, IConfiguration configuration, ServiceLifetime lifeTime = ServiceLifetime.Singleton ) { // var identityConfiguration = configuration.GetXIdentityServiceConfiguration (); AddIdentityService ( services, identityConfiguration, lifeTime ); } /// /// Register Service and All it's Requirements /// /// /// public static void AddXIdentityService ( this IServiceCollection services, XIdentityServiceConfiguration configuration, ServiceLifetime lifeTime = ServiceLifetime.Singleton ) { AddIdentityService (services, configuration, lifeTime); } /// /// Register Custome Token Provider /// /// /// public static void AddXTokenProvider ( 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)); } /// /// Use Authentication /// /// 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 (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 (req => { // var fromHeader = TokenRetrieval.FromAuthorizationHeader (); var fromQuery = TokenRetrieval.FromQueryString (); // var bearerToken = fromHeader (req) ?? fromQuery (req); // return bearerToken; }); }); // // Register Authorization Handler ... services.AddSingleton (); 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 (); } 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 { /// /// Adds a policy to check for required scopes. /// /// /// List of any required scopes. The token must contain at least one of the listed scopes. /// public static AuthorizationPolicyBuilder RequireScope (this AuthorizationPolicyBuilder builder, params string[] scope) { return builder.RequireClaim (JwtClaimTypes.Scope, scope); } } /// /// Helper for creating scope-related policies /// public static class ScopePolicy { /// /// Creates a policy to check for required scopes. /// /// List of any required scopes. The token must contain at least one of the listed scopes. /// 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 { /// /// Retrieve Authentication Service ... /// /// /// public static IAuthenticationService GetAuthenticationService (this HttpContext context) { // var result = context.RequestServices .GetRequiredService (); // return result; } /// /// Retrieve Specific Token from HttpContext ... /// /// /// /// /// public static async Task 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; } /// /// Retrieve Access Token /// /// public static async Task 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; } /// /// Retrieve Refresh Token /// /// public static async Task GetRefreshToken (this HttpContext context) { // var refreshToken = context.Request.Headers[XAuthorization.RefreshToken] .ToString (); if (refreshToken.IsNullOrEmpty ()) { refreshToken = await context .GetTokenAsync (XAuthorization.RefreshToken); } // return refreshToken; } /// /// Retrieve Access Token Expiration Date /// /// public static async Task 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 (); // return expiresAt; } /// /// Retrieve All Required Tokens /// /// public static async Task 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 { /// /// Converts an Stream to Async Enumerable ... /// /// /// /// /// public static async IAsyncEnumerable 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(); } } /// /// Converts an Stream to Async Enumerable ... /// /// /// /// /// public static async IAsyncEnumerable 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; } // T chunk = default(T); var readedBuffer = buffer.Take(read).ToArray(); var str = readedBuffer.FromBytes(); if (str.IsNullOrEmpty()) { yield return chunk; } try { chunk = str.FromJSON(); } 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 { /// /// Retrieve Tokens From Headers /// /// /// public static XLoginResponse RetrieveTokens (this HttpRequest source) { // var accessToken = source.Headers[XAuthorization.Header].ToString (); var refreshToken = source.Headers[XAuthorization.RefreshToken].ToString (); // var expiresAtStr = source.Headers[XAuthorization.ExpiresAt].ToString (); long expiresAt = expiresAtStr.ConvertTo (); // if (accessToken .ToNormalString () .Contains (XAuthorization.TokenIdentifier.ToNormalString ())) { accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length); } // return new XLoginResponse { AccessToken = accessToken, RefreshToken = refreshToken, ExpiresAt = expiresAt }; } /// /// Retrieve Tokens From HttpContext /// /// /// public static async Task RetrieveTokens (this HttpContext source) { // var accessToken = await source.GetTokenAsync (XAuthorization.AccessToken); if (accessToken .ToNormalString () .Contains (XAuthorization.TokenIdentifier.ToNormalString ())) { accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length); } var refreshToken = await source.GetTokenAsync (XAuthorization.RefreshToken); var expiresAtStr = await source.GetTokenAsync (XAuthorization.ExpiresAt); long expiresAt = expiresAtStr.ConvertTo (); // var headerRequestTokens = source.Request.RetrieveTokens (); // var result = new XLoginResponse { AccessToken = accessToken ?? headerRequestTokens.AccessToken, RefreshToken = refreshToken ?? headerRequestTokens.RefreshToken, ExpiresAt = expiresAt != 0 ? expiresAt : headerRequestTokens.ExpiresAt }; // return result; } /// /// Retrieve Tokens From ActionExecutingContext /// /// /// public static async Task RetrieveTokens (this ActionExecutingContext source) { // var result = await source.HttpContext.RetrieveTokens (); return result; } /// /// Retrieve Tokens From XUserInfo instance /// /// /// public static XTokenResponse RetrieveTokens (this XUserClaimsInfoDto source) { // var result = new XLoginResponse { AccessToken = source.AccessToken, RefreshToken = source.RefreshToken, ExpiresAt = source.ExpiresAt }; // return result; } /// /// Retrieve Tokens From IHeader Dictionary /// /// /// public static XLoginResponse RetrieveTokens (this IHeaderDictionary source) { // var accessToken = source[XAuthorization.Header].ToString () ?? ""; if (accessToken .ToNormalString () .Contains (XAuthorization.TokenIdentifier.ToNormalString ())) { accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length); } // var refreshToken = source[XAuthorization.RefreshToken].ToString () ?? ""; // var expiresAtStr = source[XAuthorization.ExpiresAt].ToString () ?? ""; var expiresAt = expiresAtStr.ConvertTo (); // var result = new XLoginResponse { AccessToken = accessToken, RefreshToken = refreshToken, ExpiresAt = expiresAt }; // return result; } /// /// Retrieve IXIdentityProvider from HttpContext /// /// /// public static IXIdentityProvider GetXApiIdentityProvider (this FilterContext source) { // var services = source.HttpContext.RequestServices; return (IXIdentityProvider) services .GetService (typeof (IXIdentityProvider)); } /// /// Generate XLoginResponse instance based on TokenResponse /// /// /// public static XLoginResponse CreateXLoginResponse (this TokenResponse source) { // if (source.IsNull () || source.IsError) { XException.InvalidToken.Throw (); } // var expiresAt = new DateTimeOffset (DateTime.UtcNow) .ToUnixTimeSeconds () + source.ExpiresIn; // var result = new XLoginResponse { AccessToken = source.AccessToken, RefreshToken = source.RefreshToken, ExpiresAt = expiresAt }; // return result; } /// /// Add Authorization Tokens in Headers of /// Specific IHeaderDictionary instance /// /// /// public static void SetXAuthenticationTokens (this IHeaderDictionary source, XLoginResponse model, string secret = null) { // source.Remove (XAuthorization.Header); source.Remove (XAuthorization.RefreshToken); source.Remove (XAuthorization.ExpiresAt); source.Remove (XAuthorization.RevisionChecksum); // source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}"); source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}"); source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}"); // if (!secret.IsNullOrEmpty ()) { var revisionChecksum = model.GetRevisionChecksum (secret); source.Add (XAuthorization.RevisionChecksum, revisionChecksum); } } /// /// Add Authorization Tokens in Headers of /// Specific IHeaderDictionary instance /// /// /// public static void SetXAuthenticationTokens (this HttpRequestHeaders source, XLoginResponse model) { // source.Remove (XAuthorization.Header); source.Remove (XAuthorization.RefreshToken); source.Remove (XAuthorization.ExpiresAt); source.Remove (XAuthorization.RevisionChecksum); // source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}"); source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}"); source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}"); } /// /// Add Authorization Tokens in Headers of /// Specific HttpRequest instance /// /// /// public static void SetXAuthenticationTokens (this HttpRequest source, XLoginResponse model) { source.Headers.SetXAuthenticationTokens (model); } /// /// Add Authorization Tokens in Headers of /// Specific HttpRequest instance /// /// /// public static void SetXAuthenticationTokens (this HttpRequestMessage source, XLoginResponse model) { source.Headers.SetXAuthenticationTokens (model); } /// /// Add ReNewed Authorization Tokens in Headers of /// Specific Response. /// Later in HttpInterceptors we can Look for AccessToken-ReNewed /// header Value and Renew User Tokens based on it /// /// /// public static void SetXAuthenticationTokens (this HttpResponse source, XLoginResponse model, string secret) { source.Headers.SetXAuthenticationTokens (model, secret); } /// /// Determines a Token Can Refrsh or not /// /// /// public static bool IsRefreshable (this XLoginResponse source) { // var containsTokenData = !source.IsNull () && !source.AccessToken.IsNullOrEmpty () && !source.RefreshToken.IsNullOrEmpty (); if (!containsTokenData) { return false; } // var current = new DateTimeOffset (DateTime.UtcNow) .ToUnixTimeSeconds (); // // var result = current > source.ExpiresAt || current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration; var result = current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration; // return result; } /// /// Generate a Revision Checksum for new Tokens /// /// /// /// public static string GetRevisionChecksum (this XLoginResponse source, string secret) { return (source.AccessToken + secret + source.RefreshToken + secret + source.ExpiresAt.ToString () ) .ToMd5String (); } /// /// Generate a Revision Checksum for new Tokens /// /// /// /// public static string GetRevisionChecksum (this XTokenResponse source, string secret) { return (source.AccessToken + secret + source.RefreshToken + secret + source.ExpiresAt.ToString () ) .ToMd5String (); } /// /// Check an XLoginResponse instance is Valid with it's revision /// /// /// /// /// public static bool ValidateRevisionChecksum (this XLoginResponse source, string checksum, string secret) { // var xChecksum = source.GetRevisionChecksum (secret); return checksum == xChecksum; } /// /// Check an XTokenResponse instance is Valid with it's revision /// /// /// /// /// public static bool ValidateRevisionChecksum (this XTokenResponse source, string checksum, string secret) { // var xChecksum = source.GetRevisionChecksum (secret); return checksum == xChecksum; } /// /// Retrieve Exception Details if Fails /// /// /// public static Exception GetException (this TokenResponse source) { // // Validate Args ... if (source.IsNull () || !source.IsError) { return XException.ActionFailed.ToException (); } // XError error = source.ErrorDescription.FromJSON (); return error.ToException (); } /// /// Convert XTokenResponse to Header Dictionary /// /// /// public static IDictionary ToHeaderDictionary (this XTokenResponse source) { // var result = new Dictionary { { XAuthorization.RefreshToken, source.RefreshToken }, { XAuthorization.ExpiresAt, source.ExpiresAt.ToString () } }; // return result; } } ### 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 { /// /// an interface for Identity Provided Http Based Services ... /// public interface IXBaseIdentityHttpProvider { /// /// Client Base Url ... /// /// string BaseUrl { get; } /// /// Logger ... /// /// ILogger Logger { get; } /// /// Powered Value ... /// /// string XPoweredValue { get; } /// /// Default Client Timeout ... /// /// int DefaultClientTimeout { get; } /// /// Default Buffering Chunk Size ... /// /// int DefaultBufferingChunckSize { get; } /// /// Validation Provider ... /// /// XValidationProvider ValidationProvider { get; } /// /// Get an Instance of Http Client /// /// HttpClient GetHttpClient(XTokenResponse tokens = null); HttpClient GetHttpClient(XUserClaimsInfoDto userInfo = null); /// /// Get an Instance of RestClient /// /// RestClient GetRestClient(XTokenResponse tokens = null); RestClient GetRestClient(XUserClaimsInfoDto userInfo = null); /// /// Get an Instance of RestRequest /// /// /// /// /// /// /// RestRequest GetRestRequet( Enum endpoint, bool addXPoweredValue = true, IDictionary @params = null, IDictionary headers = null, IDictionary queryStrings = null ); /// /// Handle Call Specific Request and retrieve Response /// /// /// /// /// /// /// /// Task RunRestRequest( RestClient client, RestRequest request, XHttpMethod method, bool supportRefreshingTokens = true, CancellationToken cancellationToken = default ); /// /// Access a Get Request Stream as AsyncEnumerable ... /// /// /// /// /// /// /// /// /// /// /// Task StreamData( Enum endpoint, int bufferLength = 8194, bool addXPoweredValue = true, XTokenResponse tokens = null, IDictionary @params = null, IDictionary headers = null, IDictionary queryStrings = null, CancellationToken cancellationToken = default ); /// /// Handle Call Specified Request and Retrieve XBaseRestResponse ... /// /// /// /// /// /// /// /// an instance of XBaseRestResponse Task> RunRestRequestByResponse( RestClient client, RestRequest request, XHttpMethod method, bool supportRefreshingTokens = true, CancellationToken cancellationToken = default ); /// /// Get User SelectBy Param /// /// /// /// /// string GetUserSelectByParam( XActionRequest model, bool forceNotNull = true, ICollection excludes = null ); /// /// Converts UserInfo to TokenResponse model ... /// /// /// XTokenResponse ToTokenResponse(XUserClaimsInfoDto userInfo = null); /// /// Prepare Url Address of Specified Enum by Filling Params /// and Query Strings Attach ... /// /// /// /// /// /// string PrepareUrl( Enum endpoint, bool attachBaseUrl = false, IDictionary @params = null, IDictionary queryStrings = null ); /// /// Prepare Url Address by Filling Params /// and Query Strings Attach ... /// /// /// /// /// /// string PrepareUrl( string url, bool attachBaseUrl = false, IDictionary @params = null, IDictionary 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 { /// /// a Referenced Service is a Service which can Referenced to other Items ... /// public interface IXBaseReferenced where TEntity : XBaseEntity { /// /// Get Reference Identifier for Specified Provider and Specified Item ... /// /// /// /// string GetIdentifier( string providedFor, TReferenceKey forProvidedId ); /// /// Check Specified Item has Refernce to Provider ... /// /// /// /// /// /// Task IsProvidedFor( string providedFor, TReferenceKey forProvidedId, TKey id, CancellationToken cancellationToken = default ); /// /// Add Specified Reference to Specified Item ... /// /// /// /// /// /// /// /// /// Task AddReference( string providedFor, TReferenceKey forProvidedId, TKey id, int forIndex = 0, XUserClaimsInfoDto userInfo = null, string connectionId = null, CancellationToken cancellationToken = default ); /// /// Remove Specified Reference from Specified Item ... /// /// /// /// /// /// /// /// /// Task RemoveReference( string providedFor, TReferenceKey forProvidedId, TKey id, int forIndex = 0, XUserClaimsInfoDto userInfo = null, string connectionId = null, CancellationToken cancellationToken = default ); /// /// Get Specified References ... /// /// /// /// /// /// Task>> 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 where TEntity : XBaseEntity { /// /// Check an Item Has Reference to Specified ProvideFor and Specified forProvidedId ... /// /// /// /// /// /// [HttpGet("{id}/Reference/IsProvidedFor")] Task> IsProvidedFor( [FromRoute] TKey id, [FromQuery] string providedFor, [FromQuery] object forProvidedId, CancellationToken cancellationToken = default ); /// /// Add a Reference to Item for Specified ProvideFor and Specified forProvidedId ... /// /// /// /// /// /// /// [HttpPost("{id}/Reference")] Task AddReference( [FromRoute] TKey id, [FromQuery] string providedFor, [FromQuery] object forProvidedId, [FromQuery] int forIndex = 0, CancellationToken cancellationToken = default ); /// /// Remove a Reference from Item for Specified ProvideFor and Specified forProvidedId ... /// /// /// /// /// /// /// [HttpDelete("{id}/Reference")] Task RemoveReference( [FromRoute] TKey id, [FromQuery] string providedFor, [FromQuery] object forProvidedId, [FromQuery] int forIndex = 0, CancellationToken cancellationToken = default ); /// /// Retrieve References of Specified Itemfor providedFor ... /// /// /// /// /// [HttpGet("{id}/References")] Task>>> 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 { /// /// 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 ... /// public interface IXIdentityBaseReferencedProvider { // #region Props ... /// /// Provider Identifier ... /// string Provider { get; } #endregion // #region Referenced Actions ... /// /// Get Specified Indexed Reference for Specific Provided ID ... /// /// /// /// Task GetReference( TKey providedForId, int forIndex = 0 ); /// /// Retrieve all Exists References of Specific Provided ID ... /// /// /// Task> GetAllReferences(TKey providedForId); /// /// Extract all Referencing Models for Specified Key ... /// /// /// Task>> GetAllReferencings(TKey providedForId); /// /// Count References ... /// /// /// Task CountReferences(TKey providedForId); /// /// Retrieve References of Specific Provided ID as Query ... /// /// /// Task> QueryReferences( XQuery query, TKey providedForId ); /// /// Add Reference a Model to Specific Provided ID ... /// /// /// /// /// /// Task AddReference( TModel model, TKey providedForId, string connectionId = null, XUserClaimsInfoDto userInfo = null ); /// /// Add Reference a Model to Specific XRefence ... /// /// /// /// /// /// Task AddReference( TModel model, XReference reference, string connectionId = null, XUserClaimsInfoDto userInfo = null ); /// /// Remove Reference a Model for Specific Provided ID ... /// /// /// /// /// /// Task RemoveReference( TModel model, TKey providedForId, string connectionId = null, XUserClaimsInfoDto userInfo = null ); /// /// Remove Reference a Model for Specific XRefence ... /// /// /// /// /// /// Task RemoveReference( TModel model, XReference reference, string connectionId = null, XUserClaimsInfoDto userInfo = null ); /// /// Remove All References to Specified Key ... /// /// /// /// /// Task 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 excludes = null ); #endregion // #region Tools ... Task RunRestRequest( RestClient client, RestRequest request, XHttpMethod method, bool supportRefreshingTokens = false ); #endregion // #region Authentication ... Task RequestDiscoveryDocument(); Task RequestScopeAccessToken(string scope); Task Introspection(XTokenResponse model); Task Login(XLoginRequest model); Task Logout(XTokenResponse model); Task Authenticate(XLoginRequest model); Task RefreshTokens(XTokenResponse model); Task ChangePassword( XTokenResponse tokens, XActionRequest model ); #endregion // #region Profile ... Task> GetUserNames( XTokenResponse tokens, string userIds ); Task> GetUserNameIds( XTokenResponse tokens, XUserNameIdRequest model ); Task GetUserProfile( XTokenResponse tokens, string userSelectByParam ); Task> QueryUsers( XTokenResponse tokens, XQuery query ); Task> QueryInRoleUsers( XTokenResponse tokens, string role, XQuery query, bool forceRole = false ); Task> QueryAvatars( XTokenResponse tokens, string userSelectByParam, XQuery query ); Task ProfileUpdateAsync( XTokenResponse tokens, string userSelectByParam, XProfileUpdateRequest model ); Task FullProfileUpdateAsync( XTokenResponse tokens, string userSelectByParam, XProfileUpdateRequest request ); Task AddAvatar( XTokenResponse tokens, IFormFile file ); Task AddAvatars( XTokenResponse tokens, IFormFileCollection files ); Task SetAvatar( XTokenResponse tokens, int avatarId ); Task RemoveAvatars( XTokenResponse tokens, string avatarIds ); #endregion // #region Search ... /// /// Query Open To Search User Profiles ... /// /// requested user's identifiers /// how to filter results based on XQuery structure /// an instance of XQueryResult of XUserProfileDto Task> QueryOpenToSearchUsers( XTokenResponse tokens, XQuery query ); #endregion // #region Registration ... Task CanRegister(string userSelectByParam); Task InviteUser( XTokenResponse tokens, XActionRequest model ); Task RequestRegistration( XActionRequest model ); Task AddAccountInfo( XActionRequest model ); Task AttachProfileImage( string actionToken, IFormFile file ); Task FinishRegistration(XActionRequest model); Task IsConfirmedEmail( XTokenResponse tokens, string userSelectByParam ); Task IsConfirmedMobile( XTokenResponse tokens, string userSelectByParam ); Task RequestConfirmRegistration(XActionRequest model); Task ConfirmRegistration( XActionRequest model ); Task RequestConfirmMobile(XActionRequest model); Task ConfirmMobileNumber(XActionRequest model); Task RequestConfirmEmail(XActionRequest model); Task ConfirmEmailAddress(XActionRequest model); Task RequestResetPassword(XActionRequest model); Task ResetPassword(XActionRequest model); #endregion // #region Friendship ... Task Follow( XTokenResponse tokens, string destUser ); Task Cancel( XTokenResponse tokens, string destUser ); Task UnFollowFollower( XTokenResponse tokens, string destUser ); Task UnFollowFollowing( XTokenResponse tokens, string destUser ); Task Block( XTokenResponse tokens, string destUser ); Task UnBlock( XTokenResponse tokens, string destUser ); Task AcceptRequest( XTokenResponse tokens, string destUser ); Task RejectRequest( XTokenResponse tokens, string destUser ); Task GetFriendshipInfo( XTokenResponse tokens, string destUser ); Task IsFollower( XTokenResponse tokens, string destUser ); Task GetFollower( XTokenResponse tokens, string destUser ); Task GetFollowerState( XTokenResponse tokens, string destUser ); Task> GetFollowers(XTokenResponse tokens); Task> GetAllFollowers(XTokenResponse tokens); Task> GetFollowingList(XTokenResponse tokens); Task> QueryFollowers( XQuery query, string destUser, XTokenResponse tokens ); Task IsFollowing( XTokenResponse tokens, string destUser ); Task GetFollowing( XTokenResponse tokens, string destUser ); Task GetFollowingState( XTokenResponse tokens, string destUser ); Task> GetFollowings(XTokenResponse tokens); Task> GetAllFollowings(XTokenResponse tokens); Task> GetFollowersList(XTokenResponse tokens); Task> QueryFollowings( XQuery query, string destUser, XTokenResponse tokens ); #endregion // #region Admin ... Task> Ban( XTokenResponse tokens, XUserNameIdRequest model ); Task> UnBan( XTokenResponse tokens, XUserNameIdRequest model ); Task IsBanned( XTokenResponse tokens, string userSelectByParam ); #endregion // #region Open Actions ... // XDeviceDto GetDevice(); // Task OpenGet( XOpenActionInnerDto model ); // Task GetUserInfo( XDeviceDto device, string userSelectByParam ); Task GetUserInfo( XOpenActionInnerDto dto ); Task GetUserInfo( string token, string request ); // Task> GetUserInfos( XDeviceDto device, string ids ); Task> GetUserInfos( XOpenActionInnerDto dto ); Task> 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 { /// /// Proxy Configuration ... /// /// XProxyConfiguration Configuration { get; } /// /// retrie Normalize Host ... /// /// string NormalizeHost (); /// /// Validate XProxy Configuration for Client ... /// /// bool ValidateConfiguration (); /// /// Retrieve all Prepared url of Routes ... /// /// IEnumerable GetRouteUrls (); /// /// retrieve all registred Routes ... /// /// IEnumerable GetRoutes (); /// /// Prepare a request url for a Proxy Route ... /// /// /// /// string PrepareActionUrlForXProxyRoute ( string url, XProxyRouteDescriptor descriptor ); /// /// Prepare a request url for a Selected Proxy Route ... /// /// /// /// string PrepareActionUrlForXProxyRoute ( string url, Expression> whereClause ); /// /// Find an Specific Route ... /// /// /// XProxyRouteDescriptor FindRoute (Expression> 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 IsTokenExists (string accessToken); Task IsTokenExists (XTokenResponse tokens); Task RemoveToken (string accessToken); Task RemoveToken (XTokenResponse tokens); Task RetrieveToken (string accessToken); Task AddToken (XTokenResponse tokens); Task UpdateToken (XTokenResponse tokens); Task 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 (); } #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 } /// /// Provide all DI Requirements for XIdentityTokenRefresher Middleware /// public static class XIdentityTokenRefresherDIHelper { /// /// Use XTokenValidator Middleware /// /// public static void UseXIdentityTokenRefresher (this IApplicationBuilder app) { app.UseMiddleware (); } } } ### 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 { /// /// Proxy Server Middleware ... /// 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 ... /// /// Throw Required Exception ... /// private void ThrowNotAuthorizedException () { throw XException.NotAuthorized.ToException (); } /// /// Show propper logs if Enabled ... /// /// /// private void SendLog (string message, LogLevel logLevel = LogLevel.Information) { // if (!CONFIGURATION.EnableLogging) { return; } // LogMessage ( message: message, logLevel: logLevel ); } /// /// Log Proxy Server Configuration ... /// 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 ($" "); }); } /// /// Retrieve Destination Request Path based on Current Request ... /// /// /// 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; } /// /// Retrieve Propper Request Message based on HttpContext and uri ...F /// /// /// /// 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 { [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; } /// /// Fill Request Message by provide HttpContext ... /// /// /// 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 acceptedHeaders = null; var acceptedHeadersKeyValue = context.Request.Headers .FirstOrDefault (hr => hr.Key == XProxyConstants.XPROXY_ACCEPTED_HEADERS ); if (!acceptedHeadersKeyValue.IsNull ()) { // acceptedHeaders = acceptedHeadersKeyValue.Value .ToString () .ParseListString (); // // 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 () ); } } /// /// Retreive and Extract Method Type of HttpRequest ... /// /// /// 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); } /// /// add all headers exists in HttpResponse MEssage to Current Context Response Headers ... /// /// /// 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"); } /// /// Processing Response Content and Handle it on HttpContextResponse ... /// /// /// /// 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); } /// /// Check Content Type of Specific Response ... /// /// /// /// 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; } /// /// Retrieve and Extract Route Descriptor ... /// /// /// 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 } /// /// Provide all requirements for Dependency Injection Handler ... /// public static class XDIHelperExtension { /// /// Retrieve XProxy Middelware Configuration from Configuration ... /// /// /// public static XProxyConfiguration GetXProxyConfiguration (this IConfiguration config) { // var xProxyConfiguration = config.GetSection (ConfigurationNodeNames.XPROXY_CONFIGURATION_NODE_NAME); return xProxyConfiguration.Get (); } /// /// Register HTTP Handler for XProxy Server ... /// /// /// /// 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 ); } /// /// Register HTTP Handler for XProxy Server ... /// /// /// /// 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; }); } /// /// Register XProxy On Server ... /// /// /// /// public static void AddXProxyServer ( this IServiceCollection services, IConfiguration configuration, HttpClientHandler httpHandler = null ) { // var proxyConfig = configuration.GetXProxyConfiguration (); // services.AddXProxyServer ( httpHandler: httpHandler, configuration: proxyConfig ); } /// /// Register XProxy On Server ... /// /// /// /// 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 (configuration); // // Regiter Proxy Handler ... services.AddXProxyHttpHandler ( httpHandler: httpHandler, configuration: configuration ); } /// /// Register XProxy On Server ... /// /// /// public static void AddXProxyClient ( this IServiceCollection services, IConfiguration configuration ) { // var proxyConfig = configuration.GetXProxyConfiguration (); // services.AddXProxyClient ( configuration: proxyConfig ); } /// /// Register XProxy On Client ... /// /// /// public static void AddXProxyClient ( this IServiceCollection services, XProxyConfiguration configuration ) { // // Validate Args ... if (configuration.IsNull ()) { throw XException.InvalidConfiguration.ToException (); } // // Register Proxy Configuration ... services.AddSingleton (configuration); // // Register IXProxyHelper ... services.AddSingleton (); } /// /// Adding XProxy Middleware to Applications ... /// /// public static void UseXProxy (this IApplicationBuilder app) { app.UseMiddleware (); } } } ### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Models\XBaseRestResponse.cs using RestSharp; namespace xIdentityService.Models { public class XBaseRestResponse { 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 ... /// /// Ban Specific Users /// /// Authentication Tokens /// an instance of XUserNameIdRequest which represents user identifier list to Ban /// a list of banned users identifiers public async Task> 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> ( client, request, XHttpMethod.POST ); return response; } /// /// UnBann Specific Users /// /// Authentication Tokens /// an instance of XUserNameIdRequest which represents user identifier list to Ban /// a list of unbanned users identifiers public async Task> 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> ( client, request, XHttpMethod.POST ); return response; } /// /// Check Specific User is Banned or not /// /// Authentication Tokens /// specified user's identifier /// a boolean value which represent user banned or not public async Task 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 { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam } } ); // var response = await RunRestRequest ( 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 ... /// /// Request for Discovery Document /// /// an instance of DiscoveryDocumentResponse public async Task 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 (); } } /// /// Request AccessToken for Specific XApiScope /// /// a member of XApiScope /// an instance of XTokenResponse public async Task 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 { { XParam.XScope.GetStringValue (), scope.ToString () } }); // var response = await RunRestRequest ( client, request, XHttpMethod.POST ); // // Save Token ... if (!response.IsNull ()) { await tokenProvider.AddOrUpdateToken (response); } // return response; } /// /// Validate a token /// /// Authentication Tokens /// an instance of TokenIntrospectionResponse public async Task 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 (); } } /// /// Authenticate a User /// /// User Login Required Info, an instance of XLoginRequest /// an instance of XTokenResponse public async Task 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 ( client, request, XHttpMethod.POST ); // // Save Token ... if (!response.IsNull ()) { await tokenProvider.AddOrUpdateToken (response); } // return response; } /// /// Do Login based on XLoginRequest /// /// User Login Required Info, an instance of XLoginRequest /// an instance of XTokenResponse public async Task 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 ( client, request, XHttpMethod.POST ); // if (!response.IsNull ()) { // var tokens = response.ToXTokenResponse (); await tokenProvider.AddOrUpdateToken (tokens); } // return response; } /// /// Logout from System /// /// /// 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); } } /// /// Refresh Tokens /// /// Authentication Tokens /// an instance of XTokenResponse public async Task 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 ( client, request, XHttpMethod.POST ); if (!response.IsNull ()) { await tokenProvider.UpdateToken (response); } // return response; } #endregion // #region Password Actions Handlers ... /// /// Change Password /// /// Authentication Tokens /// an instance of XActionRequest class which provider requirement for action /// 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 ( 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 ... /// /// Follow a User /// /// Authentication Tokens /// a user identifier which represent destination user /// an instance of XFriendshipFollowing public async Task 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.POST ); return response; } /// /// Cancel Following Request /// /// Authentication Tokens /// a user identifier which represent destination user /// a boolean value public async Task 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.POST ); return response; } /// /// Unfollow a Follower /// /// Authentication Tokens /// a user identifier which represent destination user /// 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.POST ); } /// /// Unfollow Following /// /// Authentication Tokens /// a user identifier which represent destination user /// 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.POST ); } /// /// Block a Follower /// /// Authentication Tokens /// a user identifier which represent destination user /// an instance of XFriendshipFollowing public async Task 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.POST ); return response; } /// /// Unblock a Blocked User /// /// Authentication Tokens /// a user identifier which represent destination user /// an instance of XFriendshipFollowing public async Task 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.POST ); return response; } /// /// Accept a Following Request /// /// Authentication Tokens /// a user identifier which represent destination user /// an instance of XFriendshipFollower public async Task 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.POST ); return response; } /// /// Reject a Following Request /// /// Authentication Tokens /// a user identifier which represent destination user /// an instance of XFriendshipFollower public async Task 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.POST ); return response; } /// /// Get Friendship Info Model between Specific User and Current User /// /// Authentication Tokens /// a user identifier which represent destination user /// an instance of XFriendshipInfoDto public async Task 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.GET ); return response; } /// /// Check a User IsFollower of Requested User /// /// Authentication Tokens /// a user identifier which represent destination user /// a boolean value public async Task 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.GET ); return response; } /// /// Get Specific Follower /// /// Authentication Tokens /// a user identifier which represent destination user /// an instance of XFriendshipFollower public async Task 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.GET ); return response; } /// /// Get Follower State of a User /// /// Authentication Tokens /// a user identifier which represent destination user /// an instance of XFriendshipState public async Task 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.GET ); return response; } /// /// Get Followers List Of Current User /// /// Authentication Tokens /// a collection of XFriendshipFollower public async Task> 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>( client, request, XHttpMethod.GET ); return response; } /// /// Get All Followers List Includes Blocked, Requested and etc /// of Current User /// /// Authentication Tokens /// a collection of XFriendshipFollower public async Task> 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>( client, request, XHttpMethod.GET ); return response; } /// /// Return Followers UserName's List of Current User /// /// Authentication Tokens /// a collection of UserNames public async Task> 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>( client, request, XHttpMethod.GET ); return response; } /// /// Retrieve All User's Followers based on Query Model ... /// /// Query Model Descriptor /// Dest User for Reading Followers /// Requester User's Descriptor /// public async Task> 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>( client, request, XHttpMethod.GET ); return response; } /// /// Check a User is in Followings of Current User /// /// Authentication Tokens /// a user identifier which represent destination user /// a boolean value public async Task 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.GET ); return response; } /// /// Get Specific Following Model /// /// Authentication Tokens /// a user identifier which represent destination user /// an instance of XFriendshipFollowing public async Task 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.GET ); return response; } /// /// Get Following State Relation between Specific User /// and Current User /// /// Authentication Tokens /// a user identifier which represent destination user /// an instance of XFriendshipState public async Task 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 { { XParam.XDestUser.GetStringValue (), destUser } } ); // var response = await RunRestRequest( client, request, XHttpMethod.GET ); return response; } /// /// Get Followings of Current User /// /// Authentication Tokens /// a collection of XFriendshipFollowing public async Task> 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>( client, request, XHttpMethod.GET ); return response; } /// /// Get All Following List Includes Blocked, Requested and etc /// of Current User /// /// Authentication Tokens /// a collection of XFriendshipFollowing public async Task> 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>( client, request, XHttpMethod.GET ); return response; } /// /// Return Following UserName's List of Current User /// /// Authentication Tokens /// a collection of UserNames public async Task> 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>( client, request, XHttpMethod.GET ); return response; } /// /// Retrieve All User's Followings based on Query Model ... /// /// Query Model Descriptor /// Dest User for Reading Followers /// Requester User's Descriptor /// public async Task> 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>( 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 { /// /// Prepare API Based Device to Open Actions ... /// /// 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 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 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 { { XAuthentication.TOKEN, token} }, queryStrings: new Dictionary { { XParam.XRequest.GetStringValue(), actionRequest } } ); // // Run Request and Retrieve Response ... var response = await RunRestRequestByResponse( 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(); if (responseModel.IsNull() || responseModel.Payload.IsNullOrEmpty() || responseToken != responseModel.Checksum || responseModel.Timestamp.FromTimestamp().IsExPired()) { XException.ActionFailed.Throw(); } // return result; } #endregion // #region GetUserInfo ... public async Task 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 GetUserInfo( XOpenActionInnerDto dto ) { // return await GetUserInfo( token: dto.Token, request: dto.Payload ); } public async Task 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(); if (requestModel.IsNull()) { XException.ActionFailed.Throw(); } // var resultJson = SecurityProvider.Decrypt(requestModel.Payload); var result = resultJson.FromJSON(); if (result.IsNull()) { XException.NotFound.Throw(); } // return result; } #endregion // #region GetUserInfos ... public async Task> 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> GetUserInfos( XOpenActionInnerDto dto ) { // return await GetUserInfos( token: dto.Token, request: dto.Payload ); } public async Task> 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(); if (requestModel.IsNull()) { XException.ActionFailed.Throw(); } // var resultJson = SecurityProvider.Decrypt(requestModel.Payload); var result = resultJson.FromJSON>(); 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 ... /// /// Retrieve User Names based on UserIds /// /// Authentication Tokens /// a comma seperated list of UserIds /// a collection of UserNames public async Task> 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 { { XParam.XIds.GetStringValue (), ids } } ); // var response = await RunRestRequest> ( client, request, XHttpMethod.GET ); return response; } /// /// get user ids and retrieve corresponding user names /// /// Authentication Tokens /// an instance of XUserNameIdRequest which represent required UserIds collection /// a collection of XUserNameIdResponse instance public async Task> 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> ( client, request, XHttpMethod.POST ); return response; } #endregion // #region Profile Actions ... /// /// Get Profile Object of Specific User /// /// Authentication Tokens /// determine's which user profile must be retrieved /// an instance of XUserProfileDto public async Task 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 { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam } } ); // var response = await RunRestRequest ( client, request, XHttpMethod.GET ); return response; } /// /// Retrieve Users Based On Query /// /// Authentication Tokens /// how to filter results based on XQuery structure /// an instance of XQueryResult of XUserProfileDto public async Task> 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> ( client, request, XHttpMethod.GET ); return response; } /// /// Retrieve Users Based On Query and Specified role /// /// Authentication Tokens /// an string which represent user role /// how to filter results based on XQuery structure /// if it's true the user must has exact role, otherwise top level users also listed /// an instance of XQueryResult of XUserProfileDto public async Task> 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 { { XParam.XRole.GetStringValue (), role }, { XParam.XForceRole.GetStringValue (), forceRole.AsHttpParamString () } } ); // // Attach XQuery to Request ... request = request.AttachXQuery (query); // var response = await RunRestRequest> ( client, request, XHttpMethod.GET ); return response; } /// /// Query Specified User's Profile Images /// /// Authentication Tokens /// determine's which user profile must be retrieved /// how to filter results based on XQuery structure /// an instance of XQueryResult of XProfileImage public async Task> 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 { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam } } ); // // Attach XQuery to Request ... request = request.AttachXQuery (query); // var response = await RunRestRequest> ( client, request, XHttpMethod.GET ); return response; } /// /// Update User Profile based on XProfileUpdateRequest (FirstName/LastName/DateOfBirth) /// /// Authentication Tokens /// determine's which user profile must be retrieved /// user update info, an instance of XProfileUpdateRequest /// an instance of XUserProfileDto public async Task 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 { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam } } ); request.AddJsonBody (model); // var response = await RunRestRequest ( client, request, XHttpMethod.POST ); return response; } /// /// Update a User Profile based on XProfileUpdateRequest Full /// /// Authentication Tokens /// determine's which user profile must be retrieved /// user update info, an instance of XProfileUpdateRequest /// an instance of XUserProfileDto public async Task 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 { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam } } ); request.AddJsonBody (model); // var response = await RunRestRequest ( client, request, XHttpMethod.POST ); return response; } /// /// Add a New Profile Image /// /// Authentication Tokens /// an specific File to upload, IFormFile /// an instance of XUserProfileDto public async Task 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 ( client, request, XHttpMethod.POST ); return response; } /// /// Add a New Collection of Profile Images /// /// Authentication Tokens /// a collection of Files to upload, IFormFileCollection /// an instance of XUserProfileDto public async Task 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 ( client, request, XHttpMethod.POST ); return response; } /// /// set Specified Profile Image as Avatar /// /// Authentication Tokens /// an integer which reperesent AvatarId to set as current Avatar /// an instance of XUserProfileDto public async Task 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 { { XParam.XId.GetStringValue (), id.ToString () } } ); // var response = await RunRestRequest ( client, request, XHttpMethod.POST ); return response; } /// /// Remove Profile Images /// /// Authentication Tokens /// a comma seperated list of avatarIds to remove /// an instance of XUserProfileDto public async Task 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 { { XParam.XIds.GetStringValue (), avatarIds } } ); // var response = await RunRestRequest ( 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 ... /// /// Check a User Selector is Available for Registration or Not /// /// an string value which reperesent a user /// a boolean value public async Task CanRegister (string userSelectByParam) { // // Validate ARgs ... validationProvider.NotEmpty (userSelectByParam); // var client = GetRestClient (); // // Check Endpoint ... var endpoint = XApiAccountEndpoint.CanRegisterUserName; var @params = new Dictionary { { 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 { { XParam.XMobileNumber.GetStringValue (), userSelectByParam } }; break; // case XUserSelectBy.Email: // endpoint = XApiAccountEndpoint.CanRegisterEmail; @params = new Dictionary { { XParam.XEmail.GetStringValue (), userSelectByParam } }; break; // default: throw XException.InvalidData.ToException (); } // var request = GetRestRequet ( endpoint, @params: @params ); // var response = await RunRestRequest ( client, request, XHttpMethod.GET ); return response; } /// /// Invite a User to Register on Dashboard /// /// Authentication Tokens /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse public async Task 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 ( client, request, XHttpMethod.POST ); return response; } /// /// Recieve some Basic Informations and Start Registration Proccess /// if they Valid /// /// Registration Proccess Starts with Invoking this Action /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse public async Task 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 ( client, request, XHttpMethod.POST ); return response; } /// /// Add User Account Informations /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse public async Task 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 ( client, request, XHttpMethod.POST ); return response; } /// /// Upload and Attach a Profile Image for User. this is an Optional Step /// /// user's requested action token /// an instance of IFormFile for user's Avatar /// an instance of XActionResponse public async Task 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 ( client, request, XHttpMethod.POST ); return response; } /// /// Finish Registrationn Proccess /// /// an instance of XActionRequest class which provider requirement for action /// 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 ( client, request, XHttpMethod.POST ); } /// /// Check User is Confirmed Email or not /// /// Authentication Tokens /// an string value which reperesent a user /// a boolean value public async Task 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 ( client, request, XHttpMethod.GET ); return response; } /// /// Check User is Confirmed Mobile or not /// /// Authentication Tokens /// an string value which reperesent a user /// a boolean value public async Task 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 ( client, request, XHttpMethod.GET ); return response; } /// /// Request Registration Confirm /// /// an instance of XActionRequest class which provider requirement for action /// 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 ( client, request, XHttpMethod.POST ); } /// /// Confirm Registration /// /// an instance of XActionRequest class which provider requirement for action /// 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 ( client, request, XHttpMethod.POST ); } /// /// Request For Mobile Number Change/Confirm /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse public async Task 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.Email, XUserSelectBy.MobileNumber }); // var client = GetRestClient (); // var request = GetRestRequet (XApiAccountEndpoint.RequestConfirmMobile); request.AddJsonBody (model); // var response = await RunRestRequest ( client, request, XHttpMethod.POST ); return response; } /// /// Confirm Requested Mobile Number /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse public async Task 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 ( client, request, XHttpMethod.POST ); return response; } /// /// Request For Email Address Change/Confirm /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse public async Task 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.Email, XUserSelectBy.MobileNumber }); // var client = GetRestClient (); // var request = GetRestRequet (XApiAccountEndpoint.RequestConfirmEmail); request.AddJsonBody (model); // var response = await RunRestRequest ( client, request, XHttpMethod.POST ); return response; } /// /// Confirm Requested Email Address /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse public async Task 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 ( client, request, XHttpMethod.POST ); return response; } /// /// Request Reset Password Action /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse public async Task 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.Email, XUserSelectBy.MobileNumber }); // var client = GetRestClient (); // var request = GetRestRequet (XApiAccountEndpoint.RequestResetPassword); request.AddJsonBody (model); // var response = await RunRestRequest ( client, request, XHttpMethod.POST ); return response; } /// /// Reset a User's Password /// /// an instance of XActionRequest class which provider requirement for action /// 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 ( 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 ... /// /// Query Open To Search User Profiles ... /// /// requested user's identifiers /// how to filter results based on XQuery structure /// an instance of XQueryResult of XUserProfileDto public async Task> 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>( 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 { /// /// an abstraction Implementation for Identity Provided Http Based Services ... /// public abstract class XBaseIdentityHttpProvider : IXBaseIdentityHttpProvider { /// /// Client Base Url ... /// /// public string BaseUrl { get; } /// /// Logger ... /// /// public ILogger Logger { get; } /// /// Powered Value ... /// /// public string XPoweredValue { get; } /// /// Default Client Timeout ... /// /// public int DefaultClientTimeout { get; } /// /// Default Buffering Chunk Size ... /// /// public int DefaultBufferingChunckSize { get; } /// /// Validation Provider ... /// /// public XValidationProvider ValidationProvider { get; } /// /// Token Provider ... /// private readonly IXTokenProvider tokenProvider; /// /// Identity Provider ... /// 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 ... /// /// Get an Instance of Http Client /// /// 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); } /// /// Get an Instance of RestClient /// /// 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); } /// /// Get an Instance of RestRequest /// /// /// /// /// /// /// public RestRequest GetRestRequet( Enum endpoint, bool addXPoweredValue = true, IDictionary @params = null, IDictionary headers = null, IDictionary 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; } /// /// Handle Call Specific Request and retrieve Response /// /// /// /// /// /// /// /// public async Task RunRestRequest( 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( 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(); return result; }, cancellationToken: cancellationToken); // return response; } /// /// Access a Get Request Stream as AsyncEnumerable ... /// /// /// /// /// /// /// /// /// /// /// public async Task StreamData( Enum endpoint, int bufferLength = 8194, bool addXPoweredValue = true, XTokenResponse tokens = null, IDictionary @params = null, IDictionary headers = null, IDictionary 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(cancellationToken: cancellationToken)) // // { // // // // // Console.WriteLine(item); // // // T value = item.IsNull() // // // ? default(T) // // // : item.FromBytes().FromJSON(); // // // // // // // 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(cancellationToken: cancellationToken)) // // { // // // // // T value = item.IsNull() // // ? default(T) // // : item.FromBytes().FromJSON(); // // // // // yield return value; // // } // // } } /// /// Handle Call Specified Request and Retrieve XBaseRestResponse ... /// /// /// /// /// /// /// /// an instance of XBaseRestResponse public async Task> RunRestRequestByResponse( 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( 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 { Response = resp, Model = resp.Content.FromJSON() }; // return result; }, cancellationToken: cancellationToken); // return response; } /// /// Get User SelectBy Param /// /// /// /// /// public string GetUserSelectByParam( XActionRequest model, bool forceNotNull = true, ICollection 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; } /// /// Prepare Url Address of Specified Enum by Filling Params /// and Query Strings Attach ... /// /// /// /// /// /// public string PrepareUrl( Enum endpoint, bool attachBaseUrl = false, IDictionary @params = null, IDictionary 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; } /// /// Prepare Url Address by Filling Params /// and Query Strings Attach ... /// /// /// /// /// /// public string PrepareUrl( string url, bool attachBaseUrl = false, IDictionary @params = null, IDictionary 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; } /// /// Converts UserInfo to TokenResponse model ... /// /// /// 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 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 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 ... /// /// Get an Instance of Http Client /// /// 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; } /// /// Get an Instance of RestClient /// /// 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; } /// /// Get an Instance of RestRequest /// public RestRequest GetRestRequet ( XApiAccountEndpoint endpoint, bool addXPoweredValue = true, IDictionary @params = null, IDictionary headers = null, IDictionary 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; } /// /// Handle Call Specific Request and retrieve Response /// /// /// /// /// /// public async Task RunRestRequest ( 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 ( 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 (); return result; }); // return response; } public async Task> RunRestRequestByResponse ( 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 ( 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 { Response = resp, Model = resp.Content.FromJSON () }; // return result; }); // return response; } /// /// Get User SelectBy Param /// /// /// /// /// public string GetUserSelectByParam ( XActionRequest model, bool forceNotNull = true, ICollection 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 DbContext; public XInMemoryTokenProvider () { // this.DbContext = new Dictionary (); } public async Task 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 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 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 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 RetrieveToken (string accessToken) { // // Validate Args ... if (accessToken.IsNullOrEmpty () || !await IsTokenExists (accessToken)) { return null; } // // Process Result ... var result = DbContext[accessToken]; return result; } public async Task 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 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 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 ... /// /// Validate XProxy Configuration for Client ... /// /// public bool ValidateConfiguration () { // var result = !Configuration.IsNull () && !Configuration.Host.IsNullOrEmpty () && Configuration.Host.IsValidUrl () && Configuration.Routes.HasChild (); // return result; } /// /// retrie Normalize Host ... /// /// 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; } /// /// retrieve all registred Routes ... /// /// public IEnumerable GetRoutes () { // // Validate Args ... if (Configuration.IsNull ()) { return null; } // return Configuration.Routes; } /// /// Retrieve all Prepared url of Routes ... /// /// public IEnumerable GetRouteUrls () { // var normalHost = NormalizeHost (); if (normalHost.IsNullOrEmpty ()) { return null; } // var result = GetRoutes () .Select (r => $"{normalHost}{r.Route}"); // return result; } /// /// Find an Specific Route ... /// /// /// public XProxyRouteDescriptor FindRoute (Expression> whereClause) { // // Validate Arg ... if (whereClause.IsNull ()) { return null; } // var whereFunc = whereClause .Compile (); // var result = GetRoutes () .FirstOrDefault (whereFunc); // return result; } /// /// Prepare a request url for a Proxy Route ... /// /// /// /// 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; } /// /// Prepare a request url for a Selected Proxy Route ... /// /// /// /// public string PrepareActionUrlForXProxyRoute ( string url, Expression> 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; } } }