Skip to content
This repository has been archived by the owner on May 4, 2023. It is now read-only.

Commit

Permalink
Merge pull request #58 from trevorwang/master
Browse files Browse the repository at this point in the history
add Github OAuth2 login handler
  • Loading branch information
codeskyblue authored Aug 10, 2021
2 parents f6d7003 + 21b17cb commit d8ee3ec
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 7 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ python3 main.py
# 指定认证方式
python3 main.py --auth simple # 默认是一个非常simple的认证,输入邮箱就可以
python3 main.py --auth openid # 网易内部使用
python3 main.py --auth github # github 认证, 需要在 `settings.py` 里面配置 `client_id` 和 `client_secret` 相关信息
# 其他的认证方式还有待添加,非常欢迎PR

# 设置监听端口
Expand Down
6 changes: 4 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from web.database import db
from web.entry import make_app
from web.views import OpenIdLoginHandler, SimpleLoginHandler
from web.views import OpenIdLoginHandler, SimpleLoginHandler, GithubLoginHandler


def machine_ip():
Expand All @@ -30,6 +30,7 @@ def main():
_auth_handlers = {
"simple": SimpleLoginHandler,
"openid": OpenIdLoginHandler,
"github": GithubLoginHandler
}

parser = argparse.ArgumentParser(
Expand All @@ -41,7 +42,8 @@ def main():
help='open debug log, and open hot reload')
parser.add_argument('--auth', type=str, default='simple',
choices=_auth_handlers.keys(), help='authentication method')
parser.add_argument("--no-xheaders", action="store_true", help="disable support for X-Real-Ip/X-Forwarded-For")
parser.add_argument("--no-xheaders", action="store_true",
help="disable support for X-Real-Ip/X-Forwarded-For")
parser.add_argument(
'--auth-conf-file', type=argparse.FileType('r'), help='authentication config file')
# yapf: enable
Expand Down
8 changes: 7 additions & 1 deletion web/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@
"openid": {
"endpoint": "https://login.netease.com/openid/"
}
}
}

GITHUB = {
"client_id": "client_id",
"client_secret": "client-secret",
"redirect_uri": "http://your-web-site/login"
}
2 changes: 1 addition & 1 deletion web/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
from concurrent.futures import ThreadPoolExecutor
from .base import BaseRequestHandler, AuthRequestHandler
from .login import OpenIdLoginHandler, SimpleLoginHandler
from .login import OpenIdLoginHandler, SimpleLoginHandler, GithubLoginHandler


class LogoutHandler(BaseRequestHandler):
Expand Down
3 changes: 2 additions & 1 deletion web/views/auth/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# coding: utf-8
#

from .openid import OpenIdMixin, AuthError
from .openid import OpenIdMixin, AuthError
from .github import GithubOAuth2Mixin
41 changes: 41 additions & 0 deletions web/views/auth/github.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import urllib.parse
import uuid

from logzero import logger

from tornado import httpclient
from tornado import escape
from tornado.auth import OAuth2Mixin
from tornado.httputil import url_concat
from tornado.util import unicode_type
from tornado.web import RequestHandler

from typing import List, Any, Dict, cast, Iterable, Union, Optional


class GithubOAuth2Mixin(OAuth2Mixin):

_OAUTH_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token"
_OAUTH_AUTHORIZE_URL = "https://github.com/login/oauth/authorize"
_OAUTH_SETTINGS_KEY = 'github'

async def get_authenticated_user(self, redirect_uri: str, code: str, client_id: str, client_secret: str) -> Dict[str, Any]:
http = self.get_auth_http_client()
body = urllib.parse.urlencode(
{
"redirect_uri": redirect_uri,
"code": code,
"client_id": client_id,
"client_secret": client_secret,
"grant_type": "authorization_code",
}
)

response = await http.fetch(
self._OAUTH_ACCESS_TOKEN_URL,
method="POST",
headers={"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json"},
body=body,
)
return escape.json_decode(response.body)
36 changes: 34 additions & 2 deletions web/views/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
#

from logzero import logger
from tornado.auth import OAuth2Mixin

from .auth import AuthError, OpenIdMixin
from .auth import AuthError, OpenIdMixin, GithubOAuth2Mixin
from .base import BaseRequestHandler

from ..settings import AUTH_BACKENDS
from ..settings import AUTH_BACKENDS, GITHUB


class OpenIdLoginHandler(BaseRequestHandler, OpenIdMixin):
Expand Down Expand Up @@ -44,3 +45,34 @@ async def post(self):
next_url = self.get_cookie("next", "/")
self.clear_cookie("next")
self.redirect(next_url)


class GithubLoginHandler(BaseRequestHandler, GithubOAuth2Mixin):

async def get(self):
if self.get_argument('code', False):
access = await self.get_authenticated_user(
redirect_uri=GITHUB['redirect_uri'],
client_id=GITHUB['client_id'],
client_secret=GITHUB['client_secret'],
code=self.get_argument('code'))
http = self.get_auth_http_client()

response = await http.fetch(
"https://api.github.com/user",
headers={"Authorization": "token " + access["access_token"]}
)
user = escape.json_decode(response.body)
logger.info("User info: %s", user)
await self.set_current_user(user['email'], user['name'])
next_url = self.get_argument('next', '/')
self.redirect(next_url)
# Save the user and access token with
# e.g. set_secure_cookie.
else:
await self.authorize_redirect(
redirect_uri=GITHUB['redirect_uri'],
client_id=GITHUB['client_id'],
scope=['user'],
response_type='code',
extra_params={'approval_prompt': 'auto'})

0 comments on commit d8ee3ec

Please sign in to comment.