summaryrefslogtreecommitdiff
path: root/opendc-web/opendc-web-api/app.py
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2021-05-14 15:17:49 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2021-05-17 17:06:50 +0200
commit0c6ccca5fac44ab40671627fd3181e9b138672fa (patch)
tree0c0cc4aa53921feeddfd0d1c9111eee9a9c84c54 /opendc-web/opendc-web-api/app.py
parent17327a642738e0500f9a007b32a46bb4f426f881 (diff)
api: Migrate to Auth0 for API authorization
This change updates the OpenDC API to use Auth0 for API authorization. This removes the hard dependency on Google for logging into OpenDC and simplifies implementation as we do not have to store user information anymore, other than the user identifier.
Diffstat (limited to 'opendc-web/opendc-web-api/app.py')
-rwxr-xr-xopendc-web/opendc-web-api/app.py47
1 files changed, 10 insertions, 37 deletions
diff --git a/opendc-web/opendc-web-api/app.py b/opendc-web/opendc-web-api/app.py
index 7a687678..ee4b3d32 100755
--- a/opendc-web/opendc-web-api/app.py
+++ b/opendc-web/opendc-web-api/app.py
@@ -3,16 +3,14 @@ import json
import os
import sys
import traceback
-import urllib.request
from dotenv import load_dotenv
from flask import Flask, request, jsonify
from flask_compress import Compress
from flask_cors import CORS
-from oauth2client import client, crypt
-from opendc.models.user import User
from opendc.util import rest, path_parser, database
+from opendc.util.auth import AuthError, AuthManager, AsymmetricJwtAlgorithm
from opendc.util.exceptions import AuthorizationTokenError, RequestInitializationError
from opendc.util.json import JSONEncoder
@@ -50,46 +48,21 @@ CORS(app)
compress = Compress()
compress.init_app(app)
-API_VERSIONS = {'v2'}
-
-
-@app.route('/tokensignin', methods=['POST'])
-def sign_in():
- """Authenticate a user with Google sign in"""
+auth = AuthManager(AsymmetricJwtAlgorithm(jwks_url=f"https://{os.environ['AUTH0_DOMAIN']}/.well-known/jwks.json"),
+ issuer=f"https://{os.environ['AUTH0_DOMAIN']}/", audience=os.environ['AUTH0_AUDIENCE'])
- try:
- token = request.form['idtoken']
- except KeyError:
- return 'No idtoken provided', 401
-
- try:
- idinfo = client.verify_id_token(token, os.environ['OPENDC_OAUTH_CLIENT_ID'])
-
- if idinfo['aud'] != os.environ['OPENDC_OAUTH_CLIENT_ID']:
- raise crypt.AppIdentityError('Unrecognized client.')
-
- if idinfo['iss'] not in ['accounts.google.com', 'https://accounts.google.com']:
- raise crypt.AppIdentityError('Wrong issuer.')
- except ValueError:
- url = "https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={}".format(token)
- req = urllib.request.Request(url)
- response = urllib.request.urlopen(url=req, timeout=30)
- res = response.read()
- idinfo = json.loads(res)
- except crypt.AppIdentityError as e:
- return 'Did not successfully authenticate'
-
- user = User.from_google_id(idinfo['sub'])
-
- data = {'isNewUser': user.obj is None}
+API_VERSIONS = {'v2'}
- if user.obj is not None:
- data['userId'] = user.get_id()
- return jsonify(**data)
+@app.errorhandler(AuthError)
+def handle_auth_error(ex):
+ response = jsonify(ex.error)
+ response.status_code = ex.status_code
+ return response
@app.route('/<string:version>/<path:endpoint_path>', methods=['GET', 'POST', 'PUT', 'DELETE'])
+@auth.require
def api_call(version, endpoint_path):
"""Call an API endpoint directly over HTTP."""