diff --git a/konova/sub_settings/sso_settings.py b/konova/sub_settings/sso_settings.py index 01592cc..d1b9ee8 100644 --- a/konova/sub_settings/sso_settings.py +++ b/konova/sub_settings/sso_settings.py @@ -19,4 +19,6 @@ OAUTH_CODE_VERIFIER = ''.join( random.choice( string.ascii_uppercase + string.digits ) for _ in range(random.randint(43, 128)) -) \ No newline at end of file +) +OAUTH_CLIENT_ID = "CHANGE_ME" +OAUTH_CLIENT_SECRET = "CHANGE_ME" \ No newline at end of file diff --git a/konova/views/oauth.py b/konova/views/oauth.py index fc2735f..43e888f 100644 --- a/konova/views/oauth.py +++ b/konova/views/oauth.py @@ -17,58 +17,22 @@ from django.shortcuts import redirect from django.urls import reverse from django.views import View -from konova.sub_settings.sso_settings import SSO_SERVER_BASE, OAUTH_CODE_VERIFIER +from konova.sub_settings.sso_settings import SSO_SERVER_BASE, OAUTH_CODE_VERIFIER, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET from user.models import User -OAUTH_CLIENT_ID = "CHANGE_ME" -OAUTH_CLIENT_SECRET = "CHANGE_ME" - -class OAuthCallbackView(View): - """ - Callback view for a OAuth2.0 authentication token. - Authentication tokens need to be exchanged for the access token. +class OAuthLoginView(View): """ + Starts OAuth Login procedure + -> AnonymousUser is redirected to SSO component using specific parameters + -> After successful login (in SSO component), user will be redirected to a specific callback url (OAuthCallbackView) + -> Callback view uses retrieved authorization token to get a proper access token from SSO component + -> SSO component answers with access token + -> OAuthCallbackView uses token in Authorization header to access user data of logged-in user in SSO component + -> OAuthCallbackView creates/updates user + -> OAuthCallbackView logs in user and redirects to default home view - def get(self, request: HttpRequest, *args, **kwargs): - authentication_code = request.GET.get("code") - oauth_acces_token_url = f"{SSO_SERVER_BASE}o/token/" - - next_callback_url = request.build_absolute_uri( - reverse( - "oauth-callback" - ) - ) - - params = { - "grant_type": "authorization_code", - "code": authentication_code, - "redirect_uri": next_callback_url, - "code_verifier": OAUTH_CODE_VERIFIER, - "client_id": OAUTH_CLIENT_ID, - "client_secret": OAUTH_CLIENT_SECRET - } - access_code_response = requests.post( - oauth_acces_token_url, - data=params - ) - - access_code_response_body = access_code_response.content.decode("utf-8") - status_code_invalid = access_code_response.status_code != 200 - if status_code_invalid: - raise RuntimeError(f"OAuth access token could not be fetched: {access_code_response.text}") - - access_code_response_body = json.loads(access_code_response_body) - access_token = access_code_response_body.get("access_token") - if not access_token: - raise RuntimeError(f"Access token response contained no token: {access_code_response_body}") - - user = User.oauth_get_user(access_token) - login(request, user) - return redirect("home") - - -class OAuthLoginView(View): + """ def __create_code_challenge(self): """ @@ -86,7 +50,8 @@ class OAuthLoginView(View): return code_verifier, code_challenge def get(self, request: HttpRequest, *args, **kwargs): - """ Redirects user to OAuth SSO webservice + """ + Redirects user to OAuth SSO webservice for credential based login there Args: request (): @@ -98,7 +63,6 @@ class OAuthLoginView(View): """ oauth_authentication_code_url = f"{SSO_SERVER_BASE}o/authorize/" code_verifier, code_challenge = self.__create_code_challenge() - print(code_verifier) urlencode_params = urlencode( { @@ -115,3 +79,52 @@ class OAuthLoginView(View): ) url = f"{oauth_authentication_code_url}?{urlencode_params}" return redirect(url) + + +class OAuthCallbackView(View): + """ + Callback view for OAuth2.0 authentication token. + Authentication tokens will be exchanged for access token. + Access Token will be used for fetching user data from SSO component. + User data will be used for creating/updating user data inside this app. + User will be logged-in and redirected to default home view. + + """ + + def get(self, request: HttpRequest, *args, **kwargs): + authentication_code = request.GET.get("code") + oauth_acces_token_url = f"{SSO_SERVER_BASE}o/token/" + + next_callback_url = request.build_absolute_uri( + reverse( + "oauth-callback" + ) + ) + + params = { + "grant_type": "authorization_code", + "code": authentication_code, + "redirect_uri": next_callback_url, + "code_verifier": OAUTH_CODE_VERIFIER, + "client_id": OAUTH_CLIENT_ID, + "client_secret": OAUTH_CLIENT_SECRET + } + access_code_response = requests.post( + oauth_acces_token_url, + data=params + ) + + access_code_response_body = access_code_response.content.decode("utf-8") + status_code_invalid = access_code_response.status_code != 200 + if status_code_invalid: + raise RuntimeError(f"OAuth access token could not be fetched: {access_code_response.text}") + + access_code_response_body = json.loads(access_code_response_body) + access_token = access_code_response_body.get("access_token") + if not access_token: + raise RuntimeError(f"Access token response contained no token: {access_code_response_body}") + + user = User.oauth_get_user(access_token) + login(request, user) + return redirect("home") +