I was able to work with Firebase JWT and Flask JWT Extended in order to login my users and validate the JWT. To validate the JWT issued by Firebase to my app I had to code the following:
import requests
from cryptography import x509
from app import jwt
@jwt.decode_key_loader
def decode_key_loader(claims, jwt_headers):
return convert_cert_to_pem(claims['kid'])
def convert_cert_to_pem(kid):
certificate = get_public_keys(kid)
# This is transformed because google gives pem key form, it has to be loaded to x509 certificate.
cert = x509.load_pem_x509_certificate(certificate.encode())
pub = cert.public_key()
return pub
def get_public_keys(kid=None):
# TODO: these certificates rotates so a cache should be implemented
certificate_url = 'https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com'
response = requests.get(certificate_url, verify=True)
return response.json()[kid]
But now I want to add the authentication to my frontend app and I want to use cookies. Following the docs of flask jwt extended I did this login feature:
@app.route("/login", methods=["POST"])
def login():
email = request.json.get("email")
password = request.json.get("password")
user = fb_auth.sign_in_with_email_and_password(email, password)
id_token = user['idToken']
# access_token = create_access_token(identity=user)
response = jsonify({'token': id_token})
set_access_cookies(response, id_token)
return jsonify({'token': id_token}), 200
When I try to run that code I get the following error:
Traceback (most recent call last):
File "/mnt/d/Projects/api/venv/lib/python3.7/site-packages/flask/app.py", line 2528, in wsgi_app
response = self.full_dispatch_request()
File "/mnt/d/Projects/api/venv/lib/python3.7/site-packages/flask/app.py", line 1825, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/mnt/d/Projects/api/venv/lib/python3.7/site-packages/flask_cors/extension.py", line 165, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/mnt/d/Projects/api/venv/lib/python3.7/site-packages/flask/app.py", line 1823, in full_dispatch_request
rv = self.dispatch_request()
File "/mnt/d/Projects/api/venv/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
File "/mnt/d/Projects/api/app/controllers/auth.py", line 30, in login
set_access_cookies(response, id_token)
File "/mnt/d/Projects/api/venv/lib/python3.7/site-packages/flask_jwt_extended/utils.py", line 310, in set_access_cookies
value=get_csrf_token(encoded_access_token),
File "/mnt/d/Projects/api/venv/lib/python3.7/site-packages/flask_jwt_extended/utils.py", line 267, in get_csrf_token
return token["csrf"]
KeyError: 'csrf'
127.0.0.1 - - [13/Mar/2023 15:44:02] "POST /login HTTP/1.1" 500 -
I guess that this is happening because I am not calling the create_access_token function provided by the Flask JWT Extended package and I don't think I should call it given that I already have my jwt working and being validated correctly. I also tried to call that function passing in the user
variable which is a dictionary (checkc the commented line on the login endpoint) but then I got a new error:
RuntimeError: JWT_PRIVATE_KEY must be set to use asymmetric cryptography algorithm "RS256"
I would like to use the JWT issued by the firebase with cookies, but I had no success until now. I'd appreciate it if someone could help me out here. Thanks!