From 0c1d37c29c75ce2abbc7c47fa6aaf172d9704d49 Mon Sep 17 00:00:00 2001 From: Benny Date: Thu, 9 Feb 2023 20:22:17 +0100 Subject: [PATCH] =?UTF-8?q?oauth=20=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- YYeTsFE | 2 +- yyetsweb/handler.py | 122 ++++++++++++++++++++------------------------ yyetsweb/server.py | 6 +-- 3 files changed, 58 insertions(+), 72 deletions(-) diff --git a/YYeTsFE b/YYeTsFE index 6eb3be3..b0961e2 160000 --- a/YYeTsFE +++ b/YYeTsFE @@ -1 +1 @@ -Subproject commit 6eb3be333d1f876b41a18d4b4f0ebcaf23d69f97 +Subproject commit b0961e29865e2af251338039692142219dc630b9 diff --git a/yyetsweb/handler.py b/yyetsweb/handler.py index 9b9dd5d..f409abe 100644 --- a/yyetsweb/handler.py +++ b/yyetsweb/handler.py @@ -1009,16 +1009,35 @@ class SpamProcessHandler(BaseHandler): class OAuth2Handler(BaseHandler, OAuth2Mixin): - class_name = f"OAuthRegisterResource" + class_name = "OAuthRegisterResource" _OAUTH_AUTHORIZE_URL = "" _OAUTH_ACCESS_TOKEN_URL = "" _OAUTH_API_REQUEST_URL = "" def add_oauth_user(self, username, source=None): + logging.info("User %s login with %s now...", username, source) ip = self.get_real_ip() browser = self.request.headers['user-agent'] - response = self.instance.add_user(username, ip, browser, source) - return response + result = self.instance.add_user(username, ip, browser, source) + if result["status"] == "success": + self.set_secure_cookie("username", username, 365) + self.redirect("/login?" + urlencode(result)) + + def get_authenticated_user(self, client_id: str, client_secret: str, code: str, extra_fields: dict = None): + args = {"code": code, "client_id": client_id, "client_secret": client_secret} + if extra_fields: + args.update(extra_fields) + return requests.post(self._OAUTH_ACCESS_TOKEN_URL, headers={"Accept": "application/json"}, data=args).json() + + def oauth2_sync_request(self, access_token): + return requests.get(self._OAUTH_API_REQUEST_URL, headers={"Authorization": f"Bearer {access_token}"}).json() + + def get_secret(self, settings_key): + settings = self.settings.get(settings_key) + client_id = settings.get("key") + client_secret = settings.get("secret") + redirect_uri = os.getenv("DOMAIN") + self.request.path + return client_id, client_secret, redirect_uri class GitHubOAuth2LoginHandler(OAuth2Handler): @@ -1027,32 +1046,43 @@ class GitHubOAuth2LoginHandler(OAuth2Handler): _OAUTH_API_REQUEST_URL = "https://api.github.com/user" def get(self): - settings = self.settings.get("github_oauth") - github_client_id = settings.get("key") - github_client_secret = settings.get("secret") - redirect_uri = os.getenv("DOMAIN") + self.request.path - + client_id, client_secret, redirect_uri = self.get_secret("github_oauth") code = self.get_argument('code', None) if code: - body = {"client_id": github_client_id, "client_secret": github_client_secret, "code": code} - access = requests.post(self._OAUTH_ACCESS_TOKEN_URL, data=body, - headers={"Accept": "application/json"}).json() - resp = requests.get(self._OAUTH_API_REQUEST_URL, - headers={"Authorization": "Bearer {}".format(access["access_token"])} - ).json() - + access = self.get_authenticated_user(client_id, client_secret, code) + resp = self.oauth2_sync_request(access["access_token"]) username = resp["login"] - logging.info("User %s login with GitHub now...", username) - result = self.add_oauth_user(username, "GitHub") - if result["status"] == "success": - self.set_secure_cookie("username", username, 365) - self.redirect("/login?" + urlencode(result)) + self.add_oauth_user(username, "GitHub") + else: + self.authorize_redirect( + redirect_uri=redirect_uri, + client_id=client_id, + scope=[], + response_type='code') + + +class MSOAuth2LoginHandler(OAuth2Handler): + _OAUTH_AUTHORIZE_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize" + _OAUTH_ACCESS_TOKEN_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/token" + _OAUTH_API_REQUEST_URL = "https://graph.microsoft.com/v1.0/me" + + def get(self): + client_id, client_secret, redirect_uri = self.get_secret("ms_oauth") + code = self.get_argument('code', None) + if code: + access = self.get_authenticated_user( + client_id, client_secret, code, + {"grant_type": "authorization_code", "redirect_uri": redirect_uri} + ) + resp = self.oauth2_sync_request(access["access_token"]) + email = resp["userPrincipalName"] + self.add_oauth_user(email, "Microsoft") else: self.authorize_redirect( redirect_uri=redirect_uri, - client_id=github_client_id, - scope=[], + client_id=client_id, + scope=["https://graph.microsoft.com/User.Read"], response_type='code') @@ -1069,11 +1099,7 @@ class GoogleOAuth2LoginHandler(GoogleOAuth2Mixin, OAuth2Handler): "https://www.googleapis.com/oauth2/v1/userinfo", access_token=access["access_token"]) email = user["email"] - logging.info("User %s login with Google now...", email) - result = self.add_oauth_user(email, "Google") - if result["status"] == "success": - self.set_secure_cookie("username", email, 365) - self.redirect("/login?" + urlencode(result)) + self.add_oauth_user(email, "Google") else: self.authorize_redirect( redirect_uri=redirect_uri, @@ -1088,46 +1114,6 @@ class TwitterOAuth2LoginHandler(TwitterMixin, OAuth2Handler): if self.get_argument("oauth_token", None): user = await self.get_authenticated_user() username = user["username"] - logging.info("User %s login with Twitter now...", username) - result = self.add_oauth_user(username, "Twitter") - if result["status"] == "success": - self.set_secure_cookie("username", username, 365) - self.redirect("/login?" + urlencode(result)) - # Save the user using e.g. set_secure_cookie() + self.add_oauth_user(username, "Twitter") else: await self.authorize_redirect(extra_params={"x_auth_access_type": "read"}) - - -class MSOAuth2LoginHandler(OAuth2Handler): - _OAUTH_AUTHORIZE_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize" - _OAUTH_ACCESS_TOKEN_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/token" - _OAUTH_API_REQUEST_URL = "https://graph.microsoft.com/v1.0/me" - - def get(self): - settings = self.settings.get("ms_oauth") - client_id = settings.get("key") - client_secret = settings.get("secret") - redirect_uri = os.getenv("DOMAIN") + self.request.path - - code = self.get_argument('code', None) - if code: - body = {"client_id": client_id, "client_secret": client_secret, "code": code, - "grant_type": "authorization_code", "redirect_uri": redirect_uri} - access = requests.post(self._OAUTH_ACCESS_TOKEN_URL, data=body, - headers={"Accept": "application/json"}).json() - resp = requests.get(self._OAUTH_API_REQUEST_URL, - headers={"Authorization": "Bearer {}".format(access["access_token"])} - ).json() - email = resp["userPrincipalName"] - logging.info("User %s login with Microsoft now...", email) - result = self.add_oauth_user(email, "Microsoft") - if result["status"] == "success": - self.set_secure_cookie("username", email, 365) - self.redirect("/login?" + urlencode(result)) - - else: - self.authorize_redirect( - redirect_uri=redirect_uri, - client_id=client_id, - scope=["https://graph.microsoft.com/User.Read"], - response_type='code') diff --git a/yyetsweb/server.py b/yyetsweb/server.py index a927c5b..eb08fbe 100644 --- a/yyetsweb/server.py +++ b/yyetsweb/server.py @@ -24,13 +24,13 @@ import dump_db from Mongo import OtherMongoResource, ResourceLatestMongoResource from handler import (AnnouncementHandler, BlacklistHandler, CaptchaHandler, CategoryHandler, CommentChildHandler, CommentHandler, - CommentNewestHandler, CommentReactionHandler, MSOAuth2LoginHandler, + CommentNewestHandler, CommentReactionHandler, DBDumpHandler, DoubanHandler, DoubanReportHandler, GitHubOAuth2LoginHandler, GoogleOAuth2LoginHandler, GrafanaIndexHandler, GrafanaQueryHandler, GrafanaSearchHandler, IndexHandler, LikeHandler, - MetricsHandler, NameHandler, NotFoundHandler, - NotificationHandler, ResourceHandler, + MetricsHandler, MSOAuth2LoginHandler, NameHandler, + NotFoundHandler, NotificationHandler, ResourceHandler, ResourceLatestHandler, SpamProcessHandler, TopHandler, TwitterOAuth2LoginHandler, UserEmailHandler, UserHandler) from migration.douban_sync import sync_douban