Skip to content

Commit 5a44254

Browse files
committed
Initial commit
0 parents  commit 5a44254

File tree

5 files changed

+241
-0
lines changed

5 files changed

+241
-0
lines changed

.gitignore

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
run.bat
2+
3+
# See https://help.github.com/ignore-files/ for more about ignoring files.
4+
5+
# dependencies
6+
/node_modules
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
14+
# misc
15+
.DS_Store
16+
.env.local
17+
.env.development.local
18+
.env.test.local
19+
.env.production.local
20+
21+
npm-debug.log*
22+
yarn-debug.log*
23+
yarn-error.log*
24+
25+
26+
# Byte-compiled / optimized / DLL files
27+
__pycache__/
28+
*.py[cod]
29+
*$py.class
30+
31+
# C extensions
32+
*.so
33+
34+
# Distribution / packaging
35+
.Python
36+
build/
37+
develop-eggs/
38+
dist/
39+
downloads/
40+
eggs/
41+
.eggs/
42+
lib/
43+
lib64/
44+
parts/
45+
sdist/
46+
var/
47+
wheels/
48+
*.egg-info/
49+
.installed.cfg
50+
*.egg
51+
MANIFEST
52+
53+
# PyInstaller
54+
# Usually these files are written by a python script from a template
55+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
56+
*.manifest
57+
*.spec
58+
59+
# Installer logs
60+
pip-log.txt
61+
pip-delete-this-directory.txt
62+
63+
# Unit test / coverage reports
64+
htmlcov/
65+
.tox/
66+
.coverage
67+
.coverage.*
68+
.cache
69+
nosetests.xml
70+
coverage.xml
71+
*.cover
72+
.hypothesis/
73+
.pytest_cache/
74+
75+
# Translations
76+
*.mo
77+
*.pot
78+
79+
# Django stuff:
80+
*.log
81+
local_settings.py
82+
db.sqlite3
83+
84+
# Flask stuff:
85+
instance/
86+
.webassets-cache
87+
88+
# Scrapy stuff:
89+
.scrapy
90+
91+
# Sphinx documentation
92+
docs/_build/
93+
94+
# PyBuilder
95+
target/
96+
97+
# Jupyter Notebook
98+
.ipynb_checkpoints
99+
100+
# pyenv
101+
.python-version
102+
103+
# celery beat schedule file
104+
celerybeat-schedule
105+
106+
# SageMath parsed files
107+
*.sage.py
108+
109+
# Environments
110+
.env
111+
.venv
112+
env/
113+
venv/
114+
ENV/
115+
env.bak/
116+
venv.bak/
117+
118+
# Spyder project settings
119+
.spyderproject
120+
.spyproject
121+
122+
# Rope project settings
123+
.ropeproject
124+
125+
# mkdocs documentation
126+
/site
127+
128+
# mypy
129+
.mypy_cache/
130+
131+
.vscode

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
https://www.mattbutton.com/2019/01/05/google-authentication-with-python-and-flask/

