public virtual TModel Create(Utilizer utilizer, string membershipId, TModel model) { // Check membership var membership = this.membershipService.Get(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } else { model.MembershipId = membershipId; } // Model validation if (!this.ValidateModel(model, out var errors)) { throw ErtisAuthException.ValidationError(errors); } // Check existing if (this.IsAlreadyExist(model, membershipId)) { throw this.GetAlreadyExistError(model); } // Insert to database var dto = Mapper.Current.Map <TModel, TDto>(model); var insertedDto = this.repository.Insert(dto); var inserted = Mapper.Current.Map <TDto, TModel>(insertedDto); this.OnCreated?.Invoke(this, new CreateResourceEventArgs <TModel>(utilizer, inserted)); return(inserted); }
public IPaginationCollection <dynamic> GetDynamic(string membershipId, int?skip, int?limit, bool withCount, string orderBy, SortDirection?sortDirection) { var membership = this.membershipService.Get(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } return(this.repository.Query(x => x.MembershipId == membershipId, skip, limit, withCount, orderBy, sortDirection)); }
public async Task <IPaginationCollection <dynamic> > GetDynamicAsync(string membershipId, int?skip, int?limit, bool withCount, string orderBy, SortDirection?sortDirection) { var membership = await this.membershipService.GetAsync(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } return(await this.eventRepository.QueryAsync(x => x.MembershipId == membershipId, skip, limit, withCount, orderBy, sortDirection)); }
private async Task <Membership> CheckMembershipAsync(string membershipId) { var membership = await this._membershipService.GetAsync(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } return(membership); }
public virtual async Task <TModel> GetAsync(string membershipId, string id) { var membership = await this.membershipService.GetAsync(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } var dto = await this.repository.FindOneAsync(x => x.Id == id && x.MembershipId == membershipId); return(Mapper.Current.Map <TDto, TModel>(dto)); }
public override async ValueTask <ErtisAuthEventBase> GetAsync(string membershipId, string id) { var membership = await this.membershipService.GetAsync(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } var dto = await this.repository.FindOneAsync(x => x.Id == id && x.MembershipId == membershipId); return(DtoToModel(dto)); }
public override ErtisAuthEventBase Get(string membershipId, string id) { var membership = this.membershipService.Get(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } var dto = this.repository.FindOne(x => x.Id == id && x.MembershipId == membershipId); return(DtoToModel(dto)); }
public virtual async ValueTask <TModel> UpdateAsync(Utilizer utilizer, string membershipId, TModel model) { // Check membership var membership = await this.membershipService.GetAsync(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } else { model.MembershipId = membershipId; } // Overwrite var current = await this.GetAsync(membershipId, model.Id); if (current == null) { throw this.GetNotFoundError(model.Id); } this.Overwrite(model, current); // Touch model model = await this.TouchAsync(model, CrudOperation.Update); // Model validation if (!this.ValidateModel(model, out var errors)) { throw ErtisAuthException.ValidationError(errors); } // Check existing if (await this.IsAlreadyExistAsync(model, membershipId, current)) { throw this.GetAlreadyExistError(model); } model.MembershipId = membershipId; var dto = Mapper.Current.Map <TModel, TDto>(model); var updatedDto = await this.repository.UpdateAsync(dto); var updated = Mapper.Current.Map <TDto, TModel>(updatedDto); this.OnUpdated?.Invoke(this, new UpdateResourceEventArgs <TModel>(utilizer, current, updated)); return(updated); }
protected async ValueTask <TModel> GetAsync(string membershipId, Expression <Func <TDto, bool> > expression) { var membership = await this.membershipService.GetAsync(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } var entities = await this.repository.FindAsync(expression); var entity = entities.Items.FirstOrDefault(x => x.MembershipId == membershipId); return(Mapper.Current.Map <TDto, TModel>(entity)); }
public async Task SetPasswordAsync(Utilizer utilizer, string membershipId, string resetToken, string usernameOrEmailAddress, string password) { if (string.IsNullOrEmpty(usernameOrEmailAddress)) { throw ErtisAuthException.ValidationError(new [] { "Username or email required!" }); } var membership = await this.membershipService.GetAsync(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } var user = await this.GetUserWithPasswordAsync(usernameOrEmailAddress, usernameOrEmailAddress, membershipId); if (user == null) { throw ErtisAuthException.UserNotFound(usernameOrEmailAddress, "username or email_address"); } if (utilizer.Role == Rbac.ReservedRoles.Administrator || utilizer.Id == user.Id) { if (this.jwtService.TryDecodeToken(resetToken, out var securityToken)) { var expireTime = securityToken.ValidTo.ToLocalTime(); if (DateTime.Now > expireTime) { // Token was expired! throw ErtisAuthException.TokenWasExpired(); } await this.ChangePasswordAsync(utilizer, membershipId, user.Id, password); } else { // Reset token could not decoded! throw ErtisAuthException.InvalidToken(); } } else { throw ErtisAuthException.AccessDenied("Unauthorized access"); } }
public async Task <ResetPasswordToken> ResetPasswordAsync(Utilizer utilizer, string membershipId, string usernameOrEmailAddress) { if (string.IsNullOrEmpty(usernameOrEmailAddress)) { throw ErtisAuthException.ValidationError(new [] { "Username or email required!" }); } var membership = await this.membershipService.GetAsync(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } var user = await this.GetUserWithPasswordAsync(usernameOrEmailAddress, usernameOrEmailAddress, membershipId); if (user == null) { throw ErtisAuthException.UserNotFound(usernameOrEmailAddress, "username or email_address"); } if (utilizer.Role == Rbac.ReservedRoles.Administrator || utilizer.Id == user.Id) { var tokenClaims = new TokenClaims(Guid.NewGuid().ToString(), user, membership); tokenClaims.AddClaim("token_type", "reset_token"); var resetToken = this.jwtService.GenerateToken(tokenClaims, HashAlgorithms.SHA2_256, Encoding.UTF8); var resetPasswordToken = new ResetPasswordToken(resetToken, TimeSpan.FromHours(1)); await this.eventService.FireEventAsync(this, new ErtisAuthEvent { EventType = ErtisAuthEventType.UserPasswordReset, UtilizerId = user.Id, Document = resetPasswordToken, MembershipId = membershipId }); return(resetPasswordToken); } else { throw ErtisAuthException.AccessDenied("Unauthorized access"); } }
public async ValueTask <IPaginationCollection <TModel> > SearchAsync( string membershipId, string keyword, int?skip = null, int?limit = null, bool?withCount = null, string sortField = null, SortDirection?sortDirection = null) { var membership = await this.membershipService.GetAsync(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } var textSearchLanguage = TextSearchLanguage.None; if (!string.IsNullOrEmpty(membership.DefaultLanguage) && TextSearchLanguage.All.Any(x => x.ISO6391Code == membership.DefaultLanguage)) { textSearchLanguage = TextSearchLanguage.All.FirstOrDefault(x => x.ISO6391Code == membership.DefaultLanguage); } var textSearchOptions = new TextSearchOptions { Language = textSearchLanguage, IsCaseSensitive = true, IsDiacriticSensitive = false }; var paginatedDtoCollection = await this.repository.SearchAsync(keyword, textSearchOptions, skip, limit, withCount, sortField, sortDirection); if (paginatedDtoCollection?.Items != null) { return(new PaginationCollection <TModel> { Items = paginatedDtoCollection.Items.Select(x => Mapper.Current.Map <TDto, TModel>(x)), Count = paginatedDtoCollection.Count }); } else { return(new PaginationCollection <TModel>()); } }
public async ValueTask <dynamic> GetDynamicAsync(string membershipId, string id) { var membership = await this.membershipService.GetAsync(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } var result = await this.repository.QueryAsync(x => x.Id == id && x.MembershipId == membershipId, 0, 1); if (result?.Items != null && result.Items.Any()) { return(result.Items.FirstOrDefault()); } return(null); }
public dynamic GetDynamic(string membershipId, string id) { var membership = this.membershipService.Get(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } var result = this.eventRepository.Query(x => x.Id == id && x.MembershipId == membershipId, 0, 1); if (result?.Items != null && result.Items.Any()) { return(result.Items.FirstOrDefault()); } return(null); }
public override Application Create(Utilizer utilizer, string membershipId, Application model) { var membership = this.membershipService.Get(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } var application = base.Create(utilizer, membershipId, model); if (application != null) { application.Secret = $"{application.Id}:{membership.SecretKey}"; application = this.Update(utilizer, membershipId, application); } return(application); }
public async Task <BasicTokenValidationResult> VerifyBasicTokenAsync(string basicToken, bool fireEvent = true) { if (string.IsNullOrEmpty(basicToken)) { throw ErtisAuthException.InvalidToken(); } var parts = basicToken.Split(':'); if (parts.Length != 2) { throw ErtisAuthException.InvalidToken(); } var applicationId = parts[0]; var application = await this.applicationService.GetByIdAsync(applicationId); if (application == null) { throw ErtisAuthException.ApplicationNotFound(applicationId); } var membership = await this.membershipService.GetAsync(application.MembershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(application.MembershipId); } var secret = parts[1]; if (membership.SecretKey != secret) { throw ErtisAuthException.ApplicationSecretMismatch(); } if (fireEvent) { await this.eventService.FireEventAsync(this, new ErtisAuthEvent(ErtisAuthEventType.TokenVerified, application, new { basicToken })); } return(new BasicTokenValidationResult(true, basicToken, application)); }
public async Task <BearerToken> GenerateTokenAsync(string username, string password, string membershipId, bool fireEvent = true) { // Check membership var membership = await this.membershipService.GetAsync(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } if (!membership.IsValid(out IEnumerable <string> errors)) { throw ErtisAuthException.MalformedMembership(membershipId, errors); } // Check user var user = await this.userService.GetUserWithPasswordAsync(username, username, membership.Id); if (user == null) { throw ErtisAuthException.UserNotFound(username, "username or email"); } // Check password var passwordHash = this.cryptographyService.CalculatePasswordHash(membership, password); if (passwordHash != user.PasswordHash) { throw ErtisAuthException.UsernameOrPasswordIsWrong(username, password); } else { var token = this.GenerateBearerToken(user, membership); if (fireEvent) { await this.eventService.FireEventAsync(this, new ErtisAuthEvent(ErtisAuthEventType.TokenGenerated, user, token)); } return(token); } }
public async Task <User> ChangePasswordAsync(Utilizer utilizer, string membershipId, string userId, string newPassword) { if (string.IsNullOrEmpty(newPassword)) { throw ErtisAuthException.ValidationError(new [] { "Password can not be null or empty!" }); } var membership = await this.membershipService.GetAsync(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } var user = await this.GetAsync(membershipId, userId); if (user == null) { throw ErtisAuthException.UserNotFound(userId, "_id"); } var userWithPassword = Mapper.Current.Map <User, UserWithPassword>(user); var passwordHash = this.cryptographyService.CalculatePasswordHash(membership, newPassword); userWithPassword.PasswordHash = passwordHash; var updatedUser = await this.UpdateAsync(utilizer, membershipId, userWithPassword); await this.eventService.FireEventAsync(this, new ErtisAuthEvent { EventType = ErtisAuthEventType.UserPasswordChanged, UtilizerId = user.Id, Document = updatedUser, Prior = userWithPassword, MembershipId = membershipId }); return(updatedUser); }
public async Task <bool> RevokeTokenAsync(string token, bool fireEvent = true) { var validationResult = await this.VerifyBearerTokenAsync(token, false); if (!validationResult.IsValidated) { throw ErtisAuthException.InvalidToken(); } await this.revokedTokensRepository.InsertAsync(new RevokedTokenDto { Token = token, RevokedAt = DateTime.Now, UserId = validationResult.User.Id }); var membership = await this.membershipService.GetAsync(validationResult.User.MembershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(validationResult.User.MembershipId); } if (this.jwtService.TryDecodeToken(token, out var securityToken)) { if (!this.IsRefreshToken(securityToken)) { var refreshToken = this.StimulateRefreshToken(token, validationResult.User, membership); if (!string.IsNullOrEmpty(refreshToken)) { await this.RevokeRefreshTokenAsync(refreshToken); } } } await this.eventService.FireEventAsync(this, new ErtisAuthEvent(ErtisAuthEventType.TokenRevoked, validationResult.User, new { token })); return(true); }
public override async ValueTask <IPaginationCollection <ErtisAuthEventBase> > GetAsync(string membershipId, int?skip, int?limit, bool withCount, string orderBy, SortDirection?sortDirection) { var membership = await this.membershipService.GetAsync(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } var paginatedDtoCollection = await this.repository.FindAsync(x => x.MembershipId == membershipId, skip, limit, withCount, orderBy, sortDirection); if (paginatedDtoCollection?.Items != null) { return(new PaginationCollection <ErtisAuthEventBase> { Items = paginatedDtoCollection.Items.Select(DtoToModel), Count = paginatedDtoCollection.Count }); } else { return(new PaginationCollection <ErtisAuthEventBase>()); } }
public virtual IPaginationCollection <TModel> Get(string membershipId, int?skip, int?limit, bool withCount, string orderBy, SortDirection?sortDirection) { var membership = this.membershipService.Get(membershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(membershipId); } var paginatedDtoCollection = this.repository.Find(x => x.MembershipId == membershipId, skip, limit, withCount, orderBy, sortDirection); if (paginatedDtoCollection?.Items != null) { return(new PaginationCollection <TModel> { Items = paginatedDtoCollection.Items.Select(x => Mapper.Current.Map <TDto, TModel>(x)), Count = paginatedDtoCollection.Count }); } else { return(new PaginationCollection <TModel>()); } }
protected override ErtisAuthException GetNotFoundError(string id) { return(ErtisAuthException.MembershipNotFound(id)); }
public async ValueTask <bool> RevokeTokenAsync(string token, bool logoutFromAllDevices = false, bool fireEvent = true) { User user; try { var validationResult = await this.VerifyBearerTokenAsync(token, false); user = validationResult.User; if (!validationResult.IsValidated) { throw ErtisAuthException.InvalidToken(); } } catch (ErtisAuthException ex) { if (ex.ErrorCode == ErtisAuthException.TokenWasRevoked().ErrorCode) { Console.WriteLine("This token was revoked already"); } return(false); } catch (Exception ex) { Console.WriteLine(ex); return(false); } var activeTokenDtos = await this.GetActiveTokensByUser(user.Id, user.MembershipId); var filteredActiveTokenDtos = logoutFromAllDevices ? activeTokenDtos : new[] { activeTokenDtos.FirstOrDefault(x => x.AccessToken == token) }; var activeTokens = filteredActiveTokenDtos.Where(x => x != null).ToArray(); if (activeTokens.Any()) { foreach (var activeTokenDto in activeTokens) { var isRefreshToken = false; if (this.jwtService.TryDecodeToken(activeTokenDto.AccessToken, out var securityToken)) { isRefreshToken = this.IsRefreshToken(securityToken); } await this.revokedTokensRepository.InsertAsync(new RevokedTokenDto { Token = activeTokenDto.AccessToken, RevokedAt = DateTime.Now, UserId = user.Id, UserName = user.Username, EmailAddress = user.EmailAddress, FirstName = user.FirstName, LastName = user.LastName, MembershipId = user.MembershipId, TokenType = isRefreshToken ? "refresh_token" : "bearer_token" }); var membership = await this.membershipService.GetAsync(user.MembershipId); if (membership == null) { throw ErtisAuthException.MembershipNotFound(user.MembershipId); } if (!isRefreshToken) { var refreshToken = this.StimulateRefreshToken(activeTokenDto.AccessToken, user, membership); if (!string.IsNullOrEmpty(refreshToken)) { await this.RevokeRefreshTokenAsync(refreshToken); } } await this.eventService.FireEventAsync(this, new ErtisAuthEvent(ErtisAuthEventType.TokenRevoked, user, new { activeTokenDto.AccessToken }) { MembershipId = membership.Id }); } await this.activeTokensRepository.BulkDeleteAsync(activeTokens); } return(true); }
public static NotFoundObjectResult MembershipNotFound(this ControllerBase controller, string membershipId) { return(controller.NotFound(ErtisAuthException.MembershipNotFound(membershipId))); }
public async Task <BearerTokenValidationResult> VerifyBearerTokenAsync(string token, bool fireEvent = true) { var revokedToken = await this.revokedTokensRepository.FindOneAsync(x => x.Token == token); if (revokedToken != null) { throw ErtisAuthException.TokenWasRevoked(); } if (this.jwtService.TryDecodeToken(token, out var securityToken)) { var expireTime = securityToken.ValidTo.ToLocalTime(); if (DateTime.Now <= expireTime) { var user = await this.GetTokenOwnerAsync(securityToken); if (user != null) { if (this.TryExtractClaimValue(securityToken, JwtRegisteredClaimNames.Prn, out var membershipId) && !string.IsNullOrEmpty(membershipId)) { var membership = await this.membershipService.GetAsync(membershipId); if (membership != null) { var encoding = membership.GetEncoding(); var secretSecurityKey = new SymmetricSecurityKey(encoding.GetBytes(membership.SecretKey)); var tokenClaims = new TokenClaims(null, user, membership); if (!this.jwtService.ValidateToken(token, tokenClaims, secretSecurityKey, out _)) { // Token signature not verified! throw ErtisAuthException.InvalidToken("Token signature could not verified!"); } } else { // Membership not found! throw ErtisAuthException.MembershipNotFound(membershipId); } } else { // MembershipId could not found in token claims! throw ErtisAuthException.InvalidToken(); } if (fireEvent) { await this.eventService.FireEventAsync(this, new ErtisAuthEvent(ErtisAuthEventType.TokenVerified, user, new { token })); } return(new BearerTokenValidationResult(true, token, user, expireTime - DateTime.Now, this.IsRefreshToken(securityToken))); } else { // User not found! var userId = securityToken.Subject; throw ErtisAuthException.UserNotFound(userId, "_id"); } } else { // Token was expired! throw ErtisAuthException.TokenWasExpired(); } } else { // Token could not decoded! throw ErtisAuthException.InvalidToken(); } }
public async Task <BearerToken> RefreshTokenAsync(string refreshToken, bool revokeBefore = true, bool fireEvent = true) { var revokedToken = await this.revokedTokensRepository.FindOneAsync(x => x.Token == refreshToken); if (revokedToken != null) { throw ErtisAuthException.RefreshTokenWasRevoked(); } if (this.jwtService.TryDecodeToken(refreshToken, out var securityToken)) { if (this.IsRefreshToken(securityToken)) { var expireTime = securityToken.ValidTo.ToLocalTime(); if (DateTime.Now <= expireTime) { if (this.TryExtractClaimValue(securityToken, JwtRegisteredClaimNames.Prn, out var membershipId) && !string.IsNullOrEmpty(membershipId)) { var membership = await this.membershipService.GetAsync(membershipId); if (membership != null) { var userId = securityToken.Subject; if (!string.IsNullOrEmpty(userId)) { var user = await this.userService.GetAsync(membershipId, userId); if (user != null) { var token = this.GenerateBearerToken(user, membership); if (revokeBefore) { await this.RevokeTokenAsync(refreshToken); } if (fireEvent) { await this.eventService.FireEventAsync(this, new ErtisAuthEvent(ErtisAuthEventType.TokenRefreshed, user, token, new { refreshToken })); } return(token); } else { // User not found! throw ErtisAuthException.UserNotFound(userId, "_id"); } } else { // UserId could not found in token claims! throw ErtisAuthException.InvalidToken(); } } else { // Membership not found! throw ErtisAuthException.MembershipNotFound(membershipId); } } else { // MembershipId could not found in token claims! throw ErtisAuthException.InvalidToken(); } } else { // Token was expired! throw ErtisAuthException.RefreshTokenWasExpired(); } } else { // This is not a refresh token! throw ErtisAuthException.TokenIsNotRefreshable(); } } else { // Token could not decoded! throw ErtisAuthException.InvalidToken(); } }
public async ValueTask <BasicTokenValidationResult> VerifyBasicTokenAsync(string basicToken, bool fireEvent = true) { if (string.IsNullOrEmpty(basicToken)) { throw ErtisAuthException.InvalidToken(); } var parts = basicToken.Split(':'); if (parts.Length != 2) { throw ErtisAuthException.InvalidToken(); } var applicationId = parts[0]; var secret = parts[1]; var application = await this.applicationService.GetByIdAsync(applicationId); if (application == null) { throw ErtisAuthException.ApplicationNotFound(applicationId); } var membership = await this.membershipService.GetAsync(application.MembershipId); if (membership == null) { if (this.applicationService.IsSystemReservedApplication(application)) { membership = await this.membershipService.GetBySecretKeyAsync(secret); var onTheFlyApplication = new Application { Id = application.Id, Name = application.Name, Role = application.Role, Permissions = application.Permissions, Forbidden = application.Forbidden, Sys = application.Sys, MembershipId = membership.Id }; application = onTheFlyApplication; } if (membership == null) { throw ErtisAuthException.MembershipNotFound(application.MembershipId); } } if (membership.SecretKey != secret) { throw ErtisAuthException.ApplicationSecretMismatch(); } if (fireEvent) { await this.eventService.FireEventAsync(this, new ErtisAuthEvent(ErtisAuthEventType.TokenVerified, application, new { basicToken }) { MembershipId = membership.Id }); } return(new BasicTokenValidationResult(true, basicToken, application)); }