public static string ExtractToken(string authorizationHeader, out string tokenType) { if (string.IsNullOrEmpty(authorizationHeader)) { tokenType = null; return(null); } var parts = authorizationHeader.Split(' '); if (parts.Length > 2) { throw ErtisAuthException.InvalidToken(); } if (parts.Length == 2) { var supportedTokenTypes = Enum.GetValues(typeof(SupportedTokenTypes)).Cast <SupportedTokenTypes>().Select(x => x.ToString()); if (!supportedTokenTypes.Contains(parts[0])) { throw ErtisAuthException.UnsupportedTokenType(); } tokenType = parts[0]; return(parts[1]); } tokenType = null; return(parts[0]); }
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"); } }
private async Task <Application> GetTokenOwnerApplicationAsync(string basicToken) { 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); } 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)); }
private async Task <User> GetTokenOwnerAsync(JwtSecurityToken securityToken) { if (this.TryExtractClaimValue(securityToken, JwtRegisteredClaimNames.Prn, out var membershipId) && !string.IsNullOrEmpty(membershipId)) { var userId = securityToken.Subject; if (!string.IsNullOrEmpty(userId)) { return(await this.userService.GetAsync(membershipId, userId)); } else { // UserId could not found in token claims! throw ErtisAuthException.InvalidToken(); } } else { // MembershipId could not found in token claims! throw ErtisAuthException.InvalidToken(); } }
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); }
private async Task <Utilizer> CheckAuthorizationAsync(HttpContext httpContext) { var token = httpContext.Request.GetTokenFromHeader(out var tokenType); if (string.IsNullOrEmpty(token)) { throw ErtisAuthException.AuthorizationHeaderMissing(); } if (string.IsNullOrEmpty(tokenType)) { throw ErtisAuthException.UnsupportedTokenType(); } switch (tokenType) { case "Bearer": { var verifyTokenResult = await this.tokenService.VerifyBearerTokenAsync(token, false); if (!verifyTokenResult.IsValidated) { throw ErtisAuthException.InvalidToken(); } var user = verifyTokenResult.User; if (!string.IsNullOrEmpty(user.Role)) { var role = await this.roleService.GetByNameAsync(user.Role, user.MembershipId); if (role != null) { this.VerifyRolePermissions(role, user.Id, httpContext); } } return(user); } case "Basic": { var validationResult = await this.tokenService.VerifyBasicTokenAsync(token); if (!validationResult.IsValidated) { throw ErtisAuthException.InvalidToken(); } var application = validationResult.Application; if (!string.IsNullOrEmpty(application.Role)) { var role = await this.roleService.GetByNameAsync(application.Role, application.MembershipId); if (role != null) { this.VerifyRolePermissions(role, application.Id, httpContext); } } return(application); } default: throw ErtisAuthException.UnsupportedTokenType(); } }
public static UnauthorizedObjectResult InvalidToken(this ControllerBase controller) { return(controller.Unauthorized(ErtisAuthException.InvalidToken().Error)); }
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 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(); } }
private async Task <Utilizer> CheckAuthorizationAsync() { var token = this.Context.Request.GetTokenFromHeader(out var tokenType); if (string.IsNullOrEmpty(token)) { throw ErtisAuthException.AuthorizationHeaderMissing(); } if (string.IsNullOrEmpty(tokenType)) { throw ErtisAuthException.UnsupportedTokenType(); } TokenTypeExtensions.TryParseTokenType(tokenType, out var _tokenType); switch (_tokenType) { case SupportedTokenTypes.None: throw ErtisAuthException.UnsupportedTokenType(); case SupportedTokenTypes.Basic: var validationResult = await this.tokenService.VerifyBasicTokenAsync(token, false); if (!validationResult.IsValidated) { throw ErtisAuthException.InvalidToken(); } var application = validationResult.Application; Utilizer applicationUtilizer = application; if (!string.IsNullOrEmpty(application.Role)) { var role = await this.roleService.GetByNameAsync(application.Role, application.MembershipId); if (role != null) { var rbac = this.Context.GetRbacDefinition(application.Id); if (!this.accessControlService.HasPermission(role, rbac, applicationUtilizer)) { throw ErtisAuthException.AccessDenied("Your authorization role is unauthorized for this action"); } } } applicationUtilizer.Token = token; applicationUtilizer.TokenType = _tokenType; return(applicationUtilizer); case SupportedTokenTypes.Bearer: var verifyTokenResult = await this.tokenService.VerifyBearerTokenAsync(token, false); if (!verifyTokenResult.IsValidated) { throw ErtisAuthException.InvalidToken(); } var user = verifyTokenResult.User; Utilizer userUtilizer = user; if (!string.IsNullOrEmpty(user.Role)) { var role = await this.roleService.GetByNameAsync(user.Role, user.MembershipId); if (role != null) { var rbac = this.Context.GetRbacDefinition(user.Id); if (!this.accessControlService.HasPermission(role, rbac, userUtilizer)) { throw ErtisAuthException.AccessDenied("Your authorization role is unauthorized for this action"); } } } userUtilizer.Token = token; userUtilizer.TokenType = _tokenType; return(userUtilizer); default: throw ErtisAuthException.UnsupportedTokenType(); } }
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 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)); }