public virtual IHttpActionResult RequestRefresh([FromBody] RefreshParams rp) { return(ExecuteValidatedAction(() => { // manually validating, as api is no longer wired up... ValidatorHelpers.ValidateAndThrow(rp, new RefreshParamsValidator()); // validate AuthClient and RefreshToken JwtConfig config = new JwtConfig(true, RequestLeftPart); AuthClient client = ValidateClient(rp); AuthToken rt = AuthService.RetrieveToken(rp.AuthUserId, rp.AuthClientId, rp.TokenIdentifier); AddNoCacheHeader(); if (client == null || rt == null || rt.AuthClientId != client.Id || !JsonWebToken.GrantNewAccess(config, rt.Token)) { return ImATeapot(); } // get user AuthUser user = AuthService.GetByIdForLogin(rt.AuthUserId); if (user == null) { return ImATeapot(); } CheckSetRoleManager(user); // make sure state is set in RoleManager ILoginResultDto loginResult = CreateTokenResult(user, client, config); // create new tokens, return result return loginResult != null ? (IHttpActionResult)Ok(loginResult) : ImATeapot(); })); }
/// <summary> /// Generates a reset link and sets to auth user's designated email. For use on initial /// creation of new users. /// </summary> /// <param name="user"> </param> /// <param name="email"></param> public void SendNewUserResetEmail(AuthUser user, string email) { string msgText = "A new account has been created for " + user.Username + ". Please use the following link within 24 hours to set up a password:"******"New Account Created", msgText); }
public virtual IHttpActionResult ResetPassword([FromBody] ResetPasswordParams rpp) { return(ExecuteValidatedAction(() => { ValidatorHelpers.ValidateAndThrow(rpp, new ResetPasswordParamsValidator()); // validate client AuthClient client = ValidateClient(rpp); if (client == null) { return ImATeapot(); } // validate user AuthUser user = AuthService.ValidateReset(rpp.AuthUserId, rpp.ResetKey); if (user == null) { return BadRequest(); } // change password AuthService.UpdatePassword(user, rpp.Password); CheckSetRoleManager(user); // make sure state is set in RoleManager ILoginResultDto result = CreateTokenResult(user, client); // return token AuthService.MarkResetInvalid(rpp.AuthUserId); return result != null ? (IHttpActionResult)Ok(result) : ImATeapot(); })); }
/// <summary> /// Creates a new AuthUser, given a username and password. Returns the new AuthUser's Id. /// </summary> /// <param name="username"></param> /// <param name="password"></param> /// <param name="userRoleId"></param> /// <returns>Returns the Id of the created AuthUser.</returns> public int Create(string username, string password, int userRoleId) { AuthUser au = GenerateAuthUser(username, false, password, userRoleId); Context.AuthUsers.Add(au); Context.SaveChanges(); return(au.Id); }
/// <summary> /// This method can be overridden to return specific info about whatever entity is being /// used for authentication, so long as the return type implements the ILoginResultDto interface. /// </summary> /// <param name="authUser"></param> /// <param name="client"></param> /// <param name="config"></param> /// <returns></returns> protected virtual ILoginResultDto CreateTokenResult(AuthUser authUser, AuthClient client, JwtConfig config) { LoginResult lr = GetBaseLoginResult(authUser, client, config); return(new DefaultLoginResult { LoginResult = lr }); }
/// <summary> /// Updates an AuthUser. /// </summary> /// <param name="authUser"></param> /// <returns>Returns the updated AuthUser.</returns> public AuthUser Update(AuthUser authUser) { ThrowIfNull(authUser); ValidateAndThrow(authUser, _authValidator); Context.SetEntityState(authUser, EntityState.Modified); Context.SaveChanges(); return(authUser); }
private static string CreateResetLink(AuthUser user, string resetKey) { var adminSite = AppSettings.GetAdminSite(); var resetEndpoint = AppSettings.GetResetEndpoint(); var href = $"{adminSite}{resetEndpoint}?resetKey={resetKey}&userId={user.Id}"; return(GenerateLink(href, "Reset Password")); }
private void SendResetEmail(AuthUser user, string email, string title, string msgText) { string resetKey = HttpServerUtility.UrlTokenEncode(user.ResetKey); string from = AppSettings.GetDefaultEmailFrom(); string link = CreateResetLink(user, resetKey); string body = $"{msgText}<br />{link}"; Email.SendEmail(from, email, title, body); }
/// <summary> /// Accepts reset key. Used during forgot password. /// </summary> /// <param name="userId"> </param> /// <param name="resetKey"></param> /// <returns>Returns a validated AuthUser, or null if validation failed.</returns> public AuthUser ValidateReset(int userId, string resetKey) { AuthUser user = GetByIdForLogin(userId); if (user == null) { return(null); } byte[] keyBytes = HttpServerUtility.UrlTokenDecode(resetKey); return(IsValidResetKey(user, keyBytes) ? user : null); }
/// <summary> /// Sends an invite email without a reset link. /// </summary> /// <param name="user"> </param> /// <param name="email"></param> public void SendNewUserInitEmail(AuthUser user, string email) { string msgText = $"A new account has been created for {user.Username}. " + "You may use use this to sign in:"; string from = AppSettings.GetDefaultEmailFrom(); string link = CreateDefaultAdminSiteLink(); const string title = "New Account Created"; string body = $"{msgText}<br />{link}"; Email.SendEmail(from, email, title, body); }
private static IDictionary <string, string[]> CreateJwtPayload(AuthUser user, AuthClient client) { var payload = new Dictionary <string, string[]> { [OwinKeys.AuthUserId] = new[] { user.Id.ToString() }, [OwinKeys.AuthUsername] = new[] { user.Username }, [OwinKeys.AuthClientId] = new[] { client.Id.ToString() }, [OwinKeys.UserRoleId] = new[] { user.RoleId.ToString() } }; return(payload); }
public async Task <ActionResult <Model.AuthUser> > PostAuthUser(Model.AuthUser insert) { Models.AuthUser input = _mapper.Map <Models.AuthUser>(insert); _context.AuthUser.Add(input); await _context.SaveChangesAsync(); var result = await _context.AuthUser.FindAsync(input.Id); return(_mapper.Map <Model.AuthUser>(result)); //return CreatedAtAction("Get", new { id = authUser.Id }, authUser); }
/// <summary> /// Updates a user's password. /// </summary> /// <param name="user"></param> /// <param name="password"></param> /// <returns>Returns true unless an error occurs.</returns> public bool UpdatePassword(AuthUser user, string password) { ThrowIfNull(user); if (!user.IsEditable) { throw new ValidationException("This is a protected user and cannot be edited."); } ValidatePasswordStrength(password); var sh = new SaltedHashGenerator(password); user.Password = sh.SaltedHash; user.Salt = sh.Salt; Context.SetEntityState(user, EntityState.Modified); Context.SaveChanges(); return(true); }
/// <summary> /// Creates a basic login result. /// Adds user role claims to Jwt payload /// NOTE: If you duplicate a key in the additionalPayload, this will error. /// </summary> /// <param name="authUser"></param> /// <param name="client"></param> /// <param name="config"></param> /// <param name="additionalPayload"></param> /// <returns></returns> protected LoginResult GetBaseLoginResult(AuthUser authUser, AuthClient client, JwtConfig config, IDictionary <string, string> additionalPayload = null) { config.RefreshMinutes = client.RefreshTokenMinutes; // MUST set refresh minutes by client var now = DateTime.UtcNow; IDictionary <string, string[]> payload = CreateJwtPayload(authUser, client); if (additionalPayload != null) { foreach (var kv in additionalPayload) { payload.Add(kv.Key, new[] { kv.Value }); } } // add ossied time for easier parsing payload.Add(OwinKeys.Ticks, new[] { now.Ticks.ToString() }); // add claims bool hasClaims = (authUser.UserRole?.UserRoleClaims != null); var claimFlags = new Dictionary <int, int>(); if (hasClaims) { foreach (var cgroup in authUser.UserRole.UserRoleClaims.GroupBy(cv => cv.ClaimTypeId)) { int claimValues = cgroup.Aggregate(0, (v, urc) => v | urc.ClaimValueId); // | them together claimFlags.Add(cgroup.Key, claimValues); payload[ClaimsHelper.SetTypePrefix(cgroup.Key)] = new [] { claimValues.ToString() }; } } string accessToken = JsonWebToken.CreateAccessToken(config, now, payload); string refreshToken = JsonWebToken.CreateRefreshToken(config, now, payload); string csrfToken = CsrfToken.Create(accessToken); Guid refreshGuid = AuthService.CreateToken(authUser.Id, client.Id, now, config.RefreshMinutes, refreshToken); return(new LoginResult { AuthUserId = authUser.Id, ClaimFlags = claimFlags, IssuedUtc = now, ExpiresUtc = now.AddMinutes(config.AccessMinutes), RefreshTokenIdentifier = refreshGuid.ToString(), Jwt = accessToken, CsrfToken = csrfToken }); }
public virtual IHttpActionResult GrantAdminDomainEmailAccess([FromBody] DomainEmailPasswordParams depp) { return(ExecuteValidatedAction(() => { ValidatorHelpers.ValidateAndThrow(depp, new DomainEmailPasswordParamsValidator()); AuthClient client = ValidateClient(depp); if (client == null) { return ImATeapot(); } AuthUser au = AuthService.ValidateDomainEmailLogin(depp.ResetKey); if (au == null) { return ImATeapot(); } CheckSetRoleManager(au); ILoginResultDto result = CreateTokenResult(au, client); // return token return result != null ? (IHttpActionResult)Ok(result) : ImATeapot(); })); }
/// <summary> /// Overload that accepts userId instead of username. Useful when validating user before /// updating a password. /// </summary> /// <param name="userId"> </param> /// <param name="password"></param> /// <returns>Returns a validated AuthUser, or null if validation failed.</returns> public AuthUser ValidateLogin(int userId, string password) { AuthUser user = GetByIdForLogin(userId); return((AuthUser)CheckVerifiableByPassword(user, password)); }
/// <summary> /// Validates an AuthUser. /// </summary> /// <param name="user"></param> public void ValidateAndThrow(AuthUser user) { ValidateAndThrow(user, _authValidator); }
/// <summary> /// Generates a reset link and sends to auth user's designated email. For use when users /// forget their passwords. /// </summary> /// <param name="user"> </param> /// <param name="email"></param> public void SendForgotPasswordEmail(AuthUser user, string email) { const string msgText = "Please use the following link to reset your password:"******"Reset Password", msgText); }
/// <summary> /// Checks username for uniqueness. This can be chained in the Must extension overload /// for Fluent Validation, which accepts the entity itself as the first parameter if you /// need to use another field in your logic. /// </summary> /// <param name="user"> </param> /// <param name="username"></param> /// <returns></returns> public bool IsUniqueUsername(AuthUser user, string username) { return(!Context.AuthUsers.Any(au => au.Username == username && au.Id != user.Id)); }
private bool IsValidResetKey(AuthUser user, byte[] keyBytes) { return(keyBytes != null && keyBytes.SequenceEqual(user.ResetKey) && user.ResetKeyExpirationUtc >= DateTime.UtcNow); }
protected ILoginResultDto CreateTokenResult(AuthUser user, AuthClient client) { JwtConfig config = new JwtConfig(true, RequestLeftPart); return(CreateTokenResult(user, client, config)); }
/// <summary> /// Sets a new reset key for a user, good for 15 minutes by default. /// </summary> /// <param name="user"> </param> /// <param name="resetMinutes"></param> public void SetResetKey(AuthUser user, int resetMinutes = 15) { user.ResetKey = Encryption.GetSalt(); user.ResetKeyExpirationUtc = DateTime.UtcNow.AddMinutes(resetMinutes); Update(user); }
private void CheckSetRoleManager(AuthUser user) { RoleManager.CheckSetUserTime(user.Id); RoleManager.CheckSetRoleTime(user.RoleId); }