public void PreAuthenticate(IRequest req, IResponse res) { //The API Key is sent in the Basic Auth Username and Password is Empty var userPass = req.GetBasicAuthUserAndPassword(); if (userPass != null && string.IsNullOrEmpty(userPass.Value.Value)) { if (RequireSecureConnection && !req.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.ApiKeyRequiresSecureConnection); } var apiKey = userPass.Value.Key; PreAuthenticateWithApiKey(req, res, apiKey); } var bearerToken = req.GetBearerToken(); if (bearerToken != null) { var authRepo = (IManageApiKeys)req.TryResolve <IAuthRepository>().AsUserAuthRepository(req); if (authRepo.ApiKeyExists(bearerToken)) { if (RequireSecureConnection && !req.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.ApiKeyRequiresSecureConnection); } PreAuthenticateWithApiKey(req, res, bearerToken); } } }
public object Put(UpdateOrganizationMember request) { var user = GetUser(); AssertOrganizationModerator(Db, request.OrganizationId, user, out var org, out var orgMember); var member = Db.Single <OrganizationMember>(x => x.UserId == request.UserId && x.OrganizationId == request.OrganizationId); if (member == null) { throw HttpError.NotFound("Member does not exist"); } var requiresOwner = member.IsOwner || member.IsModerator || member.IsModerator != request.IsModerator || member.IsOwner != request.IsOwner; if (requiresOwner && !user.IsOrganizationOwner(orgMember)) { throw HttpError.Forbidden("This action is limited to Organization Owners"); } member.PopulateWith(request); Db.Update(member); ClearOrganizationCaches(); return(new UpdateOrganizationMemberResponse()); }
public async Task PreAuthenticateWithApiKeyAsync(IRequest req, IResponse res, ApiKey apiKey) { if (RequireSecureConnection && !req.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.ApiKeyRequiresSecureConnection.Localize(req)); } ValidateApiKey(req, apiKey); var apiSessionKey = GetSessionKey(apiKey.Id); if (await HasCachedSessionAsync(req, apiSessionKey).ConfigAwait()) { req.Items[Keywords.ApiKey] = apiKey; return; } //Need to run SessionFeature filter since its not executed before this attribute (Priority -100) SessionFeature.AddSessionIdToRequestFilter(req, res, null); //Required to get req.GetSessionId() using var authService = HostContext.ResolveService <AuthenticateService>(req); var response = await authService.PostAsync(new Authenticate { provider = Name, UserName = "******", Password = apiKey.Id, }).ConfigAwait(); await CacheSessionAsync(req, apiSessionKey); }
public CreateLayerTokenResponse Post(CreateLayerIdentityToken request) { // validate if the user is authenticated if (!_validator.Validate(request.UserId)) { throw HttpError.Forbidden("This user is not allowed to create a validation token for the requested user."); } var feature = HostContext.GetPlugin <LayerTokenProviderFeature>(); var header = new JsonObject { { "typ", "JWT" }, { "alg", "RS256" }, { "cty", "layer-eit;v=1" }, // String - Express a Content Type of Layer External Identity Token, version 1 { "kid", feature.KeyName } }; var body = new JsonObject { { "iss", feature.ProviderId }, { "prn", request.UserId }, { "iat", DateTime.UtcNow.ToUnixTime().ToString() }, { "exp", DateTime.UtcNow.Add(feature.ExpiresIn).ToUnixTime().ToString() }, { "nce", request.Nonce } }; var headerBytes = header.ToJson().ToUtf8Bytes(); var headerEncoded = headerBytes.ToBase64UrlSafe(); var payloadBytes = body.ToJson().ToUtf8Bytes(); var payloadEncoded = payloadBytes.ToBase64UrlSafe(); var base64Header = headerBytes.ToBase64UrlSafe(); var base64Payload = payloadBytes.ToBase64UrlSafe(); var stringToSign = base64Header + "." + base64Payload; using (var sr = new StreamReader(feature.PemPath)) { var pr = new PemReader(sr); var keyPair = (AsymmetricCipherKeyPair)pr.ReadObject(); var rsaPrivate = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)keyPair.Private); var rsa = new RSACryptoServiceProvider(); rsa.ImportParameters(rsaPrivate); var inputBytes = Encoding.UTF8.GetBytes(stringToSign); var signatureBytesTemp = rsa.SignData(inputBytes, new SHA256CryptoServiceProvider()); var token = string.Join(".", headerEncoded, payloadEncoded, signatureBytesTemp.ToBase64UrlSafe()); return(new CreateLayerTokenResponse() { IdentityToken = token }); } }
public static void AssertOrganizationModerator(IDbConnection db, int orgId, AuthUserSession user, out Organization organization, out OrganizationMember orgMember) { AssertCanViewOrganization(db, orgId, user, out organization, out orgMember); if (!user.IsOrganizationModerator(orgMember)) { throw HttpError.Forbidden("This action is limited to Organization Moderators"); } }
public virtual void ValidateApiKey(IRequest req, ApiKey apiKey) { if (apiKey == null) throw HttpError.NotFound(ErrorMessages.ApiKeyDoesNotExist.Localize(req)); if (apiKey.CancelledDate != null) throw HttpError.Forbidden(ErrorMessages.ApiKeyHasBeenCancelled.Localize(req)); if (apiKey.ExpiryDate != null && DateTime.UtcNow > apiKey.ExpiryDate.Value) throw HttpError.Forbidden(ErrorMessages.ApiKeyHasExpired.Localize(req)); }
public object Any(ConvertSessionToToken request) { var jwtAuthProvider = (JwtAuthProvider)AuthenticateService.GetRequiredJwtAuthProvider(); if (jwtAuthProvider.RequireSecureConnection && !Request.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection.Localize(Request)); } if (Request.ResponseContentType.MatchesContentType(MimeTypes.Html)) { Request.ResponseContentType = MimeTypes.Json; } var token = Request.GetJwtToken(); IAuthSession session = null; var includeTokensInResponse = jwtAuthProvider.IncludeJwtInConvertSessionToTokenResponse; var createFromSession = string.IsNullOrEmpty(token); if (createFromSession || includeTokensInResponse) { session = Request.GetSession(); if (createFromSession) { token = jwtAuthProvider.CreateJwtBearerToken(Request, session); } if (!request.PreserveSession) { Request.RemoveSession(session.Id); } } return(new HttpResult(new ConvertSessionToTokenResponse { AccessToken = includeTokensInResponse ? token : null, RefreshToken = createFromSession && includeTokensInResponse && !request.PreserveSession ? jwtAuthProvider.CreateJwtRefreshToken(Request, session.UserAuthId, jwtAuthProvider.ExpireRefreshTokensIn) : null }) { Cookies = { new Cookie(Keywords.TokenCookie, token, Cookies.RootPath) { HttpOnly = true, Secure = Request.IsSecureConnection, Expires = DateTime.UtcNow.Add(jwtAuthProvider.ExpireTokensIn), } } }); }
private void ValidateAccessRights() { if (Request.TryResolve <IDbConnectionFactory>() == null || Request.GetSession().HasRole("Admin", null)) { // all good return; } throw HttpError.Forbidden("Forbidden"); }
public async Task LoginUserAsync(LoginDto dto) { HttpContext context = _httpContextAccessor.HttpContext; if (context.User.Identity.IsAuthenticated) { throw HttpError.Forbidden("User is still authenticated"); } if (dto.Name == null || dto.Password == null) { throw HttpError.InternalServerError("Username or password is null"); } User user = (await _userRepository.Find(x => x.Name == dto.Name)).FirstOrDefault(); if (user == null) { throw HttpError.Unauthorized("Wrong username or password"); } string savedPasswordHash = (await _hashRepository.Get(user.Id))?.PasswordHash; if (savedPasswordHash == null) { throw HttpError.InternalServerError("User has no password"); } if (!HashHelpers.CheckPasswordWithHash(dto.Password, savedPasswordHash)) { throw HttpError.Unauthorized("Wrong username or password"); } string[] roles = user.CredentialLevel.GetAllPossibleRoles(); List <Claim> claims = new List <Claim> { new Claim(ClaimTypes.Name, user.Name), new Claim(ClaimTypes.NameIdentifier, user.Name) }; claims.AddRange(roles.Select(x => new Claim(ClaimTypes.Role, x))); var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); var authProperties = new AuthenticationProperties { AllowRefresh = true, ExpiresUtc = DateTimeOffset.Now.AddDays(1), IsPersistent = dto.RememberMe }; await context.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, authProperties); }
public void PreAuthenticate(IRequest req, IResponse res) { if (req.OperationName != null && JwtAuthProviderReader.IgnoreForOperationTypes.Contains(req.OperationName)) { return; } var bearerToken = req.GetBearerToken() ?? req.GetCookieValue(Keywords.TokenCookie); if (bearerToken != null) { var parts = bearerToken.Split('.'); if (parts.Length != 3) { throw new TokenException("Azure AD jwt token should have 3 parts."); } if (RequireSecureConnection && !req.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection); } var header = parts[0]; var payload = parts[1]; var signatureBytes = parts[2].FromBase64UrlSafe(); var headerJson = header.FromBase64UrlSafe().FromUtf8Bytes(); var payloadBytes = payload.FromBase64UrlSafe(); var headerData = headerJson.FromJson <Dictionary <string, string> >(); var bytesToSign = string.Concat(header, ".", payload).ToUtf8Bytes(); var algorithm = headerData["alg"]; //Potential Security Risk for relying on user-specified algorithm: https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/ //if (RequireHashAlgorithm && algorithm != HashAlgorithm) // throw new NotSupportedException("Invalid algoritm '{0}', expected '{1}'".Fmt(algorithm, HashAlgorithm)); if (!VerifyPayload(algorithm, bytesToSign, signatureBytes)) { return; } var payloadJson = payloadBytes.FromUtf8Bytes(); var jwtPayload = JsonObject.Parse(payloadJson); var session = CreateSessionFromPayload(req, jwtPayload); req.Items[Keywords.Session] = session; } }
public static void AssertCanPostToOrganization(IDbConnection db, int organizationId, AuthUserSession user, out Organization org, out OrganizationMember orgMember) { AssertCanViewOrganization(db, organizationId, user, out org, out orgMember); if (orgMember?.DenyPosts == true || orgMember?.DenyAll == true) { throw HttpError.Forbidden("Access has been suspended"); } if (org.Locked != null && orgMember == null) { throw HttpError.NotFound("Organization is locked to members only"); } }
public void PreAuthenticateWithApiKey(IRequest req, IResponse res, ApiKey apiKey) { if (RequireSecureConnection && !req.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.ApiKeyRequiresSecureConnection.Localize(req)); } ValidateApiKey(req, apiKey); var apiSessionKey = GetSessionKey(apiKey.Id); if (SessionCacheDuration != null) { var session = req.GetCacheClient().Get <IAuthSession>(apiSessionKey); if (session != null) { session = HostContext.AppHost.OnSessionFilter(req, session, session.Id); } if (session != null) { req.Items[Keywords.ApiKey] = apiKey; req.Items[Keywords.Session] = session; return; } } //Need to run SessionFeature filter since its not executed before this attribute (Priority -100) SessionFeature.AddSessionIdToRequestFilter(req, res, null); //Required to get req.GetSessionId() using (var authService = HostContext.ResolveService <AuthenticateService>(req)) { var response = authService.Post(new Authenticate { provider = Name, UserName = "******", Password = apiKey.Id, }); } if (SessionCacheDuration != null) { var session = req.GetSession(); req.GetCacheClient().Set(apiSessionKey, session, SessionCacheDuration); } }
public virtual void ValidateApiKey(ApiKey apiKey) { if (apiKey == null) { throw HttpError.NotFound("ApiKey does not exist"); } if (apiKey.CancelledDate != null) { throw HttpError.Forbidden("ApiKey has been cancelled"); } if (apiKey.ExpiryDate != null && DateTime.UtcNow > apiKey.ExpiryDate.Value) { throw HttpError.Forbidden("ApiKey has expired"); } }
public void PreAuthenticate(IRequest req, IResponse res) { var signature = req.Headers[WebhookEventConstants.SecretSignatureHeaderName]; if (signature.HasValue()) { if (RequireSecureConnection && !req.IsSecureConnection) { throw HttpError.Forbidden(Resources.HmacAuthProvider_NotHttps); } var eventName = req.Headers[WebhookEventConstants.EventNameHeaderName]; if (OnGetSecret != null) { Secret = OnGetSecret(req, eventName); } if (!Secret.HasValue()) { throw HttpError.Unauthorized(Resources.HmacAuthProvider_IncorrectlyConfigured); } var isValidSecret = req.VerifySignature(signature, Secret); if (!isValidSecret) { throw new HttpError(HttpStatusCode.Unauthorized); } var requestId = req.Headers[WebhookEventConstants.RequestIdHeaderName]; var userId = requestId.HasValue() ? requestId : Guid.NewGuid().ToString("N"); var username = req.GetUrlHostName(); var sessionId = SessionExtensions.CreateRandomSessionId(); var session = SessionFeature.CreateNewSession(req, sessionId); session.UserAuthId = userId; session.UserAuthName = username; session.UserName = username; session.IsAuthenticated = true; session.CreatedAt = SystemTime.UtcNow; HostContext.AppHost.OnSessionFilter(req, session, sessionId); req.Items[Keywords.Session] = session; } }
public object Put(PinPostComment request) { if (request.Id <= 0) { throw new ArgumentNullException(nameof(request.Id)); } if (request.PostId <= 0) { throw new ArgumentNullException(nameof(request.PostId)); } var user = GetUser(); var post = AssertPost(request.PostId); AssertCanPostToOrganization(Db, post.OrganizationId, user, out var org, out var orgMember); AssertCanContributeToPost(post, user, orgMember); if (post.UserId != user.GetUserId() && !user.IsOrganizationModerator(orgMember)) { throw HttpError.Forbidden("Only Post author can pin comments"); } Db.UpdateOnly(() => new Post { PinCommentId = request.Pin ? request.Id : (long?)null, Modified = DateTime.Now, ModifiedBy = user.UserName }, where : x => x.Id == request.PostId); Db.ExecuteSql( @"update user_activity set pinned_comment_count = (select count(*) from post p join post_comment c on (p.pin_comment_id = c.id and p.user_id <> user_activity.id) where c.user_id = user_activity.id) where id = (select user_id from post_comment c where c.id = @id)", new { id = request.Id }); ClearPostCaches(); return(new PinPostCommentResponse()); }
public async Task Delete(string id) { User user = await _sessionService.GetUser(); Post post = await _postRepository.GetById(id); if (post == null) { _logger.LogWarning($"Post {id} does not exist"); throw HttpError.NotFound($"Post {id} does not exist"); } if (post.AuthorId != user.Id) { _logger.LogWarning($"Post {id} does not belong to user"); throw HttpError.Forbidden($"Post {id} does not belong to user"); } await _postRepository.Delete(id); }
public void Put(HidePost request) { var user = GetUser(); var post = AssertPost(request.Id); AssertCanPostToOrganization(Db, post.OrganizationId, user, out var org, out var orgMember); if (!user.IsOrganizationModerator(orgMember)) { throw HttpError.Forbidden("Access Denied"); } var now = DateTime.Now; if (request.Hide) { post.Hidden = now; post.HiddenBy = user.UserName; if (!string.IsNullOrEmpty(request.Reason)) { post.Notes = request.Reason; } } else { post.Hidden = null; post.HiddenBy = null; } Db.Update(post); Db.Insert(new PostChangeHistory { ChangedName = nameof(post.Hidden), ChangedValue = request.Hide.ToString(), ChangedReason = request.Reason, Created = now, CreatedBy = user.UserName, }); ClearPostCaches(); }
public async Task Update(string id, UpdatePostDto dto) { User user = await _sessionService.GetUser(); Validate("modify", dto.Content, dto.Title, user); Post post = await _postRepository.GetById(id); if (post == null) { _logger.LogWarning($"Post {id} does not exist"); throw HttpError.NotFound($"Post {id} does not exist"); } if (post.AuthorId != user.Id) { _logger.LogWarning($"Post {id} does not belong to user"); throw HttpError.Forbidden($"Post {id} does not belong to user"); } post.Title = dto.Title; post.Content = dto.Content; post.LastUpdateTime = DateTime.Now; post.Tags = TagHelpers.GetTagsFromText(dto.Content); bool success = await _postRepository.Update(post); if (!success) { _logger.LogWarning("Error during update post"); throw HttpError.InternalServerError(""); } await _tagRepository.Create(post.Tags.Select(x => new Tag { Name = x, PostsNumber = 1 }).ToArray()); _logger.LogInformation("Tags have been added"); }
public object Any(ConvertSessionToToken request) { var jwtAuthProvider = AuthenticateService.GetAuthProvider(JwtAuthProvider.Name) as JwtAuthProvider; if (jwtAuthProvider == null) { throw new NotSupportedException("JwtAuthProvider is not registered"); } if (jwtAuthProvider.RequireSecureConnection && !Request.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection); } var session = Request.GetSession(); if (session.FromToken) { return(new ConvertSessionToTokenResponse()); } var token = jwtAuthProvider.CreateJwtBearerToken(session); if (!request.PreserveSession) { Request.RemoveSession(session.Id); } return(new HttpResult(new ConvertSessionToTokenResponse()) { Cookies = { new Cookie(Keywords.TokenCookie, token, Cookies.RootPath) { HttpOnly = true, Secure = Request.IsSecureConnection, Expires = DateTime.UtcNow.Add(jwtAuthProvider.ExpireTokensIn), } } }); }
public object Any(ConvertSessionToToken request) { var jwtAuthProvider = (JwtAuthProvider)AuthenticateService.GetRequiredJwtAuthProvider(); if (jwtAuthProvider.RequireSecureConnection && !Request.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection.Localize(Request)); } if (Request.ResponseContentType.MatchesContentType(MimeTypes.Html)) { Request.ResponseContentType = MimeTypes.Json; } var token = Request.GetJwtToken(); if (string.IsNullOrEmpty(token)) { var session = Request.GetSession(); token = jwtAuthProvider.CreateJwtBearerToken(Request, session); if (!request.PreserveSession) { Request.RemoveSession(session.Id); } } return(new HttpResult(new ConvertSessionToTokenResponse()) { Cookies = { new Cookie(Keywords.TokenCookie, token, Cookies.RootPath) { HttpOnly = true, Secure = Request.IsSecureConnection, Expires = DateTime.UtcNow.Add(jwtAuthProvider.ExpireTokensIn), } } }); }
public object Post(AddOrganizationMember request) { var user = GetUser(); AssertOrganizationModerator(Db, request.OrganizationId, user, out var org, out var orgMember); var requiresOwner = request.IsModerator || request.IsOwner; if (requiresOwner && !user.IsOrganizationOwner(orgMember)) { throw HttpError.Forbidden("This action is limited to Organization Owners"); } var memberUser = Db.Single <CustomUserAuth>(x => x.UserName.ToLower() == request.UserName.ToLower()); if (memberUser == null) { throw HttpError.NotFound("User does not exist"); } var existingMember = Db.Exists <OrganizationMember>(x => x.OrganizationId == request.OrganizationId && x.UserId == memberUser.Id); if (existingMember) { throw new ArgumentException("Member has already been added", nameof(request.UserName)); } var member = request.ConvertTo <OrganizationMember>(); member.UserId = memberUser.Id; member.UserName = memberUser.UserName; member.Created = member.Modified = DateTime.Now; member.CreatedBy = member.ModifiedBy = user.UserName; Db.Insert(member); ClearOrganizationCaches(); return(new AddOrganizationMemberResponse()); }
public async Task <object> Any(GetAccessToken request) { var jwtAuthProvider = (JwtAuthProvider)AuthenticateService.GetRequiredJwtAuthProvider(); if (jwtAuthProvider.RequireSecureConnection && !Request.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection.Localize(Request)); } var refreshTokenCookie = Request.Cookies.TryGetValue(Keywords.RefreshTokenCookie, out var refTok) ? refTok.Value : null; var refreshToken = request.RefreshToken ?? refreshTokenCookie; var accessToken = await jwtAuthProvider.CreateAccessTokenFromRefreshToken(refreshToken, Request).ConfigAwait(); var response = new GetAccessTokenResponse { AccessToken = accessToken }; // Don't return JWT in Response Body if Refresh Token Cookie was used if (refreshTokenCookie == null && jwtAuthProvider.UseTokenCookie != true) { return(response); } var httpResult = new HttpResult(new GetAccessTokenResponse()) .AddCookie(Request, new Cookie(Keywords.TokenCookie, accessToken, Cookies.RootPath) { HttpOnly = true, Secure = Request.IsSecureConnection, Expires = DateTime.UtcNow.Add(jwtAuthProvider.ExpireTokensIn), }); return(httpResult); }
public static void AssertCanPostTypeToOrganization(PostType postType, Organization org, OrganizationMember orgMember, AuthUserSession user) { if (user.IsOrganizationModerator(orgMember)) { if (!org.ModeratorPostTypes.IsEmpty()) { if (!org.ModeratorPostTypes.Contains(postType.ToString())) { throw HttpError.Forbidden(postType + " is not an allowed Type for Moderators"); } return; } } if (!org.PostTypes.IsEmpty()) { if (!org.PostTypes.Contains(postType.ToString())) { throw HttpError.Forbidden($"You cannot submit {postType} posts here"); } } }
public void Delete(RemoveOrganizationMember request) { var user = GetUser(); AssertOrganizationModerator(Db, request.OrganizationId, user, out var org, out var orgMember); var member = Db.Single <OrganizationMember>(x => x.UserId == request.UserId && x.OrganizationId == request.OrganizationId); var requiresOwner = member.IsOwner || member.IsModerator; if (requiresOwner && !user.IsOrganizationOwner(orgMember)) { throw HttpError.Forbidden("This action is limited to Organization Owners"); } Db.Delete <OrganizationMember>(x => x.UserId == request.UserId && x.OrganizationId == request.OrganizationId); Db.Delete <OrganizationMemberInvite>(x => x.UserId == request.UserId && x.OrganizationId == request.OrganizationId); SendSystemEmail(nameof(RemoveOrganizationMember), $"@{member.UserName} was removed from {org.Name} by {user.UserName}"); ClearOrganizationCaches(); }
public async Task Update(string postId, string id, UpdateCommentDto dto) { User user = await _sessionService.GetUser(); Validate("modify", dto.Content, user); Comment comment = await _commentRepository.GetById(id); if (comment == null) { _logger.LogWarning($"Comment {id} does not exist"); throw HttpError.NotFound($"Comment {id} does not exist"); } if (comment.PostId != postId) { throw HttpError.NotFound(""); } if (comment.AuthorId != user.Id) { _logger.LogWarning($"Comment {id} does not belong to user"); throw HttpError.Forbidden($"Comment {id} does not belong to user"); } comment.Content = dto.Content; comment.LastUpdateTime = DateTime.Now; bool success = await _commentRepository.Update(comment); if (!success) { _logger.LogWarning("Error during update comment"); throw HttpError.InternalServerError(""); } }
public async Task Update(string commentId, string id, UpdateResponseDto dto) { User user = await _sessionService.GetUser(); Validate("modify", dto.Content, user); Response response = await _responseRepository.GetById(id); if (response == null) { _logger.LogWarning($"Response {id} does not exist"); throw HttpError.NotFound($"Response {id} does not exist"); } if (response.CommentId != commentId) { throw HttpError.NotFound(""); } if (response.AuthorId != user.Id) { _logger.LogWarning($"Response {id} does not belong to user"); throw HttpError.Forbidden($"Response {id} does not belong to user"); } response.Content = dto.Content; response.LastUpdateTime = DateTime.Now; bool success = await _responseRepository.Update(response); if (!success) { _logger.LogWarning("Error during update response"); throw HttpError.InternalServerError(""); } }
public object Any(GetAccessToken request) { var jwtAuthProvider = (JwtAuthProvider)AuthenticateService.GetRequiredJwtAuthProvider(); if (jwtAuthProvider.RequireSecureConnection && !Request.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection.Localize(Request)); } if (string.IsNullOrEmpty(request.RefreshToken)) { throw new ArgumentNullException(nameof(request.RefreshToken)); } JsonObject jwtPayload; try { jwtPayload = jwtAuthProvider.GetVerifiedJwtPayload(Request, request.RefreshToken.Split('.')); } catch (ArgumentException) { throw; } catch (Exception ex) { throw new ArgumentException(ex.Message); } jwtAuthProvider.AssertJwtPayloadIsValid(jwtPayload); if (jwtAuthProvider.ValidateRefreshToken != null && !jwtAuthProvider.ValidateRefreshToken(jwtPayload, Request)) { throw new ArgumentException(ErrorMessages.RefreshTokenInvalid.Localize(Request), nameof(request.RefreshToken)); } var userId = jwtPayload["sub"]; IAuthSession session; IEnumerable <string> roles = null, perms = null; var userSessionSource = AuthenticateService.GetUserSessionSource(); if (userSessionSource != null) { session = userSessionSource.GetUserSession(userId); if (session == null) { throw HttpError.NotFound(ErrorMessages.UserNotExists.Localize(Request)); } roles = session.Roles; perms = session.Permissions; } else if (AuthRepository is IUserAuthRepository userRepo) { var userAuth = userRepo.GetUserAuth(userId); if (userAuth == null) { throw HttpError.NotFound(ErrorMessages.UserNotExists.Localize(Request)); } if (jwtAuthProvider.IsAccountLocked(userRepo, userAuth)) { throw new AuthenticationException(ErrorMessages.UserAccountLocked.Localize(Request)); } session = SessionFeature.CreateNewSession(Request, SessionExtensions.CreateRandomSessionId()); session.PopulateSession(userAuth, userRepo); if (userRepo is IManageRoles manageRoles && session.UserAuthId != null) { roles = manageRoles.GetRoles(session.UserAuthId); perms = manageRoles.GetPermissions(session.UserAuthId); } } else { throw new NotSupportedException("JWT RefreshTokens requires a registered IUserAuthRepository or an AuthProvider implementing IUserSessionSource"); } var accessToken = jwtAuthProvider.CreateJwtBearerToken(Request, session, roles, perms); var response = new GetAccessTokenResponse { AccessToken = accessToken }; if (request.UseTokenCookie != true) { return(response); } return(new HttpResult(new GetAccessTokenResponse()) { Cookies = { new Cookie(Keywords.TokenCookie, accessToken, Cookies.RootPath) { HttpOnly = true, Secure = Request.IsSecureConnection, Expires = DateTime.UtcNow.Add(jwtAuthProvider.ExpireTokensIn), } } }); }
public void PreAuthenticate(IRequest req, IResponse res) { if (req.OperationName != null && IgnoreForOperationTypes.Contains(req.OperationName)) { return; } var bearerToken = req.GetBearerToken() ?? req.GetCookieValue(Keywords.TokenCookie); if (bearerToken != null) { var parts = bearerToken.Split('.'); if (parts.Length == 3) { if (RequireSecureConnection && !req.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection); } var header = parts[0]; var payload = parts[1]; var signatureBytes = parts[2].FromBase64UrlSafe(); var headerJson = header.FromBase64UrlSafe().FromUtf8Bytes(); var payloadBytes = payload.FromBase64UrlSafe(); var headerData = headerJson.FromJson <Dictionary <string, string> >(); var bytesToSign = string.Concat(header, ".", payload).ToUtf8Bytes(); var algorithm = headerData["alg"]; //Potential Security Risk for relying on user-specified algorithm: https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/ if (RequireHashAlgorithm && algorithm != HashAlgorithm) { throw new NotSupportedException("Invalid algoritm '{0}', expected '{1}'".Fmt(algorithm, HashAlgorithm)); } if (!VerifyPayload(algorithm, bytesToSign, signatureBytes)) { return; } var payloadJson = payloadBytes.FromUtf8Bytes(); var jwtPayload = JsonObject.Parse(payloadJson); var session = CreateSessionFromPayload(req, jwtPayload); req.Items[Keywords.Session] = session; } else if (parts.Length == 5) //Encrypted JWE Token { if (RequireSecureConnection && !req.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection); } if (PrivateKey == null || PublicKey == null) { throw new NotSupportedException("PrivateKey is required to DecryptPayload"); } var jweHeaderBase64Url = parts[0]; var jweEncKeyBase64Url = parts[1]; var ivBase64Url = parts[2]; var cipherTextBase64Url = parts[3]; var tagBase64Url = parts[4]; var sentTag = tagBase64Url.FromBase64UrlSafe(); var aadBytes = (jweHeaderBase64Url + "." + jweEncKeyBase64Url).ToUtf8Bytes(); var iv = ivBase64Url.FromBase64UrlSafe(); var cipherText = cipherTextBase64Url.FromBase64UrlSafe(); var jweEncKey = jweEncKeyBase64Url.FromBase64UrlSafe(); var cryptAuthKeys256 = RsaUtils.Decrypt(jweEncKey, PrivateKey.Value, UseRsaKeyLength); var authKey = new byte[128 / 8]; var cryptKey = new byte[128 / 8]; Buffer.BlockCopy(cryptAuthKeys256, 0, authKey, 0, authKey.Length); Buffer.BlockCopy(cryptAuthKeys256, authKey.Length, cryptKey, 0, cryptKey.Length); using (var hmac = new HMACSHA256(authKey)) using (var encryptedStream = new MemoryStream()) { using (var writer = new BinaryWriter(encryptedStream)) { writer.Write(aadBytes); writer.Write(iv); writer.Write(cipherText); writer.Flush(); var calcTag = hmac.ComputeHash(encryptedStream.ToArray()); if (!calcTag.EquivalentTo(sentTag)) { return; } } } JsonObject jwtPayload; var aes = Aes.Create(); aes.KeySize = 128; aes.BlockSize = 128; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; using (aes) using (var decryptor = aes.CreateDecryptor(cryptKey, iv)) using (var ms = MemoryStreamFactory.GetStream(cipherText)) using (var cryptStream = new CryptoStream(ms, decryptor, CryptoStreamMode.Read)) { var jwtPayloadBytes = cryptStream.ReadFully(); jwtPayload = JsonObject.Parse(jwtPayloadBytes.FromUtf8Bytes()); } var session = CreateSessionFromPayload(req, jwtPayload); req.Items[Keywords.Session] = session; } } }
public async Task <object> Any(GetAccessToken request) { var jwtAuthProvider = (JwtAuthProvider)AuthenticateService.GetRequiredJwtAuthProvider(); if (jwtAuthProvider.RequireSecureConnection && !Request.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection.Localize(Request)); } if (string.IsNullOrEmpty(request.RefreshToken)) { throw new ArgumentNullException(nameof(request.RefreshToken)); } JsonObject jwtPayload; try { jwtPayload = jwtAuthProvider.GetVerifiedJwtPayload(Request, request.RefreshToken.Split('.')); } catch (ArgumentException) { throw; } catch (Exception ex) { throw new ArgumentException(ex.Message); } if (jwtPayload == null) { throw new ArgumentException(ErrorMessages.TokenInvalid.Localize(Request)); } jwtAuthProvider.AssertJwtPayloadIsValid(jwtPayload); if (jwtAuthProvider.ValidateRefreshToken != null && !jwtAuthProvider.ValidateRefreshToken(jwtPayload, Request)) { throw new ArgumentException(ErrorMessages.RefreshTokenInvalid.Localize(Request), nameof(request.RefreshToken)); } var userId = jwtPayload["sub"]; var result = await Request.GetSessionFromSourceAsync(userId, async (authRepo, userAuth) => { if (await jwtAuthProvider.IsAccountLockedAsync(authRepo, userAuth)) { throw new AuthenticationException(ErrorMessages.UserAccountLocked.Localize(Request)); } }).ConfigAwait(); if (result == null) { throw new NotSupportedException("JWT RefreshTokens requires a registered IUserAuthRepository or an AuthProvider implementing IUserSessionSource"); } var accessToken = jwtAuthProvider.CreateJwtBearerToken(Request, session: result.Session, roles: result.Roles, perms: result.Permissions); var response = new GetAccessTokenResponse { AccessToken = accessToken }; if (request.UseTokenCookie.GetValueOrDefault(jwtAuthProvider.UseTokenCookie) != true) { return(response); } return(new HttpResult(new GetAccessTokenResponse()) { Cookies = { new Cookie(Keywords.TokenCookie, accessToken, Cookies.RootPath) { HttpOnly = true, Secure = Request.IsSecureConnection, Expires = DateTime.UtcNow.Add(jwtAuthProvider.ExpireTokensIn), } } }); }
public object Any(GetAccessToken request) { var jwtAuthProvider = (MyJwtAuthProvider)AuthenticateService.GetRequiredJwtAuthProvider(); if (jwtAuthProvider.RequireSecureConnection && !Request.IsSecureConnection) { throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection.Localize(Request)); } if (string.IsNullOrEmpty(request.RefreshToken)) { throw new ArgumentNullException(nameof(request.RefreshToken)); } JsonObject jwtPayload; try { jwtPayload = jwtAuthProvider.GetVerifiedJwtPayload(Request, request.RefreshToken.Split(CharConstants.DOT)); } catch (ArgumentException) { throw; } catch (Exception ex) { throw new ArgumentException(ex.Message); } jwtAuthProvider.AssertJwtPayloadIsValid(jwtPayload); if (jwtAuthProvider.ValidateRefreshToken != null && !jwtAuthProvider.ValidateRefreshToken(jwtPayload, Request)) { throw new ArgumentException(ErrorMessages.RefreshTokenInvalid.Localize(Request), nameof(request.RefreshToken)); } var userId = jwtPayload[TokenConstants.SUB]; CustomUserSession session; if (AuthRepository is IUserAuthRepository userRepo) { var userAuth = userRepo.GetUserAuth(userId); if (userAuth == null) { throw HttpError.NotFound(ErrorMessages.UserNotExists.Localize(Request)); } if (jwtAuthProvider.IsAccountLocked(userRepo, userAuth)) { throw new AuthenticationException(ErrorMessages.UserAccountLocked.Localize(Request)); } session = SessionFeature.CreateNewSession(Request, SessionExtensions.CreateRandomSessionId()) as CustomUserSession; PopulateSession(userRepo, userAuth, session, userId); } else { throw new NotSupportedException("JWT RefreshTokens requires a registered IUserAuthRepository or an AuthProvider implementing IUserSessionSource"); } var accessToken = jwtAuthProvider.CreateJwtBearerToken(Request, session); return(new GetAccessTokenResponse { AccessToken = accessToken }); }