public void ValidateToken_ShouldThrowException_WhenClaimsPrincipalNull()
        {
            var token                     = "expectedToken";
            var validatedToken            = new Mock <SecurityToken>().Object;
            var tokenValidationParameters = new TokenValidationParameters();
            var introspectResponse        = new IntrospectResponse
            {
                Active = false
            };

            _mockTokenService
            .Setup(ts => ts.IntrospectToken(token, It.IsAny <HttpClient>()))
            .Returns(Task.FromResult(introspectResponse));

            _mockTokenValidator.Setup(stv =>
                                      stv.ValidateToken(
                                          token,
                                          tokenValidationParameters,
                                          out validatedToken))
            .Returns((ClaimsPrincipal)null);

            Action action = () => _sut
                            .ValidateToken(token, tokenValidationParameters, out validatedToken);

            action.Should().Throw <SecurityTokenValidationException>();

            validatedToken.Should().BeNull();
        }
        public void ValidateToken_ShouldThrowException_WhenIntrospectResponseIsNotActive()
        {
            var oktaId                    = "oktaId";
            var token                     = "expectedToken";
            var validatedToken            = new Mock <SecurityToken>().Object;
            var tokenValidationParameters = new TokenValidationParameters();
            var introspectResponse        = new IntrospectResponse
            {
                Active = false
            };
            var mockExpectedClaims = new Mock <ClaimsPrincipal>();
            var claims             = new List <Claim>();
            var claim = new Claim(MEClaimTypes.OktaUserId, oktaId);

            claims.Add(claim);
            mockExpectedClaims.Setup(cp => cp.Claims).Returns(claims);
            var identities = new List <ClaimsIdentity>();
            var identity   = new ClaimsIdentity();

            identities.Add(identity);
            mockExpectedClaims.Setup(cp => cp.Identities).Returns(identities);

            _mockUserSessionRetrievalByOktaIdService
            .Setup(service => service.Handle(It.IsAny <UserSessionRetrievalByOktaIdQuery>()))
            .Returns(Task.FromResult((MeUserSession)null))
            .Verifiable();

            _mockTokenService
            .Setup(ts => ts.IntrospectToken(token, It.IsAny <HttpClient>()))
            .Returns(Task.FromResult(introspectResponse));

            _mockTokenValidator.Setup(stv =>
                                      stv.ValidateToken(
                                          token,
                                          tokenValidationParameters,
                                          out validatedToken))
            .Returns(mockExpectedClaims.Object);

            Action action = () => _sut
                            .ValidateToken(token, tokenValidationParameters, out validatedToken)
                            .Should().Be(mockExpectedClaims.Object);

            action.Should().Throw <SecurityTokenValidationException>();

            validatedToken.Should().BeNull();
        }
        public void ValidateToken_ShouldThrowException_WhenClaimsPrincipalMissingOktaId()
        {
            var token                     = "expectedToken";
            var validatedToken            = new Mock <SecurityToken>().Object;
            var tokenValidationParameters = new TokenValidationParameters();
            var introspectResponse        = new IntrospectResponse
            {
                Active = false
            };
            var mockExpectedClaims = new Mock <ClaimsPrincipal>();

            mockExpectedClaims
            .Setup(cp => cp.Claims)
            .Returns(Enumerable.Empty <Claim>());
            mockExpectedClaims
            .Setup(cp => cp.Identities)
            .Returns(Enumerable.Empty <ClaimsIdentity>());

            _mockTokenService
            .Setup(ts => ts.IntrospectToken(token, It.IsAny <HttpClient>()))
            .Returns(Task.FromResult(introspectResponse));

            _mockTokenValidator.Setup(stv =>
                                      stv.ValidateToken(
                                          token,
                                          tokenValidationParameters,
                                          out validatedToken))
            .Returns(mockExpectedClaims.Object);

            Action action = () => _sut
                            .ValidateToken(token, tokenValidationParameters, out validatedToken);

            action.Should().Throw <SecurityTokenValidationException>();

            validatedToken.Should().BeNull();
        }
        public void ValidateToken_ShouldThrowException_WhenValidTokenAndNoUserOrSessionExists_AndUserExistsWithSameEmail_ButEmailIsAlreadyBound()
        {
            // Arrange
            var userId                    = "userId";
            var oktaId                    = "oktaId";
            var token                     = "expectedToken";
            var validatedToken            = new Mock <SecurityToken>().Object;
            var tokenValidationParameters = new TokenValidationParameters();
            var introspectResponse        = new IntrospectResponse
            {
                Active = true
            };
            var mockExpectedClaims = new Mock <ClaimsPrincipal>();
            var claims             = new List <Claim>();
            var claim = new Claim(MEClaimTypes.OktaUserId, oktaId);

            claims.Add(claim);
            mockExpectedClaims.Setup(cp => cp.Claims).Returns(claims);
            var identities = new List <ClaimsIdentity>();
            var identity   = new ClaimsIdentity();

            identities.Add(identity);
            mockExpectedClaims.Setup(cp => cp.Identities).Returns(identities);

            _mockTokenService
            .Setup(ts => ts.IntrospectToken(token, It.IsAny <HttpClient>()))
            .Returns(Task.FromResult(introspectResponse));

            var user = new MeUser
            {
                UserId = userId,
                OktaId = oktaId,
                Email  = "oktaEmail",
            };

            var oktaUser = new Mock <IUser>(MockBehavior.Strict);

            oktaUser.Setup(o => o.Id).Returns(oktaId);
            oktaUser.Setup(o => o.Profile.FirstName).Returns("oktaFirstName");
            oktaUser.Setup(o => o.Profile.LastName).Returns("oktaLastName");
            oktaUser.Setup(o => o.Profile.Email).Returns("oktaEmail");

            var mockUsersClient = new Mock <IUsersClient>(MockBehavior.Strict);

            mockUsersClient
            .Setup(service => service.GetUserAsync(It.IsAny <string>(), default(CancellationToken)))
            .Returns(Task.FromResult(oktaUser.Object));

            _mockOktaClient
            .Setup(service => service.Users)
            .Returns(mockUsersClient.Object);

            _mockUserSessionRetrievalByOktaIdService
            .Setup(service => service.Handle(It.IsAny <UserSessionRetrievalByOktaIdQuery>()))
            .Returns(Task.FromResult((MeUserSession)null))
            .Verifiable();

            _mockUserRetrievalByOktaId
            .Setup(service => service.Handle(It.IsAny <UserRetrievalByOktaIdQuery>()))
            .Returns(Task.FromResult((MeUser)null));

            _mockUserRetrievalByEmailService
            .Setup(service => service.Handle(It.IsAny <UserRetrievalByEmailQuery>()))
            .Returns(Task.FromResult(user));

            var createUserResponse = new MeUser
            {
                UserId = "createUserId"
            };

            _mockUserCreationService
            .Setup(service => service.Handle(It.IsAny <CreateUserQuery>()))
            .Returns((CreateUserQuery query) => Task.FromResult(createUserResponse))
            .Verifiable();

            _mockTokenValidator.Setup(stv =>
                                      stv.ValidateToken(
                                          token,
                                          tokenValidationParameters,
                                          out validatedToken))
            .Returns(mockExpectedClaims.Object);

            _mockUserSessionUpdateOktaTokenService
            .Setup(service => service.Handle(It.IsAny <UserSessionUpdateOktaTokenQuery>()))
            .Returns((UserSessionUpdateOktaTokenQuery param) => Task.FromResult(new MeUserSession()
            {
                UserId          = param.UserId,
                OktaId          = oktaId,
                OktaToken       = param.OktaToken,
                OktaTokenExpiry = param.OktaTokenExpiry,
            }))
            .Verifiable();

            // Act
            Action action = () => _sut
                            .ValidateToken(token, tokenValidationParameters, out validatedToken)
                            .Should().Be(mockExpectedClaims.Object);

            // Assert
            action.Should().Throw <Exception>();
        }
        public void ValidateToken_ShouldReturnClaimsPrincipalAndNotUpdateUserInfo_WhenValidTokenChangedButUserInfoAlreadyUpToDate()
        {
            // Arrange
            var userId                    = "userId";
            var oktaId                    = "oktaId";
            var token                     = "expectedToken";
            var originalToken             = "expectedOriginalToken";
            var validatedToken            = new Mock <SecurityToken>().Object;
            var tokenValidationParameters = new TokenValidationParameters();
            var introspectResponse        = new IntrospectResponse
            {
                Active = true
            };
            var mockExpectedClaims = new Mock <ClaimsPrincipal>();
            var claims             = new List <Claim>();
            var claim = new Claim(MEClaimTypes.OktaUserId, oktaId);

            claims.Add(claim);
            mockExpectedClaims.Setup(cp => cp.Claims).Returns(claims);
            var identities = new List <ClaimsIdentity>();
            var identity   = new ClaimsIdentity();

            identities.Add(identity);
            mockExpectedClaims.Setup(cp => cp.Identities).Returns(identities);

            _mockTokenService
            .Setup(ts => ts.IntrospectToken(token, It.IsAny <HttpClient>()))
            .Returns(Task.FromResult(introspectResponse));

            var session = new MeUserSession
            {
                UserId          = userId,
                OktaId          = oktaId,
                OktaToken       = originalToken,
                OktaTokenExpiry = DateTimeOffset.Now.AddDays(-1),
            };

            var user = new MeUser
            {
                UserId    = userId,
                FirstName = "oktaFirstName",
                LastName  = "oktaLastName",
                Email     = "oktaEmail",
            };

            var oktaUser = new Mock <IUser>(MockBehavior.Strict);

            oktaUser.Setup(o => o.Profile.FirstName).Returns("oktaFirstName");
            oktaUser.Setup(o => o.Profile.LastName).Returns("oktaLastName");
            oktaUser.Setup(o => o.Profile.Email).Returns("oktaEmail");

            var mockUsersClient = new Mock <IUsersClient>(MockBehavior.Strict);

            mockUsersClient
            .Setup(service => service.GetUserAsync(It.IsAny <string>(), default(CancellationToken)))
            .Returns(Task.FromResult(oktaUser.Object));

            _mockOktaClient
            .Setup(service => service.Users)
            .Returns(mockUsersClient.Object);

            _mockUserSessionRetrievalByOktaIdService
            .Setup(service => service.Handle(It.IsAny <UserSessionRetrievalByOktaIdQuery>()))
            .Returns(Task.FromResult(session))
            .Verifiable();

            _mockTokenValidator.Setup(stv =>
                                      stv.ValidateToken(
                                          token,
                                          tokenValidationParameters,
                                          out validatedToken))
            .Returns(mockExpectedClaims.Object);

            _mockUserSessionUpdateOktaTokenService
            .Setup(service => service.Handle(It.IsAny <UserSessionUpdateOktaTokenQuery>()))
            .Returns((UserSessionUpdateOktaTokenQuery param) => Task.FromResult(new MeUserSession()
            {
                UserId          = param.UserId,
                OktaId          = session.OktaId,
                OktaToken       = param.OktaToken,
                OktaTokenExpiry = param.OktaTokenExpiry,
            }))
            .Verifiable();

            _mockUserRetrievalById
            .Setup(service => service.Handle(It.IsAny <UserRetrievalByIdQuery>()))
            .Returns(Task.FromResult(user));

            _mockUserUpdateService
            .Setup(service => service.Handle(It.IsAny <UserUpdateQuery>()))
            .Verifiable();

            // Act
            _sut.ValidateToken(token, tokenValidationParameters, out validatedToken)
            .Should().Be(mockExpectedClaims.Object);

            // Assert
            _mockTokenService
            .Verify(ts => ts.IntrospectToken(token, It.IsAny <HttpClient>()));

            _mockUserSessionUpdateOktaTokenService
            .Verify(service => service.Handle(It.IsAny <UserSessionUpdateOktaTokenQuery>()));

            _mockUserUpdateService
            .Verify(service => service.Handle(It.IsAny <UserUpdateQuery>()), Times.Never);
        }
        public void ValidateToken_ShouldReturnClaimsPrincipal_WhenValidTokenPassedAndIntrospectResponseIsActive()
        {
            var userId                    = "userId";
            var oktaId                    = "oktaId";
            var token                     = "expectedToken";
            var validatedToken            = new Mock <SecurityToken>().Object;
            var tokenValidationParameters = new TokenValidationParameters();
            var introspectResponse        = new IntrospectResponse
            {
                Active = true
            };
            var mockExpectedClaims = new Mock <ClaimsPrincipal>();
            var claims             = new List <Claim>();
            var claim = new Claim(MEClaimTypes.OktaUserId, oktaId);

            claims.Add(claim);
            mockExpectedClaims.Setup(cp => cp.Claims).Returns(claims);
            var identities = new List <ClaimsIdentity>();
            var identity   = new ClaimsIdentity();

            identities.Add(identity);
            mockExpectedClaims.Setup(cp => cp.Identities).Returns(identities);

            _mockTokenService
            .Setup(ts => ts.IntrospectToken(token, It.IsAny <HttpClient>()))
            .Returns(Task.FromResult(introspectResponse));

            var session = new MeUserSession
            {
                UserId          = userId,
                OktaId          = oktaId,
                OktaToken       = token,
                OktaTokenExpiry = DateTimeOffset.Now.AddDays(-1),
            };

            _mockUserSessionRetrievalByOktaIdService
            .Setup(service => service.Handle(It.IsAny <UserSessionRetrievalByOktaIdQuery>()))
            .Returns(Task.FromResult(session))
            .Verifiable();

            _mockTokenValidator.Setup(stv =>
                                      stv.ValidateToken(
                                          token,
                                          tokenValidationParameters,
                                          out validatedToken))
            .Returns(mockExpectedClaims.Object);

            _mockUserSessionUpdateOktaTokenService
            .Setup(service => service.Handle(It.IsAny <UserSessionUpdateOktaTokenQuery>()))
            .Returns((UserSessionUpdateOktaTokenQuery param) => Task.FromResult(new MeUserSession()
            {
                UserId          = param.UserId,
                OktaId          = session.OktaId,
                OktaToken       = param.OktaToken,
                OktaTokenExpiry = param.OktaTokenExpiry,
            }))
            .Verifiable();

            _sut.ValidateToken(token, tokenValidationParameters, out validatedToken)
            .Should().Be(mockExpectedClaims.Object);

            _mockTokenService
            .Verify(ts => ts.IntrospectToken(token, It.IsAny <HttpClient>()));

            _mockUserSessionUpdateOktaTokenService
            .Verify(service => service.Handle(It.IsAny <UserSessionUpdateOktaTokenQuery>()));
        }