public async Task RemovedKeyIsNotFound()
        {
            await _setup;
            await _authorizationStore.RemoveAsync(RemoveKey);

            Assert.Null(await _authorizationStore.GetAsync(RemoveKey));
        }
Example #2
0
        private async Task <TokenRequestValidationResult> ValidateAuthorizationCodeRequestAsync(NameValueCollection parameters)
        {
            Logger.Info("Start validation of authorization code token request");

            /////////////////////////////////////////////
            // check if client is authorized for grant type
            /////////////////////////////////////////////
            if (Constants.AllowedFlowsForAuthorizationCodeGrantType.Contains(_validatedRequest.Client.Flow) == false)
            {
                LogError("Client not authorized for code flow");
                return(Invalid(Constants.TokenErrors.UnauthorizedClient));
            }

            /////////////////////////////////////////////
            // validate authorization code
            /////////////////////////////////////////////
            var code = parameters.Get(Constants.TokenRequest.Code);

            if (code.IsMissing())
            {
                var error = "Authorization code is missing.";
                LogError(error);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(null, error);

                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            if (code.Length > _options.InputLengthRestrictions.AuthorizationCode)
            {
                var error = "Authorization code is too long.";
                LogError(error);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(null, error);

                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            _validatedRequest.AuthorizationCodeHandle = code;

            var authZcode = await _authorizationCodes.GetAsync(code);

            if (authZcode == null)
            {
                LogError("Invalid authorization code: " + code);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, "Invalid handle");

                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            await _authorizationCodes.RemoveAsync(code);

            /////////////////////////////////////////////
            // populate session id
            /////////////////////////////////////////////
            if (authZcode.SessionId.IsPresent())
            {
                _validatedRequest.SessionId = authZcode.SessionId;
            }

            /////////////////////////////////////////////
            // validate client binding
            /////////////////////////////////////////////
            if (authZcode.Client.ClientId != _validatedRequest.Client.ClientId)
            {
                LogError(string.Format("Client {0} is trying to use a code from client {1}", _validatedRequest.Client.ClientId, authZcode.Client.ClientId));
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, "Invalid client binding");

                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            /////////////////////////////////////////////
            // validate PKCE parameters
            /////////////////////////////////////////////
            var codeVerifier = parameters.Get(Constants.TokenRequest.CodeVerifier);

            if (authZcode.Client.Flow == Flows.AuthorizationCodeWithProofKey ||
                authZcode.Client.Flow == Flows.HybridWithProofKey)
            {
                var proofKeyResult = ValidateAuthorizationCodeWithProofKeyParameters(codeVerifier, authZcode);
                if (proofKeyResult.IsError)
                {
                    return(proofKeyResult);
                }

                _validatedRequest.CodeVerifier = codeVerifier;
            }
            else
            {
                if (codeVerifier.IsPresent())
                {
                    LogError("Unexpected code_verifier with Flow " + authZcode.Client.Flow.ToString());
                    return(Invalid(Constants.TokenErrors.InvalidGrant));
                }
            }

            /////////////////////////////////////////////
            // validate code expiration
            /////////////////////////////////////////////
            if (authZcode.CreationTime.HasExceeded(_validatedRequest.Client.AuthorizationCodeLifetime))
            {
                var error = "Authorization code is expired";
                LogError(error);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, error);

                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            _validatedRequest.AuthorizationCode = authZcode;

            /////////////////////////////////////////////
            // validate redirect_uri
            /////////////////////////////////////////////
            var redirectUri = parameters.Get(Constants.TokenRequest.RedirectUri);

            if (redirectUri.IsMissing())
            {
                var error = "Redirect URI is missing.";
                LogError(error);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, error);

                return(Invalid(Constants.TokenErrors.UnauthorizedClient));
            }

            if (redirectUri.Equals(_validatedRequest.AuthorizationCode.RedirectUri, StringComparison.Ordinal) == false)
            {
                var error = "Invalid redirect_uri: " + redirectUri;
                LogError(error);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, error);

                return(Invalid(Constants.TokenErrors.UnauthorizedClient));
            }

            /////////////////////////////////////////////
            // validate scopes are present
            /////////////////////////////////////////////
            if (_validatedRequest.AuthorizationCode.RequestedScopes == null ||
                !_validatedRequest.AuthorizationCode.RequestedScopes.Any())
            {
                var error = "Authorization code has no associated scopes.";
                LogError(error);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, error);

                return(Invalid(Constants.TokenErrors.InvalidRequest));
            }


            /////////////////////////////////////////////
            // make sure user is enabled
            /////////////////////////////////////////////
            var isActiveCtx = new IsActiveContext(_validatedRequest.AuthorizationCode.Subject, _validatedRequest.Client);
            await _users.IsActiveAsync(isActiveCtx);

            if (isActiveCtx.IsActive == false)
            {
                var error = "User has been disabled: " + _validatedRequest.AuthorizationCode.Subject;
                LogError(error);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, error);

                return(Invalid(Constants.TokenErrors.InvalidRequest));
            }

            /////////////////////////////////////////////
            // validate token type and PoP parameters if pop token is requested
            /////////////////////////////////////////////
            var tokenType = parameters.Get("token_type");

            if (tokenType != null && tokenType == Constants.ResponseTokenTypes.PoP)
            {
                var result = ValidatePopParameters(parameters);
                if (result.IsError)
                {
                    var error = "PoP parameter validation failed: " + result.ErrorDescription;
                    LogError(error);
                    await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, error);

                    return(Invalid(result.Error, result.ErrorDescription));
                }
                else
                {
                    _validatedRequest.RequestedTokenType = RequestedTokenTypes.PoP;
                }
            }

            Logger.Info("Validation of authorization code token request success");
            await RaiseSuccessfulAuthorizationCodeRedeemedEventAsync();

            return(Valid());
        }