google_auth.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import functools
2+
import os
3+
4+
import flask
5+
6+
from authlib.client import OAuth2Session
7+
import google.oauth2.credentials
8+
import googleapiclient.discovery
9+
10+
ACCESS_TOKEN_URI = 'https://www.googleapis.com/oauth2/v4/token'
11+
AUTHORIZATION_URL = 'https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&prompt=consent'
12+
13+
AUTHORIZATION_SCOPE ='openid email profile'
14+
15+
AUTH_REDIRECT_URI = os.environ.get("FN_AUTH_REDIRECT_URI", default=False)
16+
BASE_URI = os.environ.get("FN_BASE_URI", default=False)
17+
CLIENT_ID = os.environ.get("FN_CLIENT_ID", default=False)
18+
CLIENT_SECRET = os.environ.get("FN_CLIENT_SECRET", default=False)
19+
20+
AUTH_TOKEN_KEY = 'auth_token'
21+
AUTH_STATE_KEY = 'auth_state'
22+
USER_INFO_KEY = 'user_info'
23+
24+
app = flask.Flask(__name__)
25+
app.secret_key = os.environ.get("FN_FLASK_SECRET_KEY", default=False)
26+
27+
@app.route('/')
28+
def index():
29+
if is_logged_in():
30+
user_info = get_user_info()
31+
return 'You are currently logged in as ' + user_info['given_name']
32+
33+
return 'You are not currently logged in'
34+
35+
def no_cache(view):
36+
@functools.wraps(view)
37+
def no_cache_impl(*args, **kwargs):
38+
response = flask.make_response(view(*args, **kwargs))
39+
response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0'
40+
response.headers['Pragma'] = 'no-cache'
41+
response.headers['Expires'] = '-1'
42+
return response
43+
44+
return functools.update_wrapper(no_cache_impl, view)
45+
46+
@app.route('/google/login')
47+
@no_cache
48+
def login():
49+
session = OAuth2Session(CLIENT_ID, CLIENT_SECRET, scope=AUTHORIZATION_SCOPE, redirect_uri=AUTH_REDIRECT_URI)
50+
uri, state = session.authorization_url(AUTHORIZATION_URL)
51+
flask.session[AUTH_STATE_KEY] = state
52+
flask.session.permanent = True
53+
return flask.redirect(uri, code=302)
54+
55+
56+
@app.route('/google/auth')
57+
@no_cache
58+
def google_auth_redirect():
59+
state = flask.request.args.get('state', default=None, type=None)
60+
61+
session = OAuth2Session(CLIENT_ID, CLIENT_SECRET, scope=AUTHORIZATION_SCOPE, state=state, redirect_uri=AUTH_REDIRECT_URI)
62+
oauth2_tokens = session.fetch_access_token(ACCESS_TOKEN_URI, authorization_response=flask.request.url)
63+
flask.session[AUTH_TOKEN_KEY] = oauth2_tokens
64+
65+
return flask.redirect(BASE_URI, code=302)
66+
67+
@app.route('/google/logout')
68+
@no_cache
69+
def logout():
70+
flask.session.pop(AUTH_TOKEN_KEY, None)
71+
flask.session.pop(AUTH_STATE_KEY, None)
72+
flask.session.pop(USER_INFO_KEY, None)
73+
74+
return flask.redirect(BASE_URI, code=302)
75+
76+
def is_logged_in():
77+
return True if AUTH_TOKEN_KEY in flask.session else False
78+
79+
def build_credentials():
80+
if not is_logged_in():
81+
raise Exception('User must be logged in')
82+
83+
oauth2_tokens = flask.session[AUTH_TOKEN_KEY]
84+
return google.oauth2.credentials.Credentials(
85+
oauth2_tokens['access_token'],
86+
refresh_token=oauth2_tokens['refresh_token'],
87+
client_id=CLIENT_ID,
88+
client_secret=CLIENT_SECRET,
89+
token_uri=ACCESS_TOKEN_URI)
90+
91+
def get_user_info():
92+
credentials = build_credentials()
93+
oauth2_client = googleapiclient.discovery.build('oauth2', 'v2', credentials=credentials)
94+
return oauth2_client.userinfo().get().execute()

requirements.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
authlib==0.10
2+
flask==1.0.2
3+
google-api-python-client
4+
google-auth
5+
virtualenv

run.bat.sample

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
set FN_AUTH_REDIRECT_URI=http://localhost:8040/google/auth
2+
set FN_BASE_URI=http://localhost:8040
3+
set FN_CLIENT_ID=THE CLIENT ID WHICH YOU CREATED EARLIER
4+
set FN_CLIENT_SECRET=THE CLIENT SECRET WHICH YOU CREATED EARLIER
5+
6+
set FLASK_APP=google_auth.py
7+
set FLASK_DEBUG=1
8+
set FN_FLASK_SECRET_KEY=1234567
9+
10+
python -m flask run -p 8040

0 commit comments

Comments
 (0)