From 964a29a9ff34e723fc7d1dfc2f1031af61b16ffe Mon Sep 17 00:00:00 2001
From: Julian Rother <julianr@fsmpi.rwth-aachen.de>
Date: Tue, 6 Oct 2020 21:45:23 +0200
Subject: [PATCH] Replaced manual oauth implementation with
 python-requests-oauthlib

---
 app.py | 75 +++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 48 insertions(+), 27 deletions(-)

diff --git a/app.py b/app.py
index a16fc2f..b7aa395 100644
--- a/app.py
+++ b/app.py
@@ -2,16 +2,16 @@ from functools import wraps
 import secrets, json
 import urllib.parse
 
-from flask import Flask, session, request, redirect, abort, render_template, url_for, flash, Response
+from flask import Flask, session, request, redirect, abort, url_for, Response
 
-import requests
+from requests_oauthlib import OAuth2Session
 
 app = Flask(__name__)
 app.secret_key = b'my secret'
 app.config['SESSION_COOKIE_NAME'] = 'oauth-session'
-app.config['OAUTH2_AUTH_URL'] = 'http://localhost:5001/oauth2/authorize'
-app.config['OAUTH2_TOKEN_URL'] = 'http://localhost:5001/oauth2/token'
-app.config['OAUTH2_USERINFO_URL'] = 'http://localhost:5001/oauth2/userinfo'
+app.config['OAUTH2_AUTH_URL'] = 'https://localhost:5001/oauth2/authorize'
+app.config['OAUTH2_TOKEN_URL'] = 'https://localhost:5001/oauth2/token'
+app.config['OAUTH2_USERINFO_URL'] = 'https://localhost:5001/oauth2/userinfo'
 
 @app.route("/auth")
 def auth():
@@ -21,37 +21,58 @@ def auth():
 	resp.headers['REMOTE_USER'] = session['user']
 	return resp
 
+def get_oauth(**kwargs):
+	return OAuth2Session(request.headers['X-CLIENT-ID'],
+		redirect_uri=request.headers['X-REDIRECT-URI'],
+		scope=request.headers['X-SCOPE'], **kwargs)
+
 @app.route("/login")
 def login():
-	client_id = request.headers['X-CLIENT-ID']
-	scope = request.headers['X-SCOPE']
-	redirect_uri = request.headers['X-REDIRECT-URI']
-	session['oauth-state'] = secrets.token_urlsafe()
-	session['oauth-ref'] = request.values.get('url', '/')
-	return redirect(app.config['OAUTH2_AUTH_URL']+'?'+urllib.parse.urlencode({'response_type': 'code', 'client_id': client_id, 'scope': scope, 'state': session['oauth-state'], 'redirect_uri': redirect_uri}))
+	client = get_oauth()
+	url, state = client.authorization_url(app.config['OAUTH2_AUTH_URL'])
+	session['state'] = state
+	session['url'] = request.values.get('url', '/')
+	return redirect(url)
 
 @app.route("/callback")
 def callback():
-	client_id = request.headers['X-CLIENT-ID']
-	client_secret = request.headers['X-CLIENT-SECRET']
-	redirect_uri = request.headers['X-REDIRECT-URI']
-	code = request.values['code']
-	if session.pop('oauth-state') != request.values['state']:
-		abort(500)
-	r = requests.request('POST', app.config['OAUTH2_TOKEN_URL'], data={'grant_type': 'authorization_code', 'code': code, 'redirect_uri': redirect_uri, 'client_id': client_id, 'client_secret': client_secret})
-	if r.status_code != 200:
-		abort(403)
-	data = r.json()
-	r = requests.request('GET', app.config['OAUTH2_USERINFO_URL'], headers={'Authorization': 'Bearer %s'%data['access_token']})
-	if r.status_code != 200:
-		abort(403)
-	session['user'] = r.json()['email']
-	return redirect(session.pop('oauth-ref'))
+	client = get_oauth(state=session.pop('state'))
+	token = client.fetch_token(app.config['OAUTH2_TOKEN_URL'], client_secret=request.headers['X-CLIENT-SECRET'], authorization_response=request.url, verify=False)
+	userinfo = client.get(app.config['OAUTH2_USERINFO_URL']).json()
+	session['user'] = userinfo['email']
+	return redirect(session.pop('url'))
 
 @app.route("/logout")
 def logout():
 	session.clear()
 	return 'Ok', 200
 
+@app.route("/status")
+def status():
+	resp = Response('''Proxy Configuration Status
+
+For this proxy service to work properly, the OAuth client crendentials must
+be injected in by the webserver as HTTP-headers:
+
+X-CLIENT-ID: %s
+X-CLIENT-SECRET: %s
+X-REDIRECT-URI: %s
+
+If you accessed this ressource with the URL
+
+    https://mydomain/mysubpath/info
+
+then the redirect URI must be set to:
+
+    https://mydomain/mysubpath/callback
+
+This exact redirect URI must also be registered with the OAuth server as
+a valid redirect_uri for the client_id.
+'''%(request.headers.get('X-CLIENT-ID', '(unset)'),
+	'(set)' if request.headers.get('X-CLIENT-SECRET') else '(unset)',
+	request.headers.get('X-REDIRECT-URI', '(unset)')))
+	resp.mimetype = 'text/plain; charset=utf-8'
+	return resp
+
 if __name__ == '__main__':
-	app.run(port=5002)
+	app.run(debug=True, host='localhost', port=5002, ssl_context='adhoc')
-- 
GitLab