diff options
Diffstat (limited to 'gn3/auth/authentication/oauth2/grants')
3 files changed, 63 insertions, 0 deletions
diff --git a/gn3/auth/authentication/oauth2/grants/__init__.py b/gn3/auth/authentication/oauth2/grants/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/gn3/auth/authentication/oauth2/grants/__init__.py diff --git a/gn3/auth/authentication/oauth2/grants/authorisation_code_grant.py b/gn3/auth/authentication/oauth2/grants/authorisation_code_grant.py new file mode 100644 index 0000000..d398192 --- /dev/null +++ b/gn3/auth/authentication/oauth2/grants/authorisation_code_grant.py @@ -0,0 +1,45 @@ +"""Classes and function for Authorisation Code flow.""" +import uuid +from typing import Optional + +from flask import current_app as app +from authlib.oauth2.rfc6749 import grants + +from gn3.auth import db +from gn3.auth.authentication.users import User + +class AuthorisationCodeGrant(grants.AuthorizationCodeGrant): + """Implement the 'Authorisation Code' grant.""" + TOKEN_ENDPOINT_AUTH_METHODS = ["client_secret_basic", "client_secret_post"] + + def save_authorization_code(self, code, request): + """Persist the authorisation code to database.""" + raise Exception("NOT IMPLEMENTED!", self, code, request) + + def query_authorization_code(self, code, client): + """Retrieve the code from the database.""" + raise Exception("NOT IMPLEMENTED!", self, code, client) + + def delete_authorization_code(self, authorization_code):# pylint: disable=[no-self-use] + """Delete the authorisation code.""" + with db.connection(app.config["AUTH_DB"]) as conn: + with db.cursor(conn) as cursor: + cursor.execute( + "DELETE FROM authorisation_code WHERE code_id=?", + (str(authorization_code.code_id),)) + + def authenticate_user(self, authorization_code) -> Optional[User]: + """Authenticate the user who own the authorisation code.""" + query = ( + "SELECT users.* FROM authorisation_code LEFT JOIN users " + "ON authorisation_code.user_id=users.user_id " + "WHERE authorisation_code.code=?") + with db.connection(app.config["AUTH_DB"]) as conn: + with db.cursor(conn) as cursor: + cursor.execute(query, (str(authorization_code.user_id),)) + res = cursor.fetchone() + if res: + return User( + uuid.UUID(res["user_id"]), res["email"], res["name"]) + + return None diff --git a/gn3/auth/authentication/oauth2/grants/password_grant.py b/gn3/auth/authentication/oauth2/grants/password_grant.py new file mode 100644 index 0000000..91fdb7c --- /dev/null +++ b/gn3/auth/authentication/oauth2/grants/password_grant.py @@ -0,0 +1,18 @@ +"""Allows users to authenticate directly.""" + +from flask import current_app as app +from authlib.oauth2.rfc6749 import grants + +from gn3.auth import db +from gn3.auth.authentication.users import valid_login, user_by_email + +class PasswordGrant(grants.ResourceOwnerPasswordCredentialsGrant): + """Implement the 'Password' grant.""" + TOKEN_ENDPOINT_AUTH_METHODS = ["client_secret_basic", "client_secret_post"] + + def authenticate_user(self, username, password): + "Authenticate the user with their username and password." + with db.connection(app.config["AUTH_DB"]) as conn: + return user_by_email(conn, username).maybe( + None, + lambda user: valid_login(conn, user, password)) |