/// <summary> /// Create the encrypted token based on a username and associated claims /// </summary> /// <param name="userName">The user name to get claims and roles for</param> /// <param name="maskUserName">The mask username to use</param> /// <returns>The encrypted token</returns> private EncryptedAuthenticationToken CreateEncryptedAuthenticationToken(string userName, string maskUserName) { var isMasquerading = !string.IsNullOrEmpty(maskUserName); var roles = isMasquerading ? Roles.GetRolesForUser(maskUserName) : Roles.GetRolesForUser(userName); MembershipUser user = Membership.GetUser(userName); if (user == null) { throw new AccessDeniedException(ErrorFactory.CreateAndLogError(Errors.SRVEX20001, "AuthenticationManager.CreateAuthenticationToken", additionalInfo: "Unable to find Membership User {0} - {1}.", arguments: new object[] { userName, maskUserName }, additionalDescriptionParameters: new object[] { userName, maskUserName })); } Guid userId = (Guid)user.ProviderUserKey; if (isMasquerading) { MembershipUser maskUser = Membership.GetUser(maskUserName); userId = (Guid)maskUser.ProviderUserKey; } // Find the regions for the userId string[] stringRegionIds = GetRegionsForUser(userId); // Find the primary business Id long? primaryBusinessId = FindPrimaryBusinessId(userId); if (isMasquerading && primaryBusinessId != null) { userEventDao.Create(new UserEvent { UserId = userId, UserEventType = new UserEventType { Code = UserEventTypesEnum.MasqueradeUser.GetCode() }, CreatedBy = (Guid)user.ProviderUserKey }); } //get claims based on specific roles / business status for an user List<Claim> claims = new List<Claim>(); if (!isMasquerading && primaryBusinessId != null) { BusinessStatus businessStatus = businessStatusDao.GetByBusinessId(primaryBusinessId.Value, null); if (businessStatus.PmsStatus == PmsStatus.ReadOnly) { claims = claimDao.GetNonWriteClaims(roles); } if (businessStatus.PmsStatus == PmsStatus.Active) { claims = claimDao.GetClaimsByRoles(roles); } // not active, nor read only, so do access denied if (businessStatus.PmsStatus == PmsStatus.Inactive || businessStatus.PmsStatus == PmsStatus.Unknown) { userEventDao.Create(new UserEvent { UserId = userId, UserEventType = new UserEventType { Code = UserEventTypesEnum.LoginAttemptFailed.GetCode() }, CreatedBy = (Guid)user.ProviderUserKey }); throw new AccessDeniedException("SRVEX20001"); } } else // get everything as normal if masquerading { claims = claimDao.GetClaimsByRoles(roles); } DateTime issueDate = DateTime.UtcNow; DateTime expiryDate = issueDate.Add(SecurityTokenValidity); var token = new AuthenticationToken(userName, issueDate, expiryDate, claims.Select(u => u.Name).ToArray(), stringRegionIds, primaryBusinessId ?? -1); return new EncryptedAuthenticationToken(GenerateTokenString(token), token.ValidTo, GenerateClaimToken(claims)); }
/// <summary> /// Generate a string for the Authentication Token /// </summary> public static string GenerateTokenString(AuthenticationToken authenticationToken) { byte[] randomNumberBytes = new byte[24]; string unencryptedToken; string unencryptedTokenSecondPart; string encryptedToken; RNGCryptoServiceProvider csp = new RNGCryptoServiceProvider(); csp.GetBytes(randomNumberBytes); // To avoid errors occurring when the token is deserialized. If no regions are available -1 will be inserted instead of a blank string. string serializedRegions = authenticationToken.Regions.Length == 0 ? "-1" : authenticationToken.Regions.Serialize(); // Create the token unencryptedTokenSecondPart = "|" + authenticationToken.Username + "|" + authenticationToken.ValidFrom.ToString(stdFormatProvider) + "|" + authenticationToken.ValidTo.ToString(stdFormatProvider) + "|" + authenticationToken.Claims.Serialize() + "|" + serializedRegions + "|" + authenticationToken.PrimaryBusinessId.ToString(); ASCIIEncoding textConverter = new ASCIIEncoding(); //Convert the data to a byte array. string randomString = textConverter.GetString(randomNumberBytes); unencryptedToken = randomString + unencryptedTokenSecondPart; encryptedToken = DesCrypto.Encrypt(unencryptedToken); return encryptedToken; }
/// <summary> /// Validates the token string and returns an AuthenticationToken at the end /// </summary> /// <param name="tokenString">Token string</param> /// <param name="authToken">OUTPUT: AuthenticationToken</param> /// <returns>True if valid and false if the token string is not valid</returns> public static bool Validate(string tokenString, out AuthenticationToken authToken) { AuthenticationToken token = Parse(tokenString); authToken = null; // has not expired if (token.ValidTo <= DateTime.UtcNow) { //Authentication Token has expired. return false; } // issue date is valid if (token.ValidFrom > DateTime.UtcNow.AddHours(TOKEN_FUTURE_LEEWAY_HOURS)) { //SSOToken issue date is greater than future leeway hours. return false; } authToken = token; return true; }
/// <summary> /// Parse the token string and convert it to a SSOToken /// </summary> /// <param name="tokenString">Token string</param> /// <returns>Authentication Token</returns> public static AuthenticationToken Parse(string tokenString) { string unencryptedToken = DesCrypto.Decrypt(tokenString); string randomNumber = unencryptedToken.Substring(0, 24); string[] parts = unencryptedToken.Substring(25).Split(new char[] { '|' }); AuthenticationToken token = new AuthenticationToken(parts[0], Convert.ToDateTime(parts[1], stdFormatProvider), Convert.ToDateTime(parts[2], stdFormatProvider), parts[3].Deserialize(), parts[4].Deserialize(), Convert.ToInt64(parts[5])); return token; }
public void CreateTokenStringProducesTokenAndParseSuccessfullyDecrypts() { // Arrange AuthenticationToken token = new AuthenticationToken(DUMMYUSERNAME, DateTime.UtcNow.AddHours(-1), DateTime.UtcNow.AddHours(23), new string[] { "MapErrors" }, new string[] { "UK" }, 1); // Act string encryptedToken = AuthenticationManager.GenerateTokenString(token); // Assert Assert.IsNotNull(encryptedToken, "Check a non null token was returned"); Assert.AreNotEqual(String.Empty, encryptedToken, "Check that non empty token was returned"); Assert.IsFalse(encryptedToken.Contains(DUMMYUSERNAME), "Check it is encrypted by Confirming we can not see the username in the encrypted string."); AuthenticationToken decryptedToken = AuthenticationManager.Parse(encryptedToken); Assert.AreEqual(token.Username, decryptedToken.Username, "Check that username still matches after decryption"); Assert.IsTrue(token.Claims.SequenceEqual(decryptedToken.Claims), "Check that the claims still match after the decryption"); Assert.IsTrue(token.Regions.SequenceEqual(decryptedToken.Regions), "Check that the regions still match after the decryption"); }