providers/oauth2: Make AuthorizeError's state parameter requireed

This commit is contained in:
Jens Langhammer 2020-12-27 15:32:22 +01:00
parent e8debce9c8
commit e7c96eb70d
2 changed files with 19 additions and 15 deletions

View file

@ -1,5 +1,4 @@
"""OAuth errors"""
from typing import Optional
from urllib.parse import quote
from authentik.lib.sentry import SentryIgnoredException
@ -105,7 +104,7 @@ class AuthorizeError(OAuth2Error):
redirect_uri: str,
error: str,
grant_type: str,
state: Optional[str] = None,
state: str,
):
super().__init__()
self.error = error
@ -114,7 +113,7 @@ class AuthorizeError(OAuth2Error):
self.grant_type = grant_type
self.state = state
def create_uri(self, redirect_uri: str) -> str:
def create_uri(self) -> str:
"""Get a redirect URI with the error message"""
description = quote(str(self.description))
@ -123,7 +122,7 @@ class AuthorizeError(OAuth2Error):
hash_or_question = "#" if self.grant_type == GrantTypes.IMPLICIT else "?"
uri = "{0}{1}error={2}&error_description={3}".format(
redirect_uri, hash_or_question, self.error, description
self.redirect_uri, hash_or_question, self.error, description
)
# Add state if present.

View file

@ -177,11 +177,15 @@ class OAuthAuthorizationParams:
in [ResponseTypes.ID_TOKEN, ResponseTypes.ID_TOKEN_TOKEN]
):
LOGGER.warning("Missing 'openid' scope.")
raise AuthorizeError(self.redirect_uri, "invalid_scope", self.grant_type)
raise AuthorizeError(
self.redirect_uri, "invalid_scope", self.grant_type, self.state
)
# Nonce parameter validation.
if is_open_id and self.grant_type == GrantTypes.IMPLICIT and not self.nonce:
raise AuthorizeError(self.redirect_uri, "invalid_request", self.grant_type)
raise AuthorizeError(
self.redirect_uri, "invalid_request", self.grant_type, self.state
)
# Response type parameter validation.
if is_open_id:
@ -191,14 +195,14 @@ class OAuthAuthorizationParams:
actual_response_type = actual_response_type[:hash_index]
if self.response_type != actual_response_type:
raise AuthorizeError(
self.redirect_uri, "invalid_request", self.grant_type
self.redirect_uri, "invalid_request", self.grant_type, self.state
)
# PKCE validation of the transformation method.
if self.code_challenge:
if not (self.code_challenge_method in ["plain", "S256"]):
raise AuthorizeError(
self.redirect_uri, "invalid_request", self.grant_type
self.redirect_uri, "invalid_request", self.grant_type, self.state
)
def create_code(self, request: HttpRequest) -> AuthorizationCode:
@ -244,6 +248,7 @@ class OAuthFulfillmentStage(StageView):
self.params.redirect_uri,
"consent_required",
self.params.grant_type,
self.params.state,
)
Event.new(
EventAction.AUTHORIZE_APPLICATION,
@ -257,8 +262,7 @@ class OAuthFulfillmentStage(StageView):
return bad_request_message(request, error.description, title=error.error)
except AuthorizeError as error:
self.executor.stage_invalid()
uri = error.create_uri(self.params.redirect_uri)
return redirect(uri)
return redirect(error.create_uri())
def create_response_uri(self) -> str:
"""Create a final Response URI the user is redirected to."""
@ -361,7 +365,7 @@ class AuthorizationFlowInitView(PolicyAccessView):
try:
self.params = OAuthAuthorizationParams.from_request(self.request)
except AuthorizeError as error:
raise RequestValidationError(redirect(error.create_uri(error.redirect_uri)))
raise RequestValidationError(redirect(error.create_uri()))
except OAuth2Error as error:
raise RequestValidationError(
bad_request_message(self.request, error.description, title=error.error)
@ -371,11 +375,12 @@ class AuthorizationFlowInitView(PolicyAccessView):
if PROMPT_NONE in self.params.prompt and not self.request.user.is_authenticated:
# When "prompt" is set to "none" but the user is not logged in, show an error message
error = AuthorizeError(
self.params.redirect_uri, "login_required", self.params.grant_type
)
raise RequestValidationError(
redirect(error.create_uri(self.params.redirect_uri))
self.params.redirect_uri,
"login_required",
self.params.grant_type,
self.params.state,
)
raise RequestValidationError(redirect(error.create_uri()))
def resolve_provider_application(self):
client_id = self.request.GET.get("client_id")