diff --git a/app.py b/app.py index 521263b48d3e0752e4d7cb495d530f8ecd324ee3..1d13e5b9b1d4d07295511a61366802383f6b64bb 100644 --- a/app.py +++ b/app.py @@ -7,57 +7,61 @@ from flask import Flask, session, request, redirect, abort, url_for, Response 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.route("/auth") -def auth(): - if not session.get('user_id'): - abort(401) - resp = Response('Ok', 200) - resp.headers['OAUTH-USER-ID'] = session['user_id'] - resp.headers['OAUTH-USER-NAME'] = session['user_name'] - resp.headers['OAUTH-USER-NICKNAME'] = session['user_nickname'] - resp.headers['OAUTH-USER-EMAIL'] = session['user_email'] - resp.headers['OAUTH-USER-GROUPS'] = ','.join(session['user_groups']) - return resp - -def get_oauth(**kwargs): - return OAuth2Session(request.headers['X-CLIENT-ID'], - redirect_uri=request.headers['X-REDIRECT-URI'], **kwargs) - -@app.route("/login") -def login(): - 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 = 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=(not app.debug)) - userinfo = client.get(app.config['OAUTH2_USERINFO_URL']).json() - session['user_id'] = userinfo['id'] # (usually numeric) unique user id - session['user_name'] = userinfo['name'] # display name - session['user_nickname'] = userinfo['nickname'] # unique user name (for urls, @-handles, ...) - session['user_email'] = userinfo['email'] - session['user_groups'] = userinfo['groups'] - 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 +def create_app(test_config=None): + app = Flask(__name__) + app.config['SECRET_KEY'] = secrets.token_hex(128) + app.config.from_pyfile('default_config.py') + if not test_config: + app.config.from_pyfile('config.py', silent=True) + else: + app.config.from_mapping(test_config) + + @app.route("/auth") + def auth(): + if not session.get('user_id'): + abort(401) + resp = Response('Ok', 200) + resp.headers['OAUTH-USER-ID'] = session['user_id'] + resp.headers['OAUTH-USER-NAME'] = session['user_name'] + resp.headers['OAUTH-USER-NICKNAME'] = session['user_nickname'] + resp.headers['OAUTH-USER-EMAIL'] = session['user_email'] + resp.headers['OAUTH-USER-GROUPS'] = ','.join(session['user_groups']) + return resp + + def get_oauth(**kwargs): + return OAuth2Session(request.headers['X-CLIENT-ID'], + redirect_uri=request.headers['X-REDIRECT-URI'], **kwargs) + + @app.route("/login") + def login(): + 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 = 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=(not app.debug)) + userinfo = client.get(app.config['OAUTH2_USERINFO_URL']).json() + session['user_id'] = userinfo['id'] # (usually numeric) unique user id + session['user_name'] = userinfo['name'] # display name + session['user_nickname'] = userinfo['nickname'] # unique user name (for urls, @-handles, ...) + session['user_email'] = userinfo['email'] + session['user_groups'] = userinfo['groups'] + 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: @@ -68,21 +72,24 @@ X-REDIRECT-URI: %s If you accessed this ressource with the URL - https://mydomain/mysubpath/info + https://mydomain/mysubpath/info then the redirect URI must be set to: - https://mydomain/mysubpath/callback + 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 + '(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 + + return app if __name__ == '__main__': # oauthlib enforces the OAuth2.0 requirement to use HTTPS, when this is not set os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' # Don't do that in production! + app = create_app() app.run(debug=True, host='localhost', port=5002) diff --git a/default_config.py b/default_config.py new file mode 100644 index 0000000000000000000000000000000000000000..741533dec1b97be4181a2edd7159ce11a66acb38 --- /dev/null +++ b/default_config.py @@ -0,0 +1,10 @@ +# OAuthProxy will usually served from the same domain as the services that +# use it for OAuth integration, so make sure that the session cookie does +# not conflict with any other cookies! +SESSION_COOKIE_NAME = 'oauth-session' + +# URLs of the OAuth2-based identity provider +OAUTH2_AUTH_URL = 'http://localhost:5001/oauth2/authorize' +OAUTH2_TOKEN_URL = 'http://localhost:5001/oauth2/token' +OAUTH2_USERINFO_URL = 'http://localhost:5001/oauth2/userinfo' +