public void ShouldCreateParameters()
        {
            var authOptions = new AuthOptions
            {
                JwtIssuer = "jwtIssuer"
            };

            var devPermissionsOptions = new DevPermissionsOptions();

            var jwtSigningKeyProviderMock = new Mock <IJwtSigningKeyResolver>();
            var hostingEnvironmentMock    = new Mock <IHostingEnvironment>();

            var tokenValidationParametersFactory = new TokenValidationParametersFactory(Options.Create(authOptions),
                                                                                        jwtSigningKeyProviderMock.Object,
                                                                                        Options.Create(devPermissionsOptions),
                                                                                        hostingEnvironmentMock.Object);

            var tokenValidationParameters = tokenValidationParametersFactory.Create();

            Assert.False(tokenValidationParameters.ValidateIssuer);
            Assert.Equal(authOptions.JwtIssuer, tokenValidationParameters.ValidIssuer);

            Assert.False(tokenValidationParameters.ValidateAudience);
            Assert.Equal(authOptions.JwtAudience, tokenValidationParameters.ValidAudience);

            Assert.True(tokenValidationParameters.ValidateLifetime);

            Assert.True(tokenValidationParameters.RequireSignedTokens);
        }
コード例 #2
0
        public static Action <JwtBearerOptions> ConfigureJwtOptions(JwtConfig jwtConfig)
        {
            return(bearerOptions =>
            {
                JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

                bearerOptions.RequireHttpsMetadata = false;

                bearerOptions.SaveToken = true;

                bearerOptions.TokenValidationParameters = TokenValidationParametersFactory.Create(jwtConfig);
            });
        }
コード例 #3
0
        private bool IsJwtValid(string jwtTokenString, string clientId, string audience)
        {
            var trustedKeys = _keysExtractor.ExtractSecurityKeys(jwtTokenString);

            if (!trustedKeys.Any())
            {
                return(FromError("Trusted keys not found."));
            }

            var tokenValidationParameters = TokenValidationParametersFactory.Create(clientId, audience, trustedKeys);

            try
            {
                var handler = new JwtSecurityTokenHandler();
                handler.ValidateToken(jwtTokenString, tokenValidationParameters, out var token);

                var jwtToken = (JwtSecurityToken)token;

                if (IsHeaderAlgInvalid(jwtToken.Header.Alg))
                {
                    return(FromError("Header alg value must be RS256."));
                }

                if (IsSubInvalid(jwtToken))
                {
                    return(FromError("Both 'sub' and 'iss' in the client assertion token must have a value of client_id."));
                }

                if (string.IsNullOrEmpty(jwtToken.Payload.Jti))
                {
                    return(FromError("The 'jti' claim is missing from the client assertion."));
                }

                if (IsUnixTimestampGreaterThanUtcNow(jwtToken.Payload.Iat))
                {
                    return(FromError("The 'iat' claim cannot have higher value than UtcNow."));
                }

                if (IsExpired(jwtToken.Payload.Exp))
                {
                    return(FromError("The 'exp' claim states that token is expired."));
                }

                return(true);
            }
            catch (Exception e)
            {
                _logger.LogError(e, "JWT token validation error.");
                return(false);
            }
        }
        public void ValidateTokenLifetimeShouldBeTrue()
        {
            var authOptions           = new AuthOptions();
            var devPermissionsOptions = new DevPermissionsOptions
            {
                Environment = "Testing",
            };

            var jwtSigningKeyProviderMock = new Mock <IJwtSigningKeyResolver>();
            var hostingEnvironmentMock    = new Mock <IHostingEnvironment>();

            hostingEnvironmentMock.SetupGet(h => h.EnvironmentName)
            .Returns(devPermissionsOptions.Environment);

            var tokenValidationParametersFactory = new TokenValidationParametersFactory(Options.Create(authOptions),
                                                                                        jwtSigningKeyProviderMock.Object,
                                                                                        Options.Create(devPermissionsOptions),
                                                                                        hostingEnvironmentMock.Object);

            var tokenValidationParameters = tokenValidationParametersFactory.Create();

            Assert.True(tokenValidationParameters.ValidateLifetime);
        }
        public async Task <FinishSsoResult> FinishSsoAsync(HttpContext context)
        {
            if (!TryGetSamlResponse(context, out var response, out var binding))
            {
                throw new InvalidOperationException("Bad request.");
            }

            Logger.LogInformation("Finishing SAML2P authentication (SP flow).");
            Trace($"Received SAMLResponse using {binding} binding.", response);
            var partnerId = response.Issuer;
            var partner   = await Partners.GetIdentityProviderAsync(partnerId);

            if (partner == null)
            {
                throw new SecurityException($"Partner idp '{partnerId}' not found.");
            }

            if (!partner.Enabled)
            {
                throw new SecurityException($"Partner idp '{partnerId}' is disabled.");
            }

            var request = null as AuthnRequest;

            if (response.InResponseTo != null)
            {
                request = await Cache.FetchRequestAsync(response.InResponseTo);

                await Cache.RemoveAsync(response.InResponseTo);
            }

            if (request == null && !partner.CanInitiateSso)
            {
                throw new SecurityException($"Partner idp '{partnerId}' is is not allowed to initiate SSO.");
            }

            if (request != null)
            {
                Trace("Found cached SAMLRequest.", request);

                if (request.RelayState != response.RelayState)
                {
                    throw new SecurityException($"Mismatching relay state.");
                }
            }

            var ssoContext = new FinishSsoContext
            {
                PartnerId = partner.Id,
                Partner   = partner,
                Request   = request,
                Response  = response
            };

            await Events.InvokeAsync(Options, partner, e => e.OnFinishSso(context.RequestServices, ssoContext));

            if (response.Status.StatusCode.Value != Saml2pConstants.Statuses.Success)
            {
                return(FinishSsoResult.Fail(partner.Id, response.Status.StatusCode.Value, response.Status.StatusCode?.SubCode.Value));
            }
            var parameters      = _factory.Create(partner);
            var validateContext = new ValidateTokenContext
            {
                PartnerId = partner.Id,
                Partner   = partner,
                Request   = request,
                Response  = response,
                TokenValidationParameters = parameters,
                Handler = _handler
            };
            await Events.InvokeAsync(Options, partner, e => e.OnValidatingToken(context.RequestServices, validateContext));

            if (validateContext.Subject != null && validateContext.SecurityToken == null ||
                validateContext.Subject == null && validateContext.SecurityToken != null)
            {
                Logger.LogWarning($"When manually populating '{nameof(ValidateTokenContext.Subject)}' or '{nameof(ValidateTokenContext.SecurityToken)}' properties of '{nameof(ValidateTokenContext)}', then both must be populated. Otherwise they will be ignored. Clearing values...");
                validateContext.SecurityToken = null;
                validateContext.Subject       = null;
            }

            if (validateContext.Subject == null)
            {
                Logger.LogInformation("Validating incoming token.");
                var subject = validateContext.Handler.ValidateToken(validateContext.Response.XmlSecurityToken, validateContext.TokenValidationParameters, out var token);
                var saml2   = token as Saml2SecurityToken;
                var now     = _clock.UtcNow.DateTime;

                saml2.ValidateResponseToken(validateContext.Request.Id, now);

                validateContext.Subject       = subject;
                validateContext.SecurityToken = saml2;
            }

            await Events.InvokeAsync(Options, partner, e => e.OnValidatedToken(context.RequestServices, validateContext));

            context.User = validateContext.Subject;

            return(FinishSsoResult.Success(partner.Id, validateContext.SecurityToken, validateContext.Subject));
        }