From 571dad6f607b4ff304ae6037003e3a68dbae1852 Mon Sep 17 00:00:00 2001 From: knst-kotov Date: Fri, 9 Jul 2021 07:14:16 +0000 Subject: [PATCH] oauth via github --- auth/identity.py | 26 ++++++++++++++-------- auth/oauth.py | 57 +++++++++++++++++++++++++++++++++--------------- create_crt.sh | 10 +++++++++ main.py | 8 ++++--- orm/user.py | 4 +++- server.py | 2 +- 6 files changed, 76 insertions(+), 31 deletions(-) create mode 100644 create_crt.sh diff --git a/auth/identity.py b/auth/identity.py index 8af26a2c..1eefe773 100644 --- a/auth/identity.py +++ b/auth/identity.py @@ -6,12 +6,20 @@ from auth.validations import User class Identity: - @staticmethod - def identity(user_id: int, password: str) -> User: - user = global_session.query(OrmUser).filter_by(id=user_id).first() - if not user: - raise ObjectNotExist("User does not exist") - user = User(**user.dict()) - if not Password.verify(password, user.password): - raise InvalidPassword("Wrong user password") - return user + @staticmethod + def identity(user_id: int, password: str) -> User: + user = global_session.query(OrmUser).filter_by(id=user_id).first() + if not user: + raise ObjectNotExist("User does not exist") + user = User(**user.dict()) + if not Password.verify(password, user.password): + raise InvalidPassword("Wrong user password") + return user + + @staticmethod + def identity_oauth(oauth_id, input) -> User: + user = global_session.query(OrmUser).filter_by(oauth_id=oauth_id).first() + if not user: + user = OrmUser.create(**input) + user = User(**user.dict()) + return user diff --git a/auth/oauth.py b/auth/oauth.py index a52afd07..5f6c30c0 100644 --- a/auth/oauth.py +++ b/auth/oauth.py @@ -1,28 +1,51 @@ from authlib.integrations.starlette_client import OAuth from starlette.responses import PlainTextResponse +from auth.authorize import Authorize +from auth.identity import Identity + oauth = OAuth() oauth.register( - name='facebook', - client_id='222122999761250', - client_secret='', - access_token_url='https://graph.facebook.com/v11.0/oauth/access_token', - access_token_params=None, - authorize_url='https://www.facebook.com/v11.0/dialog/oauth', - authorize_params=None, - api_base_url='https://graph.facebook.com/', - client_kwargs={'scope': 'user:email'}, + name='facebook', + client_id='222122999761250', + client_secret='', + access_token_url='https://graph.facebook.com/v11.0/oauth/access_token', + access_token_params=None, + authorize_url='https://www.facebook.com/v11.0/dialog/oauth', + authorize_params=None, + api_base_url='https://graph.facebook.com/', + client_kwargs={'scope': 'user:email'}, +) + +oauth.register( + name='github', + client_id='58877ba7ad9baef280b4', + client_secret='', + access_token_url='https://github.com/login/oauth/access_token', + access_token_params=None, + authorize_url='https://github.com/login/oauth/authorize', + authorize_params=None, + api_base_url='https://api.github.com/', + client_kwargs={'scope': 'user:email'}, ) async def oauth_login(request): - facebook = oauth.create_client('facebook') - redirect_uri = request.url_for('oauth_authorize') - return await facebook.authorize_redirect(request, redirect_uri) + github = oauth.create_client('github') + redirect_uri = request.url_for('oauth_authorize') + return await github.authorize_redirect(request, redirect_uri) async def oauth_authorize(request): - facebook = oauth.create_client('facebook') - token = await facebook.authorize_access_token(request) - email = await facebook.parse_id_token(request, token) - print(email) - return PlainTextResponse("%s auth" % email) + github = oauth.create_client('github') + token = await github.authorize_access_token(request) + resp = await github.get('user', token=token) + profile = resp.json() + oauth_id = profile["id"] + user_input = { + "oauth_id" : oauth_id, + "email" : profile["email"], + "username" : profile["name"] + } + user = Identity.identity_oauth(oauth_id=oauth_id, input=user_input) + token = await Authorize.authorize(user, device="pc", auto_delete=False) + return PlainTextResponse(token) diff --git a/create_crt.sh b/create_crt.sh new file mode 100644 index 00000000..ee5b19a8 --- /dev/null +++ b/create_crt.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +openssl req -newkey rsa:4096 \ + -x509 \ + -sha256 \ + -days 3650 \ + -nodes \ + -out discours.crt \ + -keyout discours.key \ + -subj "/C=RU/ST=Moscow/L=Moscow/O=Discours/OU=Site/CN=10.0.0.187" diff --git a/main.py b/main.py index 9e934d6b..0050b16a 100644 --- a/main.py +++ b/main.py @@ -5,6 +5,7 @@ from ariadne.asgi import GraphQL from starlette.applications import Starlette from starlette.middleware import Middleware from starlette.middleware.authentication import AuthenticationMiddleware +from starlette.middleware.sessions import SessionMiddleware from starlette.routing import Route from auth.authenticate import JWTAuthenticate @@ -15,8 +16,10 @@ from resolvers.base import resolvers import_module('resolvers') schema = make_executable_schema(load_schema_from_path("schema/"), resolvers) -middleware = [Middleware(AuthenticationMiddleware, backend=JWTAuthenticate())] - +middleware = [ + Middleware(AuthenticationMiddleware, backend=JWTAuthenticate()), + Middleware(SessionMiddleware, secret_key="!secret") +] async def start_up(): await redis.connect() @@ -30,6 +33,5 @@ routes = [ Route("/authorize", endpoint=oauth_authorize) ] - app = Starlette(debug=True, on_startup=[start_up], on_shutdown=[shutdown], middleware=middleware, routes=routes) app.mount("/", GraphQL(schema, debug=True)) diff --git a/orm/user.py b/orm/user.py index be6db8d2..4cf99f4b 100644 --- a/orm/user.py +++ b/orm/user.py @@ -11,9 +11,11 @@ class User(Base): email: str = Column(String, nullable=False) username: str = Column(String, nullable=False, comment="Name") - password: str = Column(String, nullable=False, comment="Password") + password: str = Column(String, nullable=True, comment="Password") role_id: int = Column(ForeignKey("role.id"), nullable=True, comment="Role") + + oauth_id: str = Column(String, nullable=True) @classmethod def get_permission(cls, user_id): diff --git a/server.py b/server.py index 6741b77c..f3360c96 100644 --- a/server.py +++ b/server.py @@ -1,4 +1,4 @@ import uvicorn if __name__ == '__main__': - uvicorn.run("main:app", host="0.0.0.0", port=8081, reload=True) + uvicorn.run("main:app", host="0.0.0.0", port=8081, ssl_keyfile="discours.key", ssl_certfile="discours.crt", reload=True)