예제 #1
0
        public virtual async Task <TokenValidationResult> ValidateAccessTokenAsync(string token, string expectedScope = null)
        {
            Logger.Info("Start access token validation");

            _log.ExpectedScope    = expectedScope;
            _log.ValidateLifetime = true;

            TokenValidationResult result;

            if (token.Contains("."))
            {
                _log.AccessTokenType = AccessTokenType.Jwt.ToString();
                result = await ValidateJwtAsync(
                    token,
                    string.Format(Constants.AccessTokenAudience, _options.IssuerUri.EnsureTrailingSlash()),
                    new X509SecurityKey(_options.SigningCertificate));
            }
            else
            {
                _log.AccessTokenType = AccessTokenType.Reference.ToString();
                result = await ValidateReferenceAccessTokenAsync(token);
            }

            if (_options.LoggingOptions.IncludeSensitiveDataInLogs)
            {
                _log.Claims = result.Claims.ToClaimsDictionary();
            }

            if (result.IsError)
            {
                return(result);
            }

            if (expectedScope.IsPresent())
            {
                var scope = result.Claims.FirstOrDefault(c => c.Type == Constants.ClaimTypes.Scope && c.Value == expectedScope);
                if (scope == null)
                {
                    LogError(string.Format("Checking for expected scope {0} failed", expectedScope));
                    return(Invalid(Constants.ProtectedResourceErrors.InsufficientScope));
                }
            }

            var customResult = await _customValidator.ValidateAccessTokenAsync(result);

            if (customResult.IsError)
            {
                LogError("Custom validator failed: " + customResult.Error ?? "unknown");
                return(customResult);
            }

            // add claims again after custom validation
            if (_options.LoggingOptions.IncludeSensitiveDataInLogs)
            {
                _log.Claims = customResult.Claims.ToClaimsDictionary();
            }

            LogSuccess();
            return(customResult);
        }
예제 #2
0
        public virtual async Task <TokenValidationResult> ValidateAccessTokenAsync(string token, string expectedScope = null)
        {
            Logger.Info("Start access token validation");
            Logger.Debug("Token: " + token);

            TokenValidationResult result;

            if (token.Contains("."))
            {
                Logger.InfoFormat("Validating a JWT access token");
                result = await ValidateJwtAsync(
                    token,
                    string.Format(Constants.AccessTokenAudience, _options.IssuerUri.EnsureTrailingSlash()),
                    new X509SecurityKey(_options.SigningCertificate));
            }
            else
            {
                Logger.InfoFormat("Validating a reference access token");
                result = await ValidateReferenceAccessTokenAsync(token);
            }

            if (result.IsError)
            {
                return(result);
            }

            if (expectedScope.IsPresent())
            {
                var scope = result.Claims.FirstOrDefault(c => c.Type == Constants.ClaimTypes.Scope && c.Value == expectedScope);
                if (scope == null)
                {
                    Logger.InfoFormat("Checking for expected scope {0} failed", expectedScope);
                    return(Invalid(Constants.ProtectedResourceErrors.InsufficientScope));
                }

                Logger.InfoFormat("Checking for expected scope {0} succeeded", expectedScope);
            }

            Logger.Debug("Calling custom token validator");
            var customResult = await _customValidator.ValidateAccessTokenAsync(result);

            if (customResult.IsError)
            {
                Logger.Error("Custom validator failed: " + customResult.Error ?? "unknown");
            }

            return(customResult);
        }
예제 #3
0
        public virtual async Task <TokenValidationResult> ValidateAccessTokenAsync(string token, string expectedScope = null)
        {
            Logger.Info("Start access token validation");
            Logger.Debug("Token: " + token);

            var result = new TokenValidationResult();

            if (token.Contains("."))
            {
                Logger.InfoFormat("Validating a JWT access token");
                result = await ValidateJwtAccessTokenAsync(token);
            }
            else
            {
                Logger.InfoFormat("Validating a reference access token");
                result = await ValidateReferenceAccessTokenAsync(token);
            }

            if (expectedScope.IsPresent())
            {
                var scope = result.Claims.FirstOrDefault(c => c.Type == Constants.ClaimTypes.Scope && c.Value == expectedScope);
                if (scope == null)
                {
                    Logger.InfoFormat("Checking for expected scope {0} failed", expectedScope);
                    return(Invalid(Constants.ProtectedResourceErrors.InsufficientScope));
                }

                Logger.InfoFormat("Checking for expected scope {0} succeeded", expectedScope);
            }

            Logger.Debug("Calling custom token validator");
            var customResult = await _customValidator.ValidateAccessTokenAsync(result, _settings, _clients, _users);

            if (customResult.IsError)
            {
                Logger.Error("Custom validator failed: " + customResult.Error ?? "unknown");
            }

            return(customResult);
        }
