private static TokenManager GetTokenManager()
        {
            var options       = CreateOptions();
            var claimsManager = CreateClaimsManager(options);

            var factory                = new LoggerFactory();
            var protector              = new EphemeralDataProtectionProvider(factory).CreateProtector("test");
            var codeSerializer         = new TokenDataSerializer <AuthorizationCode>(options, ArrayPool <char> .Shared);
            var codeDataFormat         = new SecureDataFormat <AuthorizationCode>(codeSerializer, protector);
            var refreshTokenSerializer = new TokenDataSerializer <RefreshToken>(options, ArrayPool <char> .Shared);
            var refreshTokenDataFormat = new SecureDataFormat <RefreshToken>(refreshTokenSerializer, protector);

            var timeStampManager   = new TimeStampManager();
            var credentialsPolicy  = GetCredentialsPolicy(options, timeStampManager);
            var codeIssuer         = new AuthorizationCodeIssuer(claimsManager, codeDataFormat, new ProtocolErrorProvider());
            var accessTokenIssuer  = new JwtAccessTokenIssuer(claimsManager, credentialsPolicy, new JwtSecurityTokenHandler(), options);
            var idTokenIssuer      = new JwtIdTokenIssuer(claimsManager, credentialsPolicy, new JwtSecurityTokenHandler(), options);
            var refreshTokenIssuer = new RefreshTokenIssuer(claimsManager, refreshTokenDataFormat);

            return(new TokenManager(
                       codeIssuer,
                       accessTokenIssuer,
                       idTokenIssuer,
                       refreshTokenIssuer,
                       new ProtocolErrorProvider()));
        }
        public async Task JwtRefreshTokenIssuer_IncludesAllRequiredData()
        {
            // Arrange
            var dataFormat       = GetDataFormat();
            var options          = GetOptions();
            var expectedDateTime = new DateTimeOffset(2000, 01, 01, 0, 0, 0, TimeSpan.FromHours(1));
            var timeManager      = GetTimeManager(expectedDateTime, expectedDateTime.AddHours(1), expectedDateTime);
            var issuer           = new RefreshTokenIssuer(GetClaimsManager(timeManager), dataFormat);
            var context          = GetTokenGenerationContext(
                new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "user") })),
                new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(IdentityServiceClaimTypes.ClientId, "clientId") })));

            context.InitializeForToken(TokenTypes.RefreshToken);

            // Act
            await issuer.IssueRefreshTokenAsync(context);

            // Assert
            Assert.NotNull(context.RefreshToken);
            var RefreshToken = Assert.IsType <RefreshToken>(context.RefreshToken.Token);

            Assert.NotNull(RefreshToken);
            Assert.NotNull(RefreshToken.Id);
            Assert.Equal("user", RefreshToken.UserId);
            Assert.Equal("clientId", RefreshToken.ClientId);
            Assert.Equal(new[] { "openid profile" }, RefreshToken.Scopes);
            Assert.Equal(expectedDateTime, RefreshToken.IssuedAt);
            Assert.Equal(expectedDateTime.AddHours(1), RefreshToken.Expires);
            Assert.Equal(expectedDateTime, RefreshToken.NotBefore);
        }
        public async Task JwtRefreshTokenIssuer_Fails_IfUserIsMissingUserId()
        {
            // Arrange
            var dataFormat  = GetDataFormat();
            var options     = GetOptions();
            var timeManager = GetTimeManager();
            var issuer      = new RefreshTokenIssuer(GetClaimsManager(), dataFormat);
            var context     = GetTokenGenerationContext();

            context.InitializeForToken(TokenTypes.RefreshToken);

            // Act
            var exception = await Assert.ThrowsAsync <InvalidOperationException>(
                () => issuer.IssueRefreshTokenAsync(context));

            // Assert
            Assert.Equal($"Missing '{ClaimTypes.NameIdentifier}' claim from the user.", exception.Message);
        }
        public async Task JwtRefreshTokenIssuer_ExchangeRefreshTokenAsync_ReadTheRefreshTokenCorrectly()
        {
            // Arrange
            var options   = GetOptions();
            var protector = new EphemeralDataProtectionProvider(new LoggerFactory()).CreateProtector("test");
            var refreshTokenSerializer = new TokenDataSerializer <RefreshToken>(options, ArrayPool <char> .Shared);
            var dataFormat             = new SecureDataFormat <RefreshToken>(refreshTokenSerializer, protector);

            var expectedDateTime = new DateTimeOffset(2000, 01, 01, 0, 0, 0, TimeSpan.FromHours(1));
            var now         = DateTimeOffset.UtcNow;
            var expires     = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, TimeSpan.Zero);
            var timeManager = GetTimeManager(expectedDateTime, expires, expectedDateTime);

            var issuer  = new RefreshTokenIssuer(GetClaimsManager(timeManager), dataFormat);
            var context = GetTokenGenerationContext(
                new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "user") })),
                new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(IdentityServiceClaimTypes.ClientId, "clientId") })));

            context.InitializeForToken(TokenTypes.RefreshToken);

            await issuer.IssueRefreshTokenAsync(context);

            var message = new OpenIdConnectMessage();

            message.ClientId     = "clientId";
            message.RefreshToken = context.RefreshToken.SerializedValue;

            // Act
            var grant = await issuer.ExchangeRefreshTokenAsync(message);

            // Assert
            Assert.NotNull(grant);
            Assert.NotNull(grant.Token);
            var refreshToken = Assert.IsType <RefreshToken>(grant.Token);

            Assert.Equal("clientId", refreshToken.ClientId);
            Assert.Equal("user", refreshToken.UserId);

            Assert.Equal(expectedDateTime, refreshToken.IssuedAt);
            Assert.Equal(expires, refreshToken.Expires);
            Assert.Equal(expectedDateTime, refreshToken.NotBefore);

            Assert.Equal(new[] { "openid profile" }, refreshToken.Scopes.ToArray());
        }
        public async Task JwtRefreshTokenIssuer_Fails_IfApplicationIsMissingClientId()
        {
            // Arrange
            var dataFormat  = GetDataFormat();
            var options     = GetOptions();
            var timeManager = GetTimeManager();
            var issuer      = new RefreshTokenIssuer(GetClaimsManager(), dataFormat);
            var context     = GetTokenGenerationContext(
                new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "user") })));

            context.InitializeForToken(TokenTypes.RefreshToken);

            // Act
            var exception = await Assert.ThrowsAsync <InvalidOperationException>(
                () => issuer.IssueRefreshTokenAsync(context));

            // Assert
            Assert.Equal($"Missing '{IdentityServiceClaimTypes.ClientId}' claim from the application.", exception.Message);
        }