|
1 | | -import jwt |
2 | | - |
| 1 | +import json |
3 | 2 | from os import environ as env, path |
| 3 | +import urllib |
| 4 | + |
4 | 5 | from dotenv import load_dotenv |
5 | 6 | from functools import wraps |
6 | 7 | from flask import Flask, request, jsonify, _app_ctx_stack |
7 | 8 | from flask_cors import cross_origin |
| 9 | +from jose import jwt |
8 | 10 |
|
9 | 11 | load_dotenv(path.join(path.dirname(__file__), '.env')) |
10 | | -client_id = env["AUTH0_CLIENT_ID"] |
11 | | -client_secret = env["AUTH0_CLIENT_SECRET"] |
| 12 | +auth0_domain = env['AUTH0_DOMAIN'] |
| 13 | +api_audience = env['API_ID'] |
12 | 14 |
|
13 | 15 | app = Flask(__name__) |
14 | 16 |
|
@@ -45,31 +47,43 @@ def decorated(*args, **kwargs): |
45 | 47 | 'Bearer + \s + token'}, 401) |
46 | 48 |
|
47 | 49 | token = parts[1] |
48 | | - try: |
49 | | - payload = jwt.decode( |
50 | | - token, |
51 | | - client_secret, |
52 | | - audience=client_id |
53 | | - ) |
54 | | - except jwt.ExpiredSignatureError: |
55 | | - return handle_error({'code': 'token_expired', |
56 | | - 'description': 'token is expired'}, 401) |
57 | | - except jwt.InvalidAudienceError: |
58 | | - return handle_error({'code': 'invalid_audience', |
59 | | - 'description': 'incorrect audience, expected: ' |
60 | | - + client_id}, 401) |
61 | | - except jwt.DecodeError: |
62 | | - return handle_error({'code': 'token_invalid_signature', |
63 | | - 'description': |
64 | | - 'token signature is invalid'}, 401) |
65 | | - except Exception: |
66 | | - return handle_error({'code': 'invalid_header', |
67 | | - 'description': 'Unable to parse authentication' |
68 | | - ' token.'}, 400) |
69 | | - |
70 | | - _app_ctx_stack.top.current_user = payload |
71 | | - return f(*args, **kwargs) |
72 | | - |
| 50 | + jsonurl = urllib.urlopen('https://'+auth0_domain+'/.well-known/jwks.json') |
| 51 | + jwks = json.loads(jsonurl.read()) |
| 52 | + unverified_header = jwt.get_unverified_header(token) |
| 53 | + rsa_key = {} |
| 54 | + for key in jwks['keys']: |
| 55 | + if key['kid'] == unverified_header['kid']: |
| 56 | + rsa_key = { |
| 57 | + 'kty': key['kty'], |
| 58 | + 'kid': key['kid'], |
| 59 | + 'use': key['use'], |
| 60 | + 'n': key['n'], |
| 61 | + 'e': key['e'] |
| 62 | + } |
| 63 | + if rsa_key: |
| 64 | + try: |
| 65 | + payload = jwt.decode( |
| 66 | + token, |
| 67 | + rsa_key, |
| 68 | + algorithms=unverified_header['alg'], |
| 69 | + audience=api_audience, |
| 70 | + issuer='https://'+auth0_domain+'/' |
| 71 | + ) |
| 72 | + except jwt.ExpiredSignatureError: |
| 73 | + return handle_error({'code': 'token_expired', |
| 74 | + 'description': 'token is expired'}, 401) |
| 75 | + except jwt.JWTClaimsError: |
| 76 | + return handle_error({'code': 'invalid_claims', |
| 77 | + 'description': 'incorrect claims, please check the audience and issuer'}, 401) |
| 78 | + except Exception: |
| 79 | + return handle_error({'code': 'invalid_header', |
| 80 | + 'description': 'Unable to parse authentication' |
| 81 | + ' token.'}, 400) |
| 82 | + |
| 83 | + _app_ctx_stack.top.current_user = payload |
| 84 | + return f(*args, **kwargs) |
| 85 | + return handle_error({'code': 'invalid_header', |
| 86 | + 'description': 'Unable to find appropriate key'}, 400) |
73 | 87 | return decorated |
74 | 88 |
|
75 | 89 |
|
|
0 commit comments