diff --git a/config-sample.ini b/config-sample.ini index 303f7ae..b31be90 100644 --- a/config-sample.ini +++ b/config-sample.ini @@ -12,4 +12,11 @@ fr_secret_key=sample source=12135551212 [app] -debug=1 ;1 for true and anything else for false. \ No newline at end of file +debug=1 ;1 for true and anything else for false. + +[auth] +FN_AUTH_REDIRECT_URI=http://localhost:8040/google/auth +FN_BASE_URI=http://localhost:8040 +FN_CLIENT_ID= +FN_CLIENT_SECRET= +FN_FLASK_SECRET_KEY=SOMETHING RANDOM AND SECRET \ No newline at end of file diff --git a/google_auth.py b/google_auth.py new file mode 100644 index 0000000..d0ed095 --- /dev/null +++ b/google_auth.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +#This comes from https://www.mattbutton.com/2019/01/05/google-authentication-with-python-and-flask/ +#With the nessicary mods for my program. + +import functools +import os + +import flask + +from authlib.client import OAuth2Session +import google.oauth2.credentials +import googleapiclient.discovery + +ACCESS_TOKEN_URI = 'https://www.googleapis.com/oauth2/v4/token' +AUTHORIZATION_URL = 'https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&prompt=consent' + +AUTHORIZATION_SCOPE ='openid email profile' + +AUTH_REDIRECT_URI = config.get("auth","FN_AUTH_REDIRECT_URI") +BASE_URI = config.get("auth","FN_BASE_URI") +CLIENT_ID = config.get("auth","FN_CLIENT_ID") +CLIENT_SECRET = config.get("auth","FN_CLIENT_SECRET") + +AUTH_TOKEN_KEY = 'auth_token' +AUTH_STATE_KEY = 'auth_state' + +app = flask.Blueprint('google_auth', __name__) + +def is_logged_in(): + return True if AUTH_TOKEN_KEY in flask.session else False + +def build_credentials(): + if not is_logged_in(): + raise Exception('User must be logged in') + + oauth2_tokens = flask.session[AUTH_TOKEN_KEY] + + return google.oauth2.credentials.Credentials( + oauth2_tokens['access_token'], + refresh_token=oauth2_tokens['refresh_token'], + client_id=CLIENT_ID, + client_secret=CLIENT_SECRET, + token_uri=ACCESS_TOKEN_URI) + +def get_user_info(): + credentials = build_credentials() + + oauth2_client = googleapiclient.discovery.build( + 'oauth2', 'v2', + credentials=credentials) + + return oauth2_client.userinfo().get().execute() + +def no_cache(view): + @functools.wraps(view) + def no_cache_impl(*args, **kwargs): + response = flask.make_response(view(*args, **kwargs)) + response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0' + response.headers['Pragma'] = 'no-cache' + response.headers['Expires'] = '-1' + return response + + return functools.update_wrapper(no_cache_impl, view) + +@app.route('/google/login') +@no_cache +def login(): + session = OAuth2Session(CLIENT_ID, CLIENT_SECRET, + scope=AUTHORIZATION_SCOPE, + redirect_uri=AUTH_REDIRECT_URI) + + uri, state = session.authorization_url(AUTHORIZATION_URL) + + flask.session[AUTH_STATE_KEY] = state + flask.session.permanent = True + + return flask.redirect(uri, code=302) + +@app.route('/google/auth') +@no_cache +def google_auth_redirect(): + req_state = flask.request.args.get('state', default=None, type=None) + + if req_state != flask.session[AUTH_STATE_KEY]: + response = flask.make_response('Invalid state parameter', 401) + return response + + session = OAuth2Session(CLIENT_ID, CLIENT_SECRET, + scope=AUTHORIZATION_SCOPE, + state=flask.session[AUTH_STATE_KEY], + redirect_uri=AUTH_REDIRECT_URI) + + oauth2_tokens = session.fetch_access_token( + ACCESS_TOKEN_URI, + authorization_response=flask.request.url) + + flask.session[AUTH_TOKEN_KEY] = oauth2_tokens + + return flask.redirect(BASE_URI, code=302) + +@app.route('/google/logout') +@no_cache +def logout(): + flask.session.pop(AUTH_TOKEN_KEY, None) + flask.session.pop(AUTH_STATE_KEY, None) + + return flask.redirect(BASE_URI, code=302) \ No newline at end of file