Example #3
0
        private async Task <ValidationResult> ValidateAuthorizationCodeRequestAsync(NameValueCollection parameters)
        {
            Logger.Info("Start validation of authorization code token request");

            /////////////////////////////////////////////
            // check if client is authorized for grant type
            /////////////////////////////////////////////
            if (_validatedRequest.Client.Flow != Flows.AuthorizationCode &&
                _validatedRequest.Client.Flow != Flows.Hybrid)
            {
                LogError("Client not authorized for code flow");
                return(Invalid(Constants.TokenErrors.UnauthorizedClient));
            }

            /////////////////////////////////////////////
            // validate authorization code
            /////////////////////////////////////////////
            var code = parameters.Get(Constants.TokenRequest.Code);

            if (code.IsMissing())
            {
                var error = "Authorization code is missing.";
                LogError(error);
                RaiseFailedAuthorizationCodeRedeemedEvent(null, error);

                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            _validatedRequest.AuthorizationCodeHandle = code;

            var authZcode = await _authorizationCodes.GetAsync(code);

            if (authZcode == null)
            {
                LogError("Invalid authorization code: " + code);
                RaiseFailedAuthorizationCodeRedeemedEvent(code, "Invalid handle");

                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            await _authorizationCodes.RemoveAsync(code);

            /////////////////////////////////////////////
            // validate client binding
            /////////////////////////////////////////////
            if (authZcode.Client.ClientId != _validatedRequest.Client.ClientId)
            {
                LogError(string.Format("Client {0} is trying to use a code from client {1}", _validatedRequest.Client.ClientId, authZcode.Client.ClientId));
                RaiseFailedAuthorizationCodeRedeemedEvent(code, "Invalid client binding");

                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            /////////////////////////////////////////////
            // validate code expiration
            /////////////////////////////////////////////
            if (authZcode.CreationTime.HasExceeded(_validatedRequest.Client.AuthorizationCodeLifetime))
            {
                var error = "Authorization code is expired";
                LogError(error);
                RaiseFailedAuthorizationCodeRedeemedEvent(code, error);

                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            _validatedRequest.AuthorizationCode = authZcode;

            /////////////////////////////////////////////
            // validate redirect_uri
            /////////////////////////////////////////////
            var redirectUri = parameters.Get(Constants.TokenRequest.RedirectUri);

            if (redirectUri.IsMissing())
            {
                var error = "Redirect URI is missing.";
                LogError(error);
                RaiseFailedAuthorizationCodeRedeemedEvent(code, error);

                return(Invalid(Constants.TokenErrors.UnauthorizedClient));
            }

            if (redirectUri.Equals(_validatedRequest.AuthorizationCode.RedirectUri, StringComparison.Ordinal) == false)
            {
                var error = "Invalid redirect_uri: " + redirectUri;
                LogError(error);
                RaiseFailedAuthorizationCodeRedeemedEvent(code, error);

                return(Invalid(Constants.TokenErrors.UnauthorizedClient));
            }

            /////////////////////////////////////////////
            // validate scopes are present
            /////////////////////////////////////////////
            if (_validatedRequest.AuthorizationCode.RequestedScopes == null ||
                !_validatedRequest.AuthorizationCode.RequestedScopes.Any())
            {
                var error = "Authorization code has no associated scopes.";
                LogError(error);
                RaiseFailedAuthorizationCodeRedeemedEvent(code, error);

                return(Invalid(Constants.TokenErrors.InvalidRequest));
            }


            /////////////////////////////////////////////
            // make sure user is enabled
            /////////////////////////////////////////////
            if (await _users.IsActiveAsync(_validatedRequest.AuthorizationCode.Subject) == false)
            {
                var error = "User has been disabled: " + _validatedRequest.AuthorizationCode.Subject;
                LogError(error);
                RaiseFailedAuthorizationCodeRedeemedEvent(code, error);

                return(Invalid(Constants.TokenErrors.InvalidRequest));
            }

            Logger.Info("Validation of authorization code token request success");
            RaiseSuccessfulAuthorizationCodeRedeemedEvent();

            return(Valid());
        }
        private async Task <ValidationResult> ValidateAuthorizationCodeRequestAsync(NameValueCollection parameters)
        {
            /////////////////////////////////////////////
            // check if client is authorized for grant type
            /////////////////////////////////////////////
            if (_validatedRequest.Client.Flow != Flows.Code)
            {
                Logger.Error("Client not authorized for code flow");
                return(Invalid(Constants.TokenErrors.UnauthorizedClient));
            }

            /////////////////////////////////////////////
            // validate authorization code
            /////////////////////////////////////////////
            var code = parameters.Get(Constants.TokenRequest.Code);

            if (code.IsMissing())
            {
                Logger.Error("Authorization code is missing.");
                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            var authZcode = await _authorizationCodes.GetAsync(code);

            if (authZcode == null)
            {
                Logger.ErrorFormat("Invalid authorization code: ", code);
                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }
            else
            {
                Logger.InfoFormat("Authorization code found: {0}", code);
            }

            await _authorizationCodes.RemoveAsync(code);

            /////////////////////////////////////////////
            // validate client binding
            /////////////////////////////////////////////
            if (authZcode.Client.ClientId != _validatedRequest.Client.ClientId)
            {
                Logger.ErrorFormat("Client {0} is trying to use a code from client {1}", _validatedRequest.Client.ClientId, authZcode.Client.ClientId);
                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            /////////////////////////////////////////////
            // validate code expiration
            /////////////////////////////////////////////
            if (authZcode.CreationTime.HasExpired(_validatedRequest.Client.AuthorizationCodeLifetime))
            {
                Logger.Error("Authorization code is expired");
                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            _validatedRequest.AuthorizationCode = authZcode;

            /////////////////////////////////////////////
            // validate redirect_uri
            /////////////////////////////////////////////
            var redirectUri = parameters.Get(Constants.TokenRequest.RedirectUri);

            if (redirectUri.IsMissing())
            {
                Logger.Error("Redirect URI is missing.");
                return(Invalid(Constants.TokenErrors.UnauthorizedClient));
            }

            if (redirectUri != _validatedRequest.AuthorizationCode.RedirectUri.AbsoluteUri)
            {
                Logger.ErrorFormat("Invalid redirect_uri: {0}", redirectUri);
                return(Invalid(Constants.TokenErrors.UnauthorizedClient));
            }

            Logger.Info("Successful validation of authorization_code request");
            return(Valid());
        }
        private async Task <TokenRequestValidationResult> ValidateAuthorizationCodeRequestAsync(NameValueCollection parameters)
        {
            _logger.LogDebug("Start validation of authorization code token request");

            /////////////////////////////////////////////
            // check if client is authorized for grant type
            /////////////////////////////////////////////
            if (!_validatedRequest.Client.AllowedGrantTypes.ToList().Contains(GrantType.Code) &&
                !_validatedRequest.Client.AllowedGrantTypes.ToList().Contains(GrantType.Hybrid))
            {
                LogError("Client not authorized for code flow");
                return(Invalid(OidcConstants.TokenErrors.UnauthorizedClient));
            }

            /////////////////////////////////////////////
            // validate authorization code
            /////////////////////////////////////////////
            var code = parameters.Get(OidcConstants.TokenRequest.Code);

            if (code.IsMissing())
            {
                var error = "Authorization code is missing.";
                LogError(error);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(null, error);

                return(Invalid(OidcConstants.TokenErrors.InvalidGrant));
            }

            if (code.Length > _options.InputLengthRestrictions.AuthorizationCode)
            {
                var error = "Authorization code is too long.";
                LogError(error);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(null, error);

                return(Invalid(OidcConstants.TokenErrors.InvalidGrant));
            }

            _validatedRequest.AuthorizationCodeHandle = code;

            var authZcode = await _authorizationCodes.GetAsync(code);

            if (authZcode == null)
            {
                LogError("Authorization code cannot be found in the store: " + code);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, "Invalid handle");

                return(Invalid(OidcConstants.TokenErrors.InvalidGrant));
            }

            await _authorizationCodes.RemoveAsync(code);

            /////////////////////////////////////////////
            // populate session id
            /////////////////////////////////////////////
            if (authZcode.SessionId.IsPresent())
            {
                _validatedRequest.SessionId = authZcode.SessionId;
            }

            /////////////////////////////////////////////
            // validate client binding
            /////////////////////////////////////////////
            if (authZcode.Client.ClientId != _validatedRequest.Client.ClientId)
            {
                LogError(string.Format("Client {0} is trying to use a code from client {1}", _validatedRequest.Client.ClientId, authZcode.Client.ClientId));
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, "Invalid client binding");

                return(Invalid(OidcConstants.TokenErrors.InvalidGrant));
            }

            /////////////////////////////////////////////
            // validate code expiration
            /////////////////////////////////////////////
            if (authZcode.CreationTime.HasExceeded(_validatedRequest.Client.AuthorizationCodeLifetime))
            {
                var error = "Authorization code is expired";
                LogError(error);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, error);

                return(Invalid(OidcConstants.TokenErrors.InvalidGrant));
            }

            _validatedRequest.AuthorizationCode = authZcode;

            /////////////////////////////////////////////
            // validate redirect_uri
            /////////////////////////////////////////////
            var redirectUri = parameters.Get(OidcConstants.TokenRequest.RedirectUri);

            if (redirectUri.IsMissing())
            {
                var error = "Redirect URI is missing.";
                LogError(error);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, error);

                return(Invalid(OidcConstants.TokenErrors.UnauthorizedClient));
            }

            if (redirectUri.Equals(_validatedRequest.AuthorizationCode.RedirectUri, StringComparison.Ordinal) == false)
            {
                var error = "Invalid redirect_uri: " + redirectUri;
                LogError(error);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, error);

                return(Invalid(OidcConstants.TokenErrors.UnauthorizedClient));
            }

            /////////////////////////////////////////////
            // validate scopes are present
            /////////////////////////////////////////////
            if (_validatedRequest.AuthorizationCode.RequestedScopes == null ||
                !_validatedRequest.AuthorizationCode.RequestedScopes.Any())
            {
                var error = "Authorization code has no associated scopes.";
                LogError(error);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, error);

                return(Invalid(OidcConstants.TokenErrors.InvalidRequest));
            }


            /////////////////////////////////////////////
            // make sure user is enabled
            /////////////////////////////////////////////
            var isActiveCtx = new IsActiveContext(_validatedRequest.AuthorizationCode.Subject, _validatedRequest.Client);
            await _profile.IsActiveAsync(isActiveCtx);

            if (isActiveCtx.IsActive == false)
            {
                var error = "User has been disabled: " + _validatedRequest.AuthorizationCode.Subject;
                LogError(error);
                await RaiseFailedAuthorizationCodeRedeemedEventAsync(code, error);

                return(Invalid(OidcConstants.TokenErrors.InvalidRequest));
            }

            _logger.LogInformation("Validation of authorization code token request success");
            await RaiseSuccessfulAuthorizationCodeRedeemedEventAsync();

            return(Valid());
        }
        private async Task <ValidationResult> ValidateAuthorizationCodeRequestAsync(NameValueCollection parameters)
        {
            /////////////////////////////////////////////
            // check if client is authorized for grant type
            /////////////////////////////////////////////
            if (_validatedRequest.Client.Flow != Flows.AuthorizationCode &&
                _validatedRequest.Client.Flow != Flows.Hybrid)
            {
                Logger.Error("Client not authorized for code flow");
                return(Invalid(Constants.TokenErrors.UnauthorizedClient));
            }

            /////////////////////////////////////////////
            // validate authorization code
            /////////////////////////////////////////////
            var code = parameters.Get(Constants.TokenRequest.Code);

            if (code.IsMissing())
            {
                Logger.Error("Authorization code is missing.");
                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            var authZcode = await _authorizationCodes.GetAsync(code);

            if (authZcode == null)
            {
                Logger.ErrorFormat("Invalid authorization code: {0}", code);
                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            Logger.InfoFormat("Authorization code found: {0}", code);
            await _authorizationCodes.RemoveAsync(code);

            /////////////////////////////////////////////
            // validate client binding
            /////////////////////////////////////////////
            if (authZcode.Client.ClientId != _validatedRequest.Client.ClientId)
            {
                Logger.ErrorFormat("Client {0} is trying to use a code from client {1}", _validatedRequest.Client.ClientId, authZcode.Client.ClientId);
                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            /////////////////////////////////////////////
            // validate code expiration
            /////////////////////////////////////////////
            if (authZcode.CreationTime.HasExceeded(_validatedRequest.Client.AuthorizationCodeLifetime))
            {
                Logger.Error("Authorization code is expired");
                return(Invalid(Constants.TokenErrors.InvalidGrant));
            }

            _validatedRequest.AuthorizationCode = authZcode;

            /////////////////////////////////////////////
            // validate redirect_uri
            /////////////////////////////////////////////
            var redirectUri = parameters.Get(Constants.TokenRequest.RedirectUri);

            if (redirectUri.IsMissing())
            {
                Logger.Error("Redirect URI is missing.");
                return(Invalid(Constants.TokenErrors.UnauthorizedClient));
            }

            if (redirectUri != _validatedRequest.AuthorizationCode.RedirectUri.AbsoluteUri)
            {
                Logger.ErrorFormat("Invalid redirect_uri: {0}", redirectUri);
                return(Invalid(Constants.TokenErrors.UnauthorizedClient));
            }

            /////////////////////////////////////////////
            // validate scopes are present
            /////////////////////////////////////////////
            if (_validatedRequest.AuthorizationCode.RequestedScopes == null ||
                !_validatedRequest.AuthorizationCode.RequestedScopes.Any())
            {
                Logger.Error("Authorization code has no associated scopes.");
                return(Invalid(Constants.TokenErrors.InvalidRequest));
            }


            /////////////////////////////////////////////
            // make sure user is enabled
            /////////////////////////////////////////////
            if (await _users.IsActiveAsync(_validatedRequest.AuthorizationCode.Subject) == false)
            {
                Logger.Error("User has been disabled: " + _validatedRequest.AuthorizationCode.Subject);
                return(Invalid(Constants.TokenErrors.InvalidRequest));
            }

            Logger.Info("Successful validation of authorization_code request");
            return(Valid());
        }