Initial Commit ...

This commit is contained in:
2024-01-25 04:42:47 +03:30
commit 844b4c47ad
50 changed files with 2615 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
#
# DotNet ...
bin
obj
#
# Natural Docs ...
Documentation/*
+83
View File
@@ -0,0 +1,83 @@
using System.Collections.Generic;
using xIdentityModels.Dtos;
namespace xIdentityModels.Configurations {
public class XIdentityConfiguration {
//
// Define All Policies which can Apply to Identity Framework
// and also create a Default instance if it's not Exists
// in AppSetting JSON file ...
public XIdentityPolicy Policy { get; set; }
/// <summary>
/// the Security Key which used to Signing JWT Tokens
/// in Authentication Provider
/// </summary>
/// <value></value>
public string IdentitySecretKey { get; set; }
/// <summary>
/// the Issuer and Creator of Token
/// </summary>
/// <value></value>
public string IdentityIssuer { get; set; }
/// <summary>
/// the Audience and Consumer of Token
/// </summary>
/// <value></value>
public string IdentityAudience { get; set; }
/// <summary>
/// the List of Users Roles which must Provides in Identity
/// </summary>
/// <value></value>
public HashSet<string> IdentityRoles { get; set; }
/// <summary>
/// determines All new users must Assign to which role in Registration
/// </summary>
/// <value></value>
public string NewUsersRole { get; set; }
/// <summary>
/// determines New Registered Users Confirm Email or not
/// </summary>
/// <value></value>
public bool AutoConfirmNewUsersEmail { get; set; }
/// <summary>
/// determines New Registered Users Confirm PhoneNumber or not
/// </summary>
/// <value></value>
public bool AutoConfirmNewUsersPhoneNumber { get; set; }
/// <summary>
/// determines the Registration only Can be done with Invitation or not
/// </summary>
/// <value></value>
public bool RegistrationJustWithInvite { get; set; }
/// <summary>
/// determines the Registration required confirmation with email or not
/// </summary>
/// <value></value>
public bool RequireRegistrationConfirm { get; set; }
//
public int MaxNumberOfVerificationCodeSend { get; set; }
//
public int DeleyBetweenTwoVerificationCode { get; set; }
public int BannedDeviceTimeout { get; set; }
/// <summary>
/// an string Which Provide how long a action token can be valid
/// </summary>
/// <value></value>
public string ActionTokenExpirationDateProvider { get; set; }
public HashSet<XIdentityMessageDto> IdentityMessages { get; set; }
}
}
+37
View File
@@ -0,0 +1,37 @@
namespace xIdentityModels.Configurations {
/// <summary>
/// Provide the Available Policies with their Default Values
/// </summary>
public class XIdentityPolicy {
/// <summary>
/// User Account Lock Policies
/// </summary>
/// <value></value>
public XIdentityPolicyLockout Lockout { get; set; }
/// <summary>
/// User Password Policies
/// </summary>
/// <value></value>
public XIdentityPolicyPassword Password { get; set; }
/// <summary>
/// the Policies for User for Allowing to SignIn
/// </summary>
/// <value></value>
public XIdentityPolicySignIn SignIn { get; set; }
/// <summary>
/// the Policies for User
/// </summary>
/// <value></value>
public XIdentityPolicyUser User { get; set; }
/// <summary>
/// the policies which determines how to
/// populate user profile
/// </summary>
/// <value></value>
public XIdentityProfile Profile { get; set; }
}
}
+27
View File
@@ -0,0 +1,27 @@
namespace xIdentityModels.Configurations {
/// <summary>
/// User Account Lock Policies
/// </summary>
public class XIdentityPolicyLockout {
/// <summary>
/// The String which Provide Time Span Delais
/// between Lockout and UnLock a User Account
/// this Provided String the Parsed before Use
/// </summary>
/// <value></value>
public string LockoutTimeSpanProvider { get; set; }
/// <summary>
/// the Number of InvalidLoginAttemps which can
/// Happens to Lockout User Account
/// </summary>
/// <value></value>
public byte MaxFailedAccessAttempts { get; set; }
/// <summary>
/// determines Lockout mechanism allowed for new Users or not
/// </summary>
/// <value></value>
public bool AllowedForNewUsers { get; set; }
}
}
+42
View File
@@ -0,0 +1,42 @@
namespace xIdentityModels.Configurations {
/// <summary>
/// User Password Policies
/// </summary>
public class XIdentityPolicyPassword {
/// <summary>
/// determines Password must contains digits or not
/// </summary>
/// <value></value>
public bool RequireDigit { get; set; }
/// <summary>
/// determines the minimum allowed length for a password
/// </summary>
/// <value></value>
public byte RequiredLength { get; set; }
/// <summary>
/// determines the number of Unique Chars must be included in a Password
/// </summary>
/// <value></value>
public byte RequiredUniqueChars { get; set; }
/// <summary>
/// determines Password must contains LowerCase chars or not
/// </summary>
/// <value></value>
public bool RequireLowercase { get; set; }
/// <summary>
/// determines Password must contains Non-Alphabetical chars or not
/// </summary>
/// <value></value>
public bool RequireNonAlphanumeric { get; set; }
/// <summary>
/// determines Password must contains UpperCase chars or not
/// </summary>
/// <value></value>
public bool RequireUppercase { get; set; }
}
}
+26
View File
@@ -0,0 +1,26 @@
namespace xIdentityModels.Configurations {
/// <summary>
/// the Policies for User for Allowing to SignIn
/// </summary>
public class XIdentityPolicySignIn {
/// <summary>
/// determines only enabled users can SignIn
/// </summary>
/// <value></value>
public bool RequiredEnabled { get; set; }
/// <summary>
/// determines User must Confirm the given Email Address
/// before Login or not
/// </summary>
/// <value></value>
public bool RequireConfirmedEmail { get; set; }
/// <summary>
/// determines User must Confirm the given Phone Number
/// before Login or not
/// </summary>
/// <value></value>
public bool RequireConfirmedPhoneNumber { get; set; }
}
}
+50
View File
@@ -0,0 +1,50 @@
using System.Collections.Generic;
namespace xIdentityModels.Configurations {
/// <summary>
/// the Policies for User
/// </summary>
public class XIdentityPolicyUser {
/// <summary>
/// determines Allowed characters which can used in UserName
/// </summary>
/// <value></value>
public string AllowedUserNameCharacters { get; set; }
/// <summary>
/// determines the Email Address of each User must be Unique or not
/// </summary>
/// <value></value>
public bool RequireUniqueEmail { get; set; }
/// <summary>
/// minimum length of User Name
/// </summary>
/// <value></value>
public byte MinLength { get; set; }
/// <summary>
/// maximum length of user name
/// </summary>
/// <value></value>
public byte MaxLength { get; set; }
/// <summary>
/// Minimum Age for Registration
/// </summary>
/// <value></value>
public int MinAgeForRegistration { get; set; }
/// <summary>
/// Maximum age for Registration
/// </summary>
/// <value></value>
public int MaxAgeForRegistration { get; set; }
/// <summary>
/// a collection of invalid usernames
/// </summary>
/// <value></value>
public ICollection<string> InvalidUserNames { get; set; } = new HashSet<string> ();
}
}
+30
View File
@@ -0,0 +1,30 @@
namespace xIdentityModels.Configurations {
/// <summary>
/// contains user profile configuration
/// </summary>
public class XIdentityProfile {
/// <summary>
/// determines user profile contain email or not
/// </summary>
/// <value></value>
public bool ContainsEmail { get; set; }
/// <summary>
/// determines user profile contains phone number or not
/// </summary>
/// <value></value>
public bool ContainsPhoneNumber { get; set; }
/// <summary>
/// determines user profile contains Roles collection or not
/// </summary>
/// <value></value>
public bool ContainsRoles { get; set; }
public bool ContainsDateOfBirth { get; set; }
public bool ContainsLastLogin { get; set; }
public bool ContainsCreationDate { get; set; }
}
}
+16
View File
@@ -0,0 +1,16 @@
namespace xIdentityModels.Constants {
public enum XAction {
Authentication,
Invite,
Registration,
RequestMobileVerificationCode,
ConfirmMobileNumber,
RequestEmailVerificationCode,
ConfirmEmailAddress,
AddAccountInfo,
AttachProfileImage,
RequestResetPassword,
ProfileAction,
Finish,
}
}
+12
View File
@@ -0,0 +1,12 @@
namespace xIdentityModels.Constants {
/// <summary>
/// Represent State of Friendship between to Users
/// </summary>
public enum XFriendshipState {
None,
Pending,
Accepted,
Rejected,
Blocked,
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace xIdentityModels.Constants {
/// <summary>
/// Determines Available Genders
/// </summary>
public enum XGender {
Male,
Female
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace xIdentityModels.Constants {
public enum XUserSelectBy {
NotSpecified,
ID,
Username,
Email,
MobileNumber
}
}
+3
View File
@@ -0,0 +1,3 @@
namespace xIdentityModels.Constants {
public class xIdentityModelsConstants { }
}
+3
View File
@@ -0,0 +1,3 @@
namespace xIdentityModels.DI {
public static class XDIHelperExtension { }
}
+20
View File
@@ -0,0 +1,20 @@
namespace xIdentityModels.Descriptors {
/// <summary>
/// contains default users information
/// </summary>
public class XIdentityUserDescriptor {
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public string Password { get; set; }
public string Role { get; set; }
public bool IsEnable { get; set; }
public bool IsBanned { get; set; }
public string DateOfBirth { get; set; }
}
}
+83
View File
@@ -0,0 +1,83 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace xIdentityModels.Dtos
{
public class XDiscoveryDocumentDto
{
[JsonProperty ("issuer")]
public string Issuer { get; set; }
[JsonProperty ("jwks_uri")]
public string JwksUri { get; set; }
[JsonProperty ("authorization_endpoint")]
public string AuthorizationEndpoint { get; set; }
[JsonProperty ("token_endpoint")]
public string TokenEndpoint { get; set; }
[JsonProperty ("userinfo_endpoint")]
public string UserinfoEndpoint { get; set; }
[JsonProperty ("end_session_endpoint")]
public string EndSessionEndpoint { get; set; }
[JsonProperty ("check_session_iframe")]
public string CheckSessionIframe { get; set; }
[JsonProperty ("revocation_endpoint")]
public string RevocationEndpoint { get; set; }
[JsonProperty ("introspection_endpoint")]
public string IntrospectionEndpoint { get; set; }
[JsonProperty ("device_authorization_endpoint")]
public string DeviceAuthorizationEndpoint { get; set; }
[JsonProperty ("frontchannel_logout_supported")]
public bool FrontchannelLogoutSupported { get; set; }
[JsonProperty ("frontchannel_logout_session_supported")]
public bool FrontchannelLogoutSessionSupported { get; set; }
[JsonProperty ("backchannel_logout_supported")]
public bool BackchannelLogoutSupported { get; set; }
[JsonProperty ("backchannel_logout_session_supported")]
public bool BackchannelLogoutSessionSupported { get; set; }
[JsonProperty ("scopes_supported")]
public List<string> ScopesSupported { get; set; }
[JsonProperty ("claims_supported")]
public List<string> ClaimsSupported { get; set; }
[JsonProperty ("grant_types_supported")]
public List<string> GrantTypesSupported { get; set; }
[JsonProperty ("response_types_supported")]
public List<string> ResponseTypesSupported { get; set; }
[JsonProperty ("response_modes_supported")]
public List<string> ResponseModesSupported { get; set; }
[JsonProperty ("token_endpoint_auth_methods_supported")]
public List<string> TokenEndpointAuthMethodsSupported { get; set; }
[JsonProperty ("id_token_signing_alg_values_supported")]
public List<string> IdTokenSigningAlgValuesSupported { get; set; }
[JsonProperty ("subject_types_supported")]
public List<string> SubjectTypesSupported { get; set; }
[JsonProperty ("code_challenge_methods_supported")]
public List<string> CodeChallengeMethodsSupported { get; set; }
[JsonProperty ("request_parameter_supported")]
public bool RequestParameterSupported { get; set; }
[JsonProperty ("account_api")]
public string AccountApi { get; set; }
}
}
+14
View File
@@ -0,0 +1,14 @@
using xModels.Base;
using xIdentityModels.Constants;
namespace xIdentityModels.Dtos {
public class XFriendshipInfoDto : XBaseDto {
public string UserId { get; set; }
public bool IsFollower { get; set; }
public bool IsFollowing { get; set; }
public XFriendshipState FollowerState { get; set; }
public XFriendshipState FollowingState { get; set; }
public long Followers { get; set; }
public long Followings { get; set; }
}
}
+9
View File
@@ -0,0 +1,9 @@
using xModels.Base;
namespace xIdentityModels.Dtos {
public class XIdentityMessageDto : XBaseDto {
public string Language { get; set; }
public string ResourceTitle { get; set; }
public string TranslatedValue { get; set; }
}
}
+39
View File
@@ -0,0 +1,39 @@
using System;
using Newtonsoft.Json;
using xModels.Base;
namespace xIdentityModels.Dtos {
public class XProfileImageDto : XBaseDto {
public int Id { get; set; }
[JsonProperty (
"name",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty (
"thumb",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public string Thumb { get; set; }
[JsonProperty (
"path",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public string Path { get; set; }
[JsonProperty (
"thumbPath",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public string ThumbPath { get; set; }
[JsonProperty (
"creationDate",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public DateTime CreationDate { get; set; }
}
}
+8
View File
@@ -0,0 +1,8 @@
using System.Collections.Generic;
using xModels.Base;
namespace xIdentityModels.Dtos {
public class XUserNameIdRequest : XBaseDto {
public IEnumerable<string> Ids { get; set; }
}
}
+8
View File
@@ -0,0 +1,8 @@
using xModels.Base;
namespace xIdentityModels.Dtos {
public class XUserNameIdResponse : XBaseDto {
public string Id { get; set; }
public string UserName { get; set; }
}
}
+117
View File
@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using xIdentityModels.Constants;
using xModels.Base;
namespace xIdentityModels.Dtos {
public class XUserProfileDto : XBaseDto {
[JsonProperty (
"userId",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public string UserId { get; set; }
[JsonProperty (
"userName",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public string UserName { get; set; }
[JsonProperty (
"email",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public string Email { get; set; }
[JsonProperty (
"emailConfirmed",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public bool EmailConfirmed { get; set; }
[JsonProperty (
"phoneNumber",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public string PhoneNumber { get; set; }
[JsonProperty (
"phoneNumberConfirmed",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public bool PhoneNumberConfirmed { get; set; }
[JsonProperty (
"firstName",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public string FirstName { get; set; }
[JsonProperty (
"lastName",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public string LastName { get; set; }
[JsonProperty (
"dateOfBirth",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public DateTime? DateOfBirth { get; set; }
[JsonProperty (
"creationDate",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public DateTime? CreationDate { get; set; }
[JsonProperty (
"lastLogin",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public DateTime? LastLogin { get; set; }
[JsonProperty (
"avatar",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public string Avatar { get; set; }
[JsonProperty (
"gender",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public XGender Gender { get; set; }
[JsonProperty (
"friendshipInfo",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public XFriendshipInfoDto FriendshipInfo { get; set; }
[JsonProperty (
"roles",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public ICollection<string> Roles { get; set; } = new HashSet<string> ();
[JsonProperty (
"avatars",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public ICollection<XProfileImageDto> Avatars { get; set; } = new HashSet<XProfileImageDto> ();
[JsonProperty (
"isEnable",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public bool IsEnable { get; set; }
[JsonProperty (
"isBanned",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public bool IsBanned { get; set; }
}
}
+36
View File
@@ -0,0 +1,36 @@
using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xIdentityModels.Interfaces;
using xIdentityModels.Providers;
namespace xIdentityModels.Extensions {
public static class DIExtensions {
/// <summary>
/// since registering IXUserRoleHelper need to add default instance if
/// user not provided we create this helper ...
/// </summary>
/// <param name="services"></param>
public static void AddXUserRoleHandler (
this IServiceCollection services,
IXUserRoleHelper helper = null
) {
//
// Check if Provider is null ...
if (helper.IsNull ()) {
helper = services.GetRegisteredService<IXUserRoleHelper> ();
}
//
// check if Provider registered or not ...
if (helper.IsNull ()) {
//
// Create Default provider ...
services.AddSingleton<IXUserRoleHelper> (new XDefaultUserRoleHelper ());
} else {
//
// Register Given Helper ...
services.AddSingleton<IXUserRoleHelper> (helper);
}
}
}
}
+105
View File
@@ -0,0 +1,105 @@
using System.Collections.Generic;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Models;
namespace xIdentityModels.Extensions {
public static class XIdentityExtensions {
public static XUserSelectBy GetUserSelectByType (
this string source,
bool forceUserSelectByParamNotEmpty = true,
bool forceUserSelectByTypeMustSpecified = false
) {
//
// Validate Args ...
if (source.IsNullOrEmpty () &&
forceUserSelectByParamNotEmpty) {
XException.InvalidArgs.Throw ();
}
//
var result = XUserSelectBy.NotSpecified;
var userSelectByParam = source.ToNormalString ();
if (userSelectByParam.IsValidEmail ()) {
//
// Find User by Email ...
result = XUserSelectBy.Email;
} else if (userSelectByParam.IsValidMobileNumber ()) {
//
// Find User by Mobile Number ...
result = XUserSelectBy.MobileNumber;
} else if (userSelectByParam.IsGuid ()) {
//
// Find User By it's ID ...
result = XUserSelectBy.ID;
} else {
//
// UserName ...
result = XUserSelectBy.Username;
}
//
// Validation Result ...
if (forceUserSelectByTypeMustSpecified &&
result == XUserSelectBy.NotSpecified) {
XException.InvalidData.Throw ();
}
//
return result;
}
public static string GetUserSelectByParam (
this XActionRequest source,
bool forceNotNull = true,
ICollection<XUserSelectBy> excludes = null
) {
//
// Validate Args ...
if (source.IsNull ()) {
XException.InvalidArgs.Throw ();
}
//
var id = source.UserId;
var userName = source.UserName;
var email = source.Email;
var phoneNumber = source.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;
}
}
}
+120
View File
@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using xCommons.Extensions;
using xIdentityModels.Descriptors;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
namespace xIdentityModels.Extensions {
public static class XModelExtensions {
/// <summary>
/// /// Convert XIdentityUserDescriptor instance to XUser
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XUser ToXUser (this XIdentityUserDescriptor source) {
return new XUser {
Id = source.Id,
FirstName = source.FirstName,
LastName = source.LastName,
UserName = source.UserName,
Email = source.Email,
EmailConfirmed = source.EmailConfirmed,
PhoneNumber = source.PhoneNumber,
PhoneNumberConfirmed = source.PhoneNumberConfirmed,
IsEnable = true,
IsBanned = false,
CreationDate = DateTime.UtcNow,
DateOfBirth = DateTime.Parse (source.DateOfBirth)
};
}
/// <summary>
/// Check a User is Same as Descriptor User
/// </summary>
/// <param name="source"></param>
/// <param name="dest"></param>
/// <returns></returns>
public static bool IsSameAs (this XUser source, XIdentityUserDescriptor dest) {
//
if (source.IsNull () ||
dest.IsNull ()) {
return false;
}
//
var isSame = source.IsSameContent (dest, propertyWhiteList : new [] {
nameof (XIdentityUserDescriptor.FirstName),
nameof (XIdentityUserDescriptor.LastName),
nameof (XIdentityUserDescriptor.UserName),
nameof (XIdentityUserDescriptor.Email),
nameof (XIdentityUserDescriptor.EmailConfirmed),
nameof (XIdentityUserDescriptor.PhoneNumber),
nameof (XIdentityUserDescriptor.PhoneNumberConfirmed),
nameof (XIdentityUserDescriptor.IsEnable),
nameof (XIdentityUserDescriptor.IsBanned),
nameof (XIdentityUserDescriptor.DateOfBirth)
},
propertyValueCheckers : new [] {
new KeyValuePair<string, Func<XUser, XIdentityUserDescriptor, bool>> (
nameof (XIdentityUserDescriptor.DateOfBirth),
(user, descriptorUser) => {
//
var descriptorUserDateOfBirth = DateTime.Parse (descriptorUser.DateOfBirth);
return DateTime.Equals (user.DateOfBirth, descriptorUserDateOfBirth);
})
}
);
//
return isSame;
}
/// <summary>
/// Check to XDevice instance to be same or not
/// </summary>
/// <param name="source"></param>
/// <param name="dest"></param>
/// <returns></returns>
public static bool IsSameAs (this XDevice source, XDevice dest) {
//
if (source.IsNull () ||
dest.IsNull ()) {
return false;
}
//
var isSame = source.Os.ToNormalString () == dest.Os.ToNormalString () &&
source.OsVersion.ToNormalString () == dest.OsVersion.ToNormalString () &&
source.Browser.ToNormalString () == dest.Browser.ToNormalString () &&
source.UserAgent.ToNormalString () == dest.UserAgent.ToNormalString () &&
source.DeviceType == dest.DeviceType;
//
return isSame;
}
/// <summary>
/// convert UserClaimsInfo to TokenResponse ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XTokenResponse ToXTokenResponse (this XUserClaimsInfoDto source) {
//
if (source.IsNull () ||
(source.AccessToken.IsNullOrEmpty () && source.RefreshToken.IsNullOrEmpty ())) {
return null;
}
//
var result = new XTokenResponse {
AccessToken = source.AccessToken,
RefreshToken = source.RefreshToken,
ExpiresAt = source.ExpiresAt
};
//
return result;
}
}
}
+748
View File
@@ -0,0 +1,748 @@
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.IdentityModel.Tokens;
using xCommons.Constants;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Models;
namespace xIdentityModels.Extensions {
public static class XTokenExtensions {
//
#region Identity Token Extensions ...
/// <summary>
/// Convert a SecurityToken to it's Token String
/// </summary>
/// <param name="source"></param>
/// <param name="tokenHandler"></param>
/// <returns></returns>
public static string ToTokenString (
this SecurityToken source,
JwtSecurityTokenHandler tokenHandler
) {
return tokenHandler.WriteToken (source);
}
/// <summary>
/// Validate a Token
/// </summary>
/// <param name="token"></param>
/// <param name="tokenHandler"></param>
/// <param name="tokenValidationParams"></param>
/// <returns></returns>
public static bool ValidateToken (
this string token,
JwtSecurityTokenHandler tokenHandler,
TokenValidationParameters tokenValidationParams) {
//
if (token.IsNullOrEmpty ()) {
return false;
}
//
SecurityToken tokenObj = null;
try {
tokenHandler.ValidateToken (token, tokenValidationParams, out tokenObj);
} catch {
return false;
}
//
return tokenObj != null;
}
/// <summary>
/// Convert a token string to Security Token
/// </summary>
/// <param name="token"></param>
/// <param name="tokenHandler"></param>
/// <param name="tokenValidationParams"></param>
/// <returns></returns>
public static SecurityToken ToSecurityToken (
this string token,
JwtSecurityTokenHandler tokenHandler,
TokenValidationParameters tokenValidationParams) {
//
if (token.IsNullOrEmpty () ||
!token.ValidateToken (tokenHandler, tokenValidationParams)) {
//
return null;
}
//
// convert token from String to JWTSecurity Token ...
try {
return tokenHandler.ReadToken (token);
} catch {
return null;
}
}
/// <summary>
/// Parse Action Token and return Corresponding RegistrationRequestDto
/// </summary>
/// <param name="token"></param>
/// <param name="tokenHandler"></param>
/// <param name="tokenValidationParams"></param>
/// <returns></returns>
public static XActionRequestToken ParseActionRequestToken (
this string token,
JwtSecurityTokenHandler tokenHandler,
TokenValidationParameters tokenValidationParams) {
//
if (token.IsNullOrEmpty () ||
!token.ValidateToken (tokenHandler, tokenValidationParams)) {
//
return null;
}
//
// convert token from String to JWTSecurity Token ...
JwtSecurityToken tokenObj = null;
try {
tokenObj = tokenHandler.ReadToken (token) as JwtSecurityToken;
} catch {
return null;
}
//
if (tokenObj == null) {
return null;
}
//
// Extract Registered Payload Claims ...
var mCurrentStepClaim = tokenObj.Claims
.FirstOrDefault (c => c.Type == nameof (XActionRequestToken.Action));
var mContextClaim = tokenObj.Claims
.FirstOrDefault (c => c.Type == nameof (XActionRequestToken.Context));
var mTokenClaim = tokenObj.Claims
.FirstOrDefault (c => c.Type == nameof (XActionRequestToken.Token));
//
// Check All Claims to be NotNull ...
if (mCurrentStepClaim == null ||
mContextClaim == null ||
mTokenClaim == null) {
return null;
}
//
// Reading all Claims Values ...
var mCurrentStepStr = mCurrentStepClaim.Value;
var mCurrentStep = 0;
try {
int.TryParse (mCurrentStepStr, out mCurrentStep);
} catch { }
//
var mContext = mContextClaim.Value.IsNullOrEmpty () ?
null : mContextClaim.Value.FromJSON<XActionRequestContext> ();
var mToken = mTokenClaim.Value;
//
// Create Instance of UserInvite ...
var result = new XActionRequestToken {
Action = (XAction) mCurrentStep,
Context = mContext,
Token = mToken
};
//
return result;
}
/// <summary>
/// Check to ActionRequestContext object is same or not
/// </summary>
/// <param name="source"></param>
/// <param name="dest"></param>
/// <returns></returns>
public static bool IsSameAs (
this XActionRequestContext source,
XActionRequestContext dest
) {
//
if (source == null ||
dest == null) {
return false;
}
//
var result = source.ToJSON () == dest.ToJSON ();
//
return result;
}
/// <summary>
/// Convert a RegistrationRequestDto object to it's jwt token Claims
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static Claim[] ToJwtClaims (this XActionRequestToken source) {
//
// Generate Required Fields ...
var action = source.Action;
var context = source.Context;
var token = source.Token;
//
// Generate Claims Array ...
var claims = new Claim[] {
new Claim (nameof (XActionRequestToken.Action), ((int) action).ToString (), ClaimValueTypes.Integer),
new Claim (nameof (XActionRequestToken.Context), context == null ? "" : context.ToJSON (), ClaimValueTypes.String),
new Claim (nameof (XActionRequestToken.Token), token.IsNullOrEmpty () ? "" : token, ClaimValueTypes.String)
};
//
// Return Result ...
return claims;
}
/// <summary>
/// Generate a SecurityToken based on RegistrationRequestDto object
/// </summary>
/// <param name="source"></param>
/// <param name="tokenHandler"></param>
/// <param name="tokenDescriptor"></param>
/// <returns></returns>
public static SecurityToken ToJwtToken (
this XActionRequestToken source,
JwtSecurityTokenHandler tokenHandler,
SecurityTokenDescriptor tokenDescriptor) {
//
// Getting Claims ...
var claims = source.ToJwtClaims ();
tokenDescriptor.Subject = new ClaimsIdentity (claims);
//
// Generate Token Object ...
var tokenObject = tokenHandler.CreateToken (tokenDescriptor);
//
// Return Result ...
return tokenObject;
}
#endregion
//
#region IdentityServer Token Extensions ...
/// <summary>
/// Retrieve Tokens From Headers
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XTokenResponse RetrieveTokens (this HttpRequest source) {
//
var accessToken = source.Headers[XAuthorization.Header].ToString ();
var refreshToken = source.Headers[XAuthorization.RefreshToken].ToString ();
//
var expiresAtStr = source.Headers[XAuthorization.ExpiresAt].ToString ();
long expiresAt = expiresAtStr.ConvertTo<long> ();
//
if (accessToken
.ToNormalString ()
.Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
}
//
return new XTokenResponse {
AccessToken = accessToken,
RefreshToken = refreshToken,
ExpiresAt = expiresAt
};
}
/// <summary>
/// Retrieve Tokens From HttpContext
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static async Task<XTokenResponse> RetrieveTokens (this HttpContext source) {
//
var accessToken = await source.GetTokenAsync (XAuthorization.AccessToken);
if (accessToken
.ToNormalString ()
.Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
}
var refreshToken = await source.GetTokenAsync (XAuthorization.RefreshToken);
var expiresAtStr = await source.GetTokenAsync (XAuthorization.ExpiresAt);
long expiresAt = expiresAtStr.ConvertTo<long> ();
//
var headerRequestTokens = source.Request.RetrieveTokens ();
//
var result = new XTokenResponse {
AccessToken = accessToken ?? headerRequestTokens.AccessToken,
RefreshToken = refreshToken ?? headerRequestTokens.RefreshToken,
ExpiresAt = expiresAt != 0 ? expiresAt : headerRequestTokens.ExpiresAt
};
//
return result;
}
/// <summary>
/// Retrieve Tokens From ActionExecutingContext
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static async Task<XTokenResponse> RetrieveTokens (this ActionExecutingContext source) {
//
var result = await source.HttpContext.RetrieveTokens ();
return result;
}
/// <summary>
/// Retrieve Tokens From XUserInfo instance
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XTokenResponse RetrieveTokens (this XUserClaimsInfoDto source) {
//
var result = new XTokenResponse {
AccessToken = source.AccessToken,
RefreshToken = source.RefreshToken,
ExpiresAt = source.ExpiresAt
};
//
return result;
}
/// <summary>
/// Retrieve Tokens From IHeader Dictionary
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XTokenResponse RetrieveTokens (this IHeaderDictionary source) {
//
var accessToken = source[XAuthorization.Header].ToString () ?? "";
if (accessToken
.ToNormalString ()
.Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
}
//
var refreshToken = source[XAuthorization.RefreshToken].ToString () ?? "";
//
var expiresAtStr = source[XAuthorization.ExpiresAt].ToString () ?? "";
var expiresAt = expiresAtStr.ConvertTo<long> ();
//
var result = new XTokenResponse {
AccessToken = accessToken,
RefreshToken = refreshToken,
ExpiresAt = expiresAt
};
//
return result;
}
/// <summary>
/// Generate XTokenResponse instance based on TokenResponse
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XLoginResponse CreateXLoginResponse (this TokenResponse source) {
//
if (source.IsNull () ||
source.IsError) {
XException.InvalidToken.Throw ();
}
//
var expiresAt = new DateTimeOffset (DateTime.UtcNow)
.ToUnixTimeSeconds () +
source.ExpiresIn;
//
var result = new XLoginResponse {
AccessToken = source.AccessToken,
RefreshToken = source.RefreshToken,
ExpiresAt = expiresAt
};
//
return result;
}
/// <summary>
/// Generate XTokenResponse instance based on TokenResponse
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XTokenResponse CreateXTokenResponse (this TokenResponse source) {
//
if (source.IsNull () ||
source.IsError) {
XException.InvalidToken.Throw ();
}
//
var expiresAt = new DateTimeOffset (DateTime.UtcNow)
.ToUnixTimeSeconds () +
source.ExpiresIn;
//
var result = new XTokenResponse {
AccessToken = source.AccessToken,
RefreshToken = source.RefreshToken,
ExpiresAt = expiresAt
};
//
return result;
}
/// <summary>
/// Convert XLoginResponse to XTokenResponse
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XTokenResponse ToXTokenResponse (this XLoginResponse source) {
//
if (source.IsNull ()) {
return null;
}
//
return new XTokenResponse {
AccessToken = source.AccessToken,
RefreshToken = source.RefreshToken,
ExpiresAt = source.ExpiresAt
};
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific IHeaderDictionary instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (
this IHeaderDictionary source,
XLoginResponse model,
string secret = null
) {
//
source.Remove (XAuthorization.Header);
source.Remove (XAuthorization.RefreshToken);
source.Remove (XAuthorization.ExpiresAt);
source.Remove (XAuthorization.RevisionChecksum);
//
source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}");
source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}");
source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}");
//
if (!secret.IsNullOrEmpty ()) {
var revisionChecksum = model.GetRevisionChecksum (secret);
source.Add (XAuthorization.RevisionChecksum, revisionChecksum);
}
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific IHeaderDictionary instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (
this IHeaderDictionary source,
XTokenResponse model,
string secret = null
) {
//
source.Remove (XAuthorization.Header);
source.Remove (XAuthorization.RefreshToken);
source.Remove (XAuthorization.ExpiresAt);
source.Remove (XAuthorization.RevisionChecksum);
//
source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}");
source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}");
source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}");
//
if (!secret.IsNullOrEmpty ()) {
var revisionChecksum = model.GetRevisionChecksum (secret);
source.Add (XAuthorization.RevisionChecksum, revisionChecksum);
}
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific IHeaderDictionary instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (
this HttpRequestHeaders source,
XLoginResponse model
) {
//
source.Remove (XAuthorization.Header);
source.Remove (XAuthorization.RefreshToken);
source.Remove (XAuthorization.ExpiresAt);
source.Remove (XAuthorization.RevisionChecksum);
//
source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}");
source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}");
source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}");
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific IHeaderDictionary instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (
this HttpRequestHeaders source,
XTokenResponse model
) {
//
source.Remove (XAuthorization.Header);
source.Remove (XAuthorization.RefreshToken);
source.Remove (XAuthorization.ExpiresAt);
source.Remove (XAuthorization.RevisionChecksum);
//
source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}");
source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}");
source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}");
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific HttpRequest instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (
this HttpRequest source,
XLoginResponse model
) {
source.Headers.SetXAuthenticationTokens (model);
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific HttpRequest instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (
this HttpRequest source,
XTokenResponse model
) {
source.Headers.SetXAuthenticationTokens (model);
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific HttpRequest instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (
this HttpRequestMessage source,
XLoginResponse model
) {
source.Headers.SetXAuthenticationTokens (model);
}
/// <summary>
/// Add Authorization Tokens in Headers of
/// Specific HttpRequest instance
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (
this HttpRequestMessage source,
XTokenResponse model
) {
source.Headers.SetXAuthenticationTokens (model);
}
/// <summary>
/// Add ReNewed Authorization Tokens in Headers of
/// Specific Response.
/// Later in HttpInterceptors we can Look for AccessToken-ReNewed
/// header Value and Renew User Tokens based on it
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (
this HttpResponse source,
XLoginResponse model,
string secret
) {
source.Headers.SetXAuthenticationTokens (model, secret);
}
/// <summary>
/// Add ReNewed Authorization Tokens in Headers of
/// Specific Response.
/// Later in HttpInterceptors we can Look for AccessToken-ReNewed
/// header Value and Renew User Tokens based on it
/// </summary>
/// <param name="source"></param>
/// <param name="model"></param>
public static void SetXAuthenticationTokens (
this HttpResponse source,
XTokenResponse model,
string secret
) {
source.Headers.SetXAuthenticationTokens (model, secret);
}
/// <summary>
/// Determines a Token Can Refrsh or not
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool IsRefreshable (this XLoginResponse source) {
//
var containsTokenData = !source.IsNull () &&
!source.AccessToken.IsNullOrEmpty () &&
!source.RefreshToken.IsNullOrEmpty ();
if (!containsTokenData) {
return false;
}
//
var current = new DateTimeOffset (DateTime.UtcNow)
.ToUnixTimeSeconds ();
//
// var result = current > source.ExpiresAt || current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration;
var result = current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration;
//
return result;
}
/// <summary>
/// Determines a Token Can Refrsh or not
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool IsRefreshable (this XTokenResponse source) {
//
var containsTokenData = !source.IsNull () &&
!source.AccessToken.IsNullOrEmpty () &&
!source.RefreshToken.IsNullOrEmpty ();
if (!containsTokenData) {
return false;
}
//
var current = new DateTimeOffset (DateTime.UtcNow)
.ToUnixTimeSeconds ();
//
// var result = current > source.ExpiresAt || current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration;
var result = current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration;
//
return result;
}
/// <summary>
/// Generate a Revision Checksum for new Tokens
/// </summary>
/// <param name="source"></param>
/// <param name="secret"></param>
/// <returns></returns>
public static string GetRevisionChecksum (
this XLoginResponse source,
string secret
) {
return (source.AccessToken +
secret +
source.RefreshToken +
secret +
source.ExpiresAt.ToString ()
)
.ToMd5String ();
}
/// <summary>
/// Generate a Revision Checksum for new Tokens
/// </summary>
/// <param name="source"></param>
/// <param name="secret"></param>
/// <returns></returns>
public static string GetRevisionChecksum (
this XTokenResponse source,
string secret
) {
return (source.AccessToken +
secret +
source.RefreshToken +
secret +
source.ExpiresAt.ToString ()
)
.ToMd5String ();
}
/// <summary>
/// Check an XLoginResponse instance is Valid with it's revision
/// </summary>
/// <param name="source"></param>
/// <param name="checksum"></param>
/// <param name="secret"></param>
/// <returns></returns>
public static bool ValidateRevisionChecksum (
this XLoginResponse source,
string checksum,
string secret
) {
//
var xChecksum = source.GetRevisionChecksum (secret);
return checksum == xChecksum;
}
/// <summary>
/// Check an XTokenResponse instance is Valid with it's revision
/// </summary>
/// <param name="source"></param>
/// <param name="checksum"></param>
/// <param name="secret"></param>
/// <returns></returns>
public static bool ValidateRevisionChecksum (
this XTokenResponse source,
string checksum,
string secret
) {
//
var xChecksum = source.GetRevisionChecksum (secret);
return checksum == xChecksum;
}
#endregion
}
}
+3
View File
@@ -0,0 +1,3 @@
namespace xIdentityModels.Extensions {
public static class xIdentityModelsExtensions { }
}
+9
View File
@@ -0,0 +1,9 @@
using xIdentityModels.Models;
namespace xIdentityModels.Interfaces {
public interface IXUserRoleHelper {
bool canReadCriticalData (XUserClaimsInfoDto userInfo);
bool canDoDangerousAction (XUserClaimsInfoDto userInfo);
bool isInRole (XUserClaimsInfoDto userInfo, string role);
}
}
+93
View File
@@ -0,0 +1,93 @@
using System;
using Microsoft.AspNetCore.Http;
using xIdentityModels.Navigations;
namespace xIdentityModels.Models {
/// <summary>
/// represent a system wide actions
/// </summary>
public class XActionRequest {
/// <summary>
/// Client Device Locale
/// </summary>
/// <value>user's client device local such as en-US</value>
public string Lang { get; set; } = null;
/// <summary>
/// Requested Action Token
/// </summary>
/// <value>a hashed content</value>
public string ActionToken { get; set; } = null;
/// <summary>
/// user's device
/// </summary>
/// <value>an instance of <see>XDevice</see> which represent user's device</value>
public XDevice Device { get; set; } = null;
/// <summary>
/// FirstName
/// </summary>
/// <value>users FirstName</value>
public string FirstName { get; set; } = null;
/// <summary>
/// LastName
/// </summary>
/// <value>user's LastName</value>
public string LastName { get; set; } = null;
/// <summary>
/// an Optional Value which represetns User's DateOfBirth
/// </summary>
/// <value>user's DateOfBirth</value>
public DateTime? DateOfBirth { get; set; } = DateTime.MinValue;
/// <summary>
/// User's Id
/// </summary>
/// <value>a GUID string which represent user's Id</value>
public string UserId { get; set; } = null;
/// <summary>
/// UserName
/// </summary>
/// <value>user's UserName</value>
public string UserName { get; set; } = null;
/// <summary>
/// Email
/// </summary>
/// <value>user's Email address</value>
public string Email { get; set; } = null;
/// <summary>
/// MobileNumber / PhoneNumber
/// </summary>
/// <value>user's PhoneNumber</value>
public string MobileNumber { get; set; } = null;
/// <summary>
/// Password
/// </summary>
/// <value>user's Password</value>
public string Password { get; set; } = null;
/// <summary>
/// NewPassword
/// </summary>
/// <value>a passwor string which used to Change/Reset password</value>
public string NewPassword { get; set; } = null;
/// <summary>
/// EmailVerificationCode
/// </summary>
/// <value>a Verification Code which assign to user's for confirm it's Email Address</value>
public string EmailVerificationCode { get; set; } = null;
/// <summary>
/// MobileVerificationCode
/// </summary>
/// <value>a Verification Code which assign to user's for confirm it's Phone Number</value>
public string MobileVerificationCode { get; set; } = null;
/// <summary>
/// Thumbnail
/// </summary>
/// <value>an instance of <see>IFormFile</see> which is used as user's avatar</value>
public IFormFile Thumbnail { get; set; }
/// <summary>
/// ReturnUrl
/// </summary>
/// <value>
/// a url string which used in many used cases for providing a way to lead users to right places.
/// </value>
public string ReturnUrl { get; set; } = null;
}
}
+33
View File
@@ -0,0 +1,33 @@
using System;
using Microsoft.AspNetCore.Http;
using xIdentityModels.Navigations;
namespace xIdentityModels.Models {
public class XActionRequestContext {
//
public string Lang { get; set; }
//
public string UserId { get; set; }
public string UserName { get; set; }
//
public string MobileNumber { get; set; }
public string MobileVerificationCode { get; set; }
public bool MobileVerified { get; set; }
//
public string Email { get; set; }
public string EmailVerificationCode { get; set; }
public bool EmailVerified { get; set; }
//
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
//
public XDevice Device { get; set; }
public IFormFile Thubmnail { get; set; }
}
}
+22
View File
@@ -0,0 +1,22 @@
using xCommons.Extensions;
using xIdentityModels.Constants;
namespace xIdentityModels.Models {
public class XActionRequestToken {
public XAction Action { get; set; }
public XActionRequestContext Context { get; set; }
public string Token { get; set; }
public void Prepare (string secret) {
Token = (Action.ToString () +
secret +
Context.ToJSON ()).ToMd5String ();
}
public bool Validate (string secret) {
return (Action.ToString () +
secret +
Context.ToJSON ()).ToMd5String () == Token;
}
}
}
+29
View File
@@ -0,0 +1,29 @@
using System;
using Newtonsoft.Json;
namespace xIdentityModels.Models {
/// <summary>
/// represent a system wide action result
/// </summary>
public class XActionResponse {
/// <summary>
/// ActionToken
/// </summary>
/// <value>a hashed string which carry required info for doing system actions.</value>
[JsonProperty (
"token",
Required = Required.Default,
NullValueHandling = NullValueHandling.Ignore)]
public string Token { get; set; }
/// <summary>
/// ActionToken Lifetime
/// </summary>
/// <value>an instance of <see>DateTime</see> which represent token expiration time</value>
[JsonProperty (
"expiration",
Required = Required.DisallowNull,
NullValueHandling = NullValueHandling.Ignore)]
public DateTime Expiration { get; set; }
}
}
+23
View File
@@ -0,0 +1,23 @@
using System;
using System.ComponentModel.DataAnnotations.Schema;
using xCommons.Extensions;
using xIdentityModels.Navigations;
using xModels.Base;
namespace xIdentityModels.Models {
public class XBannedDevice : XBaseIntIDEntity {
public DateTime BannedOn { get; set; }
public string DeviceStr { get; set; }
[NotMapped]
public XDevice Device {
get {
return DeviceStr.FromJSON<XDevice> ();
}
set {
DeviceStr = value.ToJSON ();
}
}
}
}
+35
View File
@@ -0,0 +1,35 @@
using System.ComponentModel.DataAnnotations;
using xIdentityModels.Navigations;
namespace xIdentityModels.Models {
/// <summary>
/// Represent Requirements for Authenticationg a User
/// </summary>
public class XLoginRequest {
/// <summary>
/// how select an specific User
/// </summary>
/// <value>an string value which represent how system select user such as: UserName, Email Address or MobileNumber</value>
[Required]
public string UserSelectBy { get; set; }
/// <summary>
/// user's password
/// </summary>
/// <value>an string which represent user's pasword</value>
[Required]
public string Password { get; set; }
/// <summary>
/// user's device
/// </summary>
/// <value>an instance of <see>XDevice</see> which represent user's device</value>
public XDevice Device { get; set; }
/// <summary>
/// user's language
/// </summary>
/// <value>an string which represent user's language and locale, such as: en-US</value>
public string Language { get; set; }
}
}
+7
View File
@@ -0,0 +1,7 @@
using xIdentityModels.Dtos;
namespace xIdentityModels.Models {
public class XLoginResponse : XTokenResponse {
public XUserProfileDto Profile { get; set; }
}
}
+22
View File
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using xIdentityModels.Constants;
namespace xIdentityModels.Models {
public class XProfileUpdateRequest {
public string Email { get; set; }
public bool? EmailConfirmed { get; set; }
public string PhoneNumber { get; set; }
public bool? PhoneNumberConfirmed { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Avatar { get; set; }
public DateTime? DateOfBirth { get; set; }
public DateTime? CreationDate { get; set; }
public DateTime? LastLogin { get; set; }
public XGender? Gender { get; set; }
public ICollection<string> Roles { get; set; } = new HashSet<string> ();
public bool? IsEnable { get; set; }
public bool? IsBanned { get; set; }
}
}
+26
View File
@@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations.Schema;
using xCommons.Extensions;
using xIdentityModels.Constants;
using xIdentityModels.Navigations;
using xModels.Base;
namespace xIdentityModels.Models {
public class XToken : XBaseIntIDEntity {
public string Token { get; set; }
public string Hash { get; set; }
public string UserSelectByParam { get; set; }
public string DeviceStr { get; set; }
public XAction Type { get; set; }
[NotMapped]
public XDevice Device {
get {
return DeviceStr.FromJSON<XDevice> ();
}
set {
DeviceStr = value.ToJSON ();
}
}
}
}
+10
View File
@@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
namespace xIdentityModels.Models {
public class XTokenResponse {
[Required]
public string AccessToken { get; set; }
public string RefreshToken { get; set; }
public long ExpiresAt { get; set; }
}
}
+195
View File
@@ -0,0 +1,195 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using xCommons.Constants;
using xCommons.Extensions;
using xCommons.Helpers;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xModels.Base;
namespace xIdentityModels.Models {
public class XUserClaimsInfoDto : XBaseDto {
//
#region Properties ...
public string AccessToken { get; }
public string RefreshToken { get; }
public long ExpiresAt { get; }
public string UserId { get; }
public string UserName { get; }
public string FirstName { get; }
public string LastName { get; }
public string Picture { get; }
public string Email { get; }
public string PhoneNumber { get; }
public XGender Gender { get; }
public bool IsBanned { get; }
public bool IsEnabled { get; }
public bool EmailConfirmed { get; }
public bool PhoneNumberConfirmed { get; }
public long? ExpiredOn { get; }
public long? AuthenticatedOn { get; }
public DateTime? BrithDate { get; }
public IEnumerable<string> Issuers { get; } = new HashSet<string> ();
public IEnumerable<string> Audiences { get; } = new HashSet<string> ();
public IEnumerable<string> ClientIds { get; } = new HashSet<string> ();
public IEnumerable<string> Scopes { get; } = new HashSet<string> ();
public IEnumerable<string> Roles { get; } = new HashSet<string> ();
#endregion
//
public XUserClaimsInfoDto () { }
public XUserClaimsInfoDto (
string accessToken,
string refreshToken,
long expiresAt,
IEnumerable<Claim> claims
) {
//
// refreshToken.IsNullOrEmpty ()
if (claims.IsNull () ||
accessToken.IsNullOrEmpty ()) {
XException.InvalidArgs.Throw ();
}
//
// Attach XLogin Properties ...
AccessToken = accessToken;
RefreshToken = refreshToken;
ExpiresAt = expiresAt;
//
if (!claims.IsNull ()) {
UserId = claims.FirstOrDefault (c => c.Type == XCustomClaims.UserId)?.Value ?? "";
UserName = claims.FirstOrDefault (c => c.Type == XCustomClaims.UserName)?.Value ?? "";
FirstName = claims.FirstOrDefault (c => c.Type == XCustomClaims.FirstName)?.Value ?? "";
LastName = claims.FirstOrDefault (c => c.Type == XCustomClaims.LastName)?.Value ?? "";
Picture = claims.FirstOrDefault (c => c.Type == XCustomClaims.Picture)?.Value ?? "";
Email = claims.FirstOrDefault (c => c.Type == XCustomClaims.Email)?.Value ?? null;
PhoneNumber = claims.FirstOrDefault (c => c.Type == XCustomClaims.PhoneNumber)?.Value ?? null;
//
// Handle Gender ...
var genders = ObjectHelper.ToEnumerableKeys<XGender> ();
var genderStr = claims.FirstOrDefault (c => c.Type == XCustomClaims.Gender).Value ?? null;
if (genderStr.IsNullOrEmpty ()) {
Gender = XGender.Male;
} else {
Gender = genderStr.GetValue<XGender> ();
}
//
// Handle IsBanned ...
var isBannedStr = claims.FirstOrDefault (c => c.Type == XCustomClaims.IsBanned).Value ?? null;
if (isBannedStr.IsNullOrEmpty ()) {
IsBanned = false;
} else {
//
var isBanned = false;
Boolean.TryParse (isBannedStr, out isBanned);
//
IsBanned = isBanned;
}
//
// Handle IsEnabled ...
var isEnabledStr = claims.FirstOrDefault (c => c.Type == XCustomClaims.IsEnabled).Value ?? null;
if (isEnabledStr.IsNullOrEmpty ()) {
IsEnabled = false;
} else {
//
var isEnabled = false;
Boolean.TryParse (isEnabledStr, out isEnabled);
//
IsEnabled = isEnabled;
}
//
// Handle Email Confirmed ...
var emailConfirmedStr = claims.FirstOrDefault (c => c.Type == XCustomClaims.EmailVerified).Value ?? null;
if (emailConfirmedStr.IsNullOrEmpty ()) {
EmailConfirmed = false;
} else {
//
var emailConfirmed = false;
Boolean.TryParse (emailConfirmedStr, out emailConfirmed);
//
EmailConfirmed = emailConfirmed;
}
//
// Handle PhoneNumber Confirmed ...
var phoneNumberConfirmedStr = claims.FirstOrDefault (c => c.Type == XCustomClaims.PhoneNumberVerified).Value ?? null;
if (phoneNumberConfirmedStr.IsNullOrEmpty ()) {
PhoneNumberConfirmed = false;
} else {
//
var phoneNumberConfirmed = false;
Boolean.TryParse (phoneNumberConfirmedStr, out phoneNumberConfirmed);
//
PhoneNumberConfirmed = phoneNumberConfirmed;
}
//
// Handle ExpiredOn ...
var expiredOnStr = claims.FirstOrDefault (c => c.Type == XCustomClaims.ExpiredOn).Value ?? null;
if (expiredOnStr.IsNullOrEmpty ()) {
ExpiredOn = null;
} else {
//
long expiredOn = 0;
long.TryParse (expiredOnStr, out expiredOn);
//
ExpiredOn = expiredOn;
}
//
// Handle AuthenticatedOn ...
var authenticatedOnStr = claims.FirstOrDefault (c => c.Type == XCustomClaims.AuthenticatedOn).Value ?? null;
if (authenticatedOnStr.IsNullOrEmpty ()) {
AuthenticatedOn = null;
} else {
//
long authenticatedOn = 0;
long.TryParse (authenticatedOnStr, out authenticatedOn);
//
AuthenticatedOn = authenticatedOn;
}
//
// Handle BrithDate ...
var brithDateStr = claims.FirstOrDefault (c => c.Type == XCustomClaims.BrithDate)?.Value ?? "";
if (brithDateStr.IsNullOrEmpty ()) {
// BrithDate = null;
} else {
//
DateTime bDate;
DateTime.TryParse (brithDateStr, out bDate);
//
BrithDate = bDate;
}
//
Issuers = claims.Where (c => c.Type == XCustomClaims.Issuer) ?
.Select (c => c.Value) ?? new HashSet<string> ();
Audiences = claims.Where (c => c.Type == XCustomClaims.Audience) ?
.Select (c => c.Value) ?? new HashSet<string> ();
ClientIds = claims.Where (c => c.Type == XCustomClaims.ClientId) ?
.Select (c => c.Value) ?? new HashSet<string> ();
Scopes = claims.Where (c => c.Type == XCustomClaims.Scope) ?
.Select (c => c.Value) ?? new HashSet<string> ();
Roles = claims.Where (c => c.Type == XCustomClaims.Role) ?
.Select (c => c.Value) ?? new HashSet<string> ();
}
}
}
}
+41
View File
@@ -0,0 +1,41 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using xCommons.Extensions;
using xIdentityModels.Navigations;
using xModels.Base;
namespace xIdentityModels.Models {
public class XVerificationRequest : XBaseIntIDEntity {
[Required]
public string VerificationCode { get; set; }
public int NumberOfTries { get; set; }
public DateTime LastTryOn { get; set; }
[NotMapped]
public XActionRequestToken Request {
get {
return RequestStr.FromJSON<XActionRequestToken> ();
}
set {
RequestStr = value.ToJSON ();
}
}
public string RequestStr { get; set; }
[NotMapped]
public XDevice Device {
get {
return DeviceStr.FromJSON<XDevice> ();
}
set {
DeviceStr = value.ToJSON ();
}
}
public string DeviceStr { get; set; }
}
}
+51
View File
@@ -0,0 +1,51 @@
using System.ComponentModel.DataAnnotations.Schema;
using xCommons.Constants;
using xModels.Base;
namespace xIdentityModels.Navigations {
/// <summary>
/// Represent a Client Device which used by User
/// </summary>
public class XDevice : XBaseIntIDEntity {
/// <summary>
/// Operating System
/// </summary>
/// <value>device operating system identifier</value>
public string Os { get; set; }
/// <summary>
/// Operating System Version
/// </summary>
/// <value>which version of operatin system is in use</value>
public string OsVersion { get; set; }
/// <summary>
/// Device Browser
/// </summary>
/// <value>the Browser identifier</value>
public string Browser { get; set; }
/// <summary>
/// Browser Engine Agent
/// </summary>
/// <value>browser engine Agent</value>
public string UserAgent { get; set; }
/// <summary>
/// Type of client Device
/// </summary>
/// <value>represent device type <see>XDeviceType</see></value>
public XDeviceType DeviceType { get; set; }
//
#region User ...
/// <summary>
/// UserId
/// </summary>
/// <value>Represent this Devie belong to which User Identifier</value>
public string UserId { get; set; }
/// <summary>
/// User
/// </summary>
/// <value>Represent Device User <see>XUser</see></value>
[ForeignKey (nameof (UserId))]
public virtual XUser User { get; set; }
#endregion
}
}
+46
View File
@@ -0,0 +1,46 @@
using System.ComponentModel.DataAnnotations.Schema;
using xIdentityModels.Constants;
using xModels.Base;
namespace xIdentityModels.Navigations {
/// <summary>
/// represent a Follower of specific User
/// </summary>
public class XFriendshipFollower : XBaseIntIDEntity {
/// <summary>
/// XFriendshipState
/// </summary>
/// <value>state of Friendship at current moment <see>XFriendshipState</see></value>
public XFriendshipState State { get; set; }
//
#region User ...
/// <summary>
/// UserId
/// </summary>
/// <value>source User's Id</value>
public string UserId { get; set; }
/// <summary>
/// User
/// </summary>
/// <value>source User <see>XUser</see></value>
[ForeignKey (nameof (UserId))]
public virtual XUser User { get; set; }
#endregion
//
#region Dest User ...
/// <summary>
/// DestId
/// </summary>
/// <value>destination User's Id</value>
public string DestId { get; set; }
/// <summary>
/// Dest
/// </summary>
/// <value>dest User <see>XUser</see></value>
[ForeignKey (nameof (DestId))]
public virtual XUser Dest { get; set; }
#endregion
}
}
+46
View File
@@ -0,0 +1,46 @@
using System.ComponentModel.DataAnnotations.Schema;
using xIdentityModels.Constants;
using xModels.Base;
namespace xIdentityModels.Navigations {
/// <summary>
/// represent a Following of specific User
/// </summary>
public class XFriendshipFollowing : XBaseIntIDEntity {
/// <summary>
/// XFriendshipState
/// </summary>
/// <value>state of Friendship at current moment <see>XFriendshipState</see></value>
public XFriendshipState State { get; set; }
//
#region User ...
/// <summary>
/// UserId
/// </summary>
/// <value>source User's Id</value>
public string UserId { get; set; }
/// <summary>
/// User
/// </summary>
/// <value>source User <see>XUser</see></value>
[ForeignKey (nameof (UserId))]
public virtual XUser User { get; set; }
#endregion
//
#region Dest User ...
/// <summary>
/// DestId
/// </summary>
/// <value>destination User's Id</value>
public string DestId { get; set; }
/// <summary>
/// Dest
/// </summary>
/// <value>dest User <see>XUser</see></value>
[ForeignKey (nameof (DestId))]
public virtual XUser Dest { get; set; }
#endregion
}
}
+56
View File
@@ -0,0 +1,56 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using xModels.Base;
namespace xIdentityModels.Navigations {
/// <summary>
/// Represent a User's Avatar Entity
/// </summary>
public class XProfileImage : XBaseIntIDEntity {
/// <summary>
/// UserId
/// </summary>
/// <value>represent current Avatar belongs to which User</value>
public string UserId { get; set; }
/// <summary>
/// User
/// </summary>
/// <value>User instance <see>XUser</see></value>
[ForeignKey (nameof (UserId))]
public XUser User { get; set; }
/// <summary>
/// Name
/// </summary>
/// <value>Avatar's file name</value>
[Required]
[StringLength (255)]
public string Name { get; set; }
/// <summary>
/// Thumb
/// </summary>
/// <value>Avatar's thumbnail file's name</value>
[Required]
[StringLength (255)]
public string Thumb { get; set; }
/// <summary>
/// Path
/// </summary>
/// <value>Avatar's Image path on Profile Server</value>
[Required]
[StringLength (255)]
public string Path { get; set; }
/// <summary>
/// ThumbPath
/// </summary>
/// <value>Avatar's Thumbnail Image path on Profile Service</value>
[Required]
[StringLength (255)]
public string ThumbPath { get; set; }
/// <summary>
/// CreationDate
/// </summary>
/// <value>Upload Time</value>
public DateTime CreationDate { get; set; }
}
}
+23
View File
@@ -0,0 +1,23 @@
using System.Linq;
using xCommons.Extensions;
using xIdentityModels.Models;
using xIdentityModels.Interfaces;
namespace xIdentityModels.Providers {
public class XDefaultUserRoleHelper : IXUserRoleHelper {
public bool canReadCriticalData (XUserClaimsInfoDto userInfo) {
return isInRole (userInfo, "admin");
}
public bool canDoDangerousAction (XUserClaimsInfoDto userInfo) {
return isInRole (userInfo, "admin");
}
public bool isInRole (XUserClaimsInfoDto userInfo, string role) {
return userInfo.Roles
.Any (r =>
r.ToNormalString () == role.ToNormalString ()
);
}
}
}
+11
View File
@@ -0,0 +1,11 @@
# xIdentityModels
it is a Part of xDashboard on SaherElm IT Center which provides all required identity models
## Maintainer
Hadi Khazaee asl
[https://www.saherelm.ir](https://www.saherelm.ir)
[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com)
+16
View File
@@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations.Schema;
using xCommons.Extensions;
using xModels.Base;
using xIdentityModels.Models;
namespace xIdentityModels {
public class XApiToken : XBaseIntIDEntity {
public string Content { get; set; }
[NotMapped]
public XTokenResponse Tokens {
get { return Content.IsNullOrEmpty () ? null : Content.FromJSON<XTokenResponse> (); }
set { Content = value.ToJSON (); }
}
}
}
+113
View File
@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.AspNetCore.Identity;
using xIdentityModels.Constants;
using xIdentityModels.Navigations;
namespace xIdentityModels {
/// <summary>
/// represnt a User of System
/// </summary>
public partial class XUser : IdentityUser {
//
#region Properties ...
/// <summary>
/// FirstName
/// </summary>
/// <value>user's FirstName</value>
[Required]
[StringLength (50)]
public string FirstName { get; set; }
/// <summary>
/// LastName
/// </summary>
/// <value>user's LastName</value>
[Required]
[StringLength (100)]
public string LastName { get; set; }
/// <summary>
/// User is Enabled or not
/// </summary>
/// <remarks>
/// system was restrict Disabled Users access to Many Resources
/// </remarks>
/// <value>boolean value represent User is Enable or not</value>
public bool IsEnable { get; set; }
/// <summary>
/// User is Banned or not
/// </summary>
/// <remarks>
/// system was reject Banned Users access to Almost all Resources
/// </remarks>
/// <value>boolean value represent User is Banned or not</value>
public bool IsBanned { get; set; }
/// <summary>
/// DateOfBirth
/// </summary>
/// <value>user's DateOfBirth</value>
[Required]
public DateTime DateOfBirth { get; set; }
/// <summary>
/// CreationDate
/// </summary>
/// <value>user's Creation/Registration Date</value>
[Required]
public DateTime CreationDate { get; set; }
/// <summary>
/// LastLogin
/// </summary>
/// <value>user's Last Successfull Login Date</value>
public DateTime? LastLogin { get; set; }
/// <summary>
/// ProfileImage/Avatar
/// </summary>
/// <value>user's current Avatar</value>
public string Avatar { get; set; }
/// <summary>
/// Gender
/// </summary>
/// <value>user's Gender</value>
[Required]
public XGender Gender { get; set; }
#endregion
//
#region Navigation Properties ...
/// <summary>
/// User's Devices
/// </summary>
/// <typeparam name="XDevice"><see>XDevice</see></typeparam>
/// <returns>a Collection of all assigned Devices to User</returns>
[InverseProperty ("User")]
public virtual ICollection<XDevice> Devices { get; set; } = new HashSet<XDevice> ();
[InverseProperty ("User")]
/// <summary>
/// User's Avatars
/// </summary>
/// <typeparam name="XProfileImage"><see>XProfileImage</see></typeparam>
/// <returns>a Collection of all assigned Avatars to User</returns>
public virtual ICollection<XProfileImage> Avatars { get; set; } = new HashSet<XProfileImage> ();
/// <summary>
/// User's Followers
/// </summary>
/// <typeparam name="XFriendshipFollower"><see>XFriendshipFollower</see></typeparam>
/// <returns>a Collection of all User's Followers</returns>
[InverseProperty ("User")]
public virtual ICollection<XFriendshipFollower> Followers { get; set; } = new HashSet<XFriendshipFollower> ();
/// <summary>
/// User's Followings
/// </summary>
/// <typeparam name="XFriendshipFollowing"><see>XFriendshipFollowing</see></typeparam>
/// <returns>a Collection of all User's Followings</returns>
[InverseProperty ("User")]
public virtual ICollection<XFriendshipFollowing> Followings { get; set; } = new HashSet<XFriendshipFollowing> ();
/// <summary>
/// User's Roles
/// </summary>
/// <returns>a Collection of all User's Roles in System</returns>
public virtual ICollection<IdentityUserRole<string>> Roles { get; set; } = new HashSet<IdentityUserRole<string>> ();
#endregion
}
}
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="baget" value="https://nuget.saherelmhub.ir/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>
+36
View File
@@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">
<!-- Runtime Definition -->
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>xDashboard.xIdentityModels</PackageId>
<Version>1.0.0</Version>
<Authors>Hadi Khazaee Asl</Authors>
<Company>SaherElm IT Center</Company>
<Description>
it is a Part of xDashboard on SaherElm IT Center which provides all required identity models
</Description>
<!-- Icon Definition -->
<PackageIcon>icon.png</PackageIcon>
</PropertyGroup>
<!-- Icon Handling -->
<ItemGroup>
<None Include="../../Resources/Images/favicon.png" Link="icon.png" Pack="true" PackagePath="\icon.png" />
</ItemGroup>
<!-- Local Modules -->
<ItemGroup>
<PackageReference Include="xDashboard.xModels" Version="1.0.0" />
<!-- <ProjectReference Include="../xModels/xModels.csproj" /> -->
</ItemGroup>
<!-- Nuget Package Dependencies -->
<ItemGroup>
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="5.6.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.6.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="5.0.2" />
</ItemGroup>
</Project>