예제 #4
0
        public virtual async Task <TokenValidationResult> ValidateAccessTokenAsync(string token, string expectedScope = null)
        {
            _logger.LogTrace("Start access token validation");

            _log.ExpectedScope    = expectedScope;
            _log.ValidateLifetime = true;

            TokenValidationResult result;

            if (token.Contains("."))
            {
                if (token.Length > _options.InputLengthRestrictions.Jwt)
                {
                    _logger.LogError("JWT too long");

                    return(new TokenValidationResult
                    {
                        IsError = true,
                        Error = OidcConstants.ProtectedResourceErrors.InvalidToken,
                        ErrorDescription = "Token too long"
                    });
                }

                _log.AccessTokenType = AccessTokenType.Jwt.ToString();
                result = await ValidateJwtAsync(
                    token,
                    string.Format(Constants.AccessTokenAudience, _context.HttpContext.GetIssuerUri().EnsureTrailingSlash()),
                    await _keys.GetValidationKeysAsync());
            }
            else
            {
                if (token.Length > _options.InputLengthRestrictions.TokenHandle)
                {
                    _logger.LogError("token handle too long");

                    return(new TokenValidationResult
                    {
                        IsError = true,
                        Error = OidcConstants.ProtectedResourceErrors.InvalidToken,
                        ErrorDescription = "Token too long"
                    });
                }

                _log.AccessTokenType = AccessTokenType.Reference.ToString();
                result = await ValidateReferenceAccessTokenAsync(token);
            }

            _log.Claims = result.Claims.ToClaimsDictionary();

            if (result.IsError)
            {
                return(result);
            }

            if (expectedScope.IsPresent())
            {
                var scope = result.Claims.FirstOrDefault(c => c.Type == JwtClaimTypes.Scope && c.Value == expectedScope);
                if (scope == null)
                {
                    LogError(string.Format("Checking for expected scope {0} failed", expectedScope));
                    return(Invalid(OidcConstants.ProtectedResourceErrors.InsufficientScope));
                }
            }

            var customResult = await _customValidator.ValidateAccessTokenAsync(result);

            if (customResult.IsError)
            {
                LogError("Custom validator failed: " + (customResult.Error ?? "unknown"));
                return(customResult);
            }

            // add claims again after custom validation
            _log.Claims = customResult.Claims.ToClaimsDictionary();

            LogSuccess();
            return(customResult);
        }
예제 #5
0
        public async Task <TokenValidationResult> ValidateAccessTokenAsync(string token, string expectedScope = null)
        {
            _logger.LogTrace("Start access token validation");

            _log.ExpectedScope    = expectedScope;
            _log.ValidateLifetime = true;

            TokenValidationResult result;

            if (token.Contains("."))
            {
                if (token.Length > _options.InputLengthRestrictions.Jwt)
                {
                    _logger.LogError("JWT too long");

                    return(new TokenValidationResult
                    {
                        IsError = true,
                        Error = OidcConstants.ProtectedResourceErrors.InvalidToken,
                        ErrorDescription = "Token too long"
                    });
                }

                _log.AccessTokenType = AccessTokenType.Jwt.ToString();
                result = await ValidateJwtAsync(
                    token,
                    string.Format(Constants.AccessTokenAudience, _context.HttpContext.GetIdentityServerIssuerUri().EnsureTrailingSlash()),
                    await _keys.GetValidationKeysAsync());
            }
            else
            {
                if (token.Length > _options.InputLengthRestrictions.TokenHandle)
                {
                    _logger.LogError("token handle too long");

                    return(new TokenValidationResult
                    {
                        IsError = true,
                        Error = OidcConstants.ProtectedResourceErrors.InvalidToken,
                        ErrorDescription = "Token too long"
                    });
                }

                _log.AccessTokenType = AccessTokenType.Reference.ToString();
                result = await ValidateReferenceAccessTokenAsync(token);
            }

            _log.Claims = result.Claims.ToClaimsDictionary();

            if (result.IsError)
            {
                return(result);
            }

            // make sure client is still active (if client_id claim is present)
            var clientClaim = result.Claims.FirstOrDefault(c => c.Type == JwtClaimTypes.ClientId);

            if (clientClaim != null)
            {
                var client = await _clients.FindEnabledClientByIdAsync(clientClaim.Value);

                if (client == null)
                {
                    _logger.LogError("Client deleted or disabled: {clientId}", clientClaim.Value);

                    result.IsError = true;
                    result.Error   = OidcConstants.ProtectedResourceErrors.InvalidToken;
                    result.Claims  = null;

                    return(result);
                }
            }

            // make sure user is still active (if sub claim is present)
            var subClaim = result.Claims.FirstOrDefault(c => c.Type == JwtClaimTypes.Subject);

            if (subClaim != null)
            {
                var principal = Principal.Create("tokenvalidator", result.Claims.ToArray());

                if (result.ReferenceTokenId.IsPresent())
                {
                    principal.Identities.First().AddClaim(new Claim(JwtClaimTypes.ReferenceTokenId, result.ReferenceTokenId));
                }

                var isActiveCtx = new IsActiveContext(principal, result.Client, IdentityServerConstants.ProfileIsActiveCallers.AccessTokenValidation);
                await _profile.IsActiveAsync(isActiveCtx);

                if (isActiveCtx.IsActive == false)
                {
                    _logger.LogError("User marked as not active: {subject}", subClaim.Value);

                    result.IsError = true;
                    result.Error   = OidcConstants.ProtectedResourceErrors.InvalidToken;
                    result.Claims  = null;

                    return(result);
                }
            }

            // check expected scope(s)
            if (expectedScope.IsPresent())
            {
                var scope = result.Claims.FirstOrDefault(c => c.Type == JwtClaimTypes.Scope && c.Value == expectedScope);
                if (scope == null)
                {
                    LogError(string.Format("Checking for expected scope {0} failed", expectedScope));
                    return(Invalid(OidcConstants.ProtectedResourceErrors.InsufficientScope));
                }
            }

            _logger.LogDebug("Calling into custom token validator: {type}", _customValidator.GetType().FullName);
            var customResult = await _customValidator.ValidateAccessTokenAsync(result);

            if (customResult.IsError)
            {
                LogError("Custom validator failed: " + (customResult.Error ?? "unknown"));
                return(customResult);
            }

            // add claims again after custom validation
            _log.Claims = customResult.Claims.ToClaimsDictionary();

            LogSuccess();
            return(customResult);
        }