Search code examples
amazon-web-servicesaws-lambdajwtamazon-cognito

How to validate IdToken/AccessToken from AWS Cognito inside lambda function


I tried to create lambda function which is accessible through lambda function url and want to perform my own validation. the flow more or less will be like this

flow expected

For the first Lambda function (to generate token) it is working fine using user pool and boto3 library

For the 2nd part of lambda function, I am planning to use sample from https://github.com/awslabs/aws-support-tools/blob/master/Cognito/decode-verify-jwt/decode-verify-jwt.py However I got stuck in importing jwk and jwt from jose

so here's step I take :

  • Create lambda layer which install boto3 (latest version) and python-jose[cryptography]
  • Attach the layer
  • execute lambda function

here's the snippet of the function where it got failed :

import json
import boto3
import traceback
import sys
import time
import hashlib
import base64

from botocore.exceptions import ClientError
from jose import jwt
from jose.utils import base64url_decode



# Bedrock Runtime client used to invoke and question the models
bedrock_runtime = boto3.client(
    service_name='bedrock-runtime', 
    region_name='us-east-1'
)

the error I got :

e 690, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 940, in exec_module
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/var/task/lambda_function.py", line 10, in <module>
from jose import jwt
File "/opt/python/jose/jwt.py", line 6, in <module>
from jose import jws
File "/opt/python/jose/jws.py", line 5, in <module>
from jose import jwk
File "/opt/python/jose/jwk.py", line 1, in <module>
from jose.backends.base import Key
File "/opt/python/jose/backends/__init__.py", line 2, in <module>
from jose.backends.cryptography_backend import get_random_bytes  # noqa: F401
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/python/jose/backends/cryptography_backend.py", line 4, in <module>
from cryptography.exceptions import InvalidSignature, InvalidTag
File "/opt/python/cryptography/exceptions.py", line 9, in <module>
from cryptography.hazmat.bindings._rust import exceptions as rust_exceptions
pyo3_runtime.PanicException: Python API call failed
INIT_REPORT Init Duration: 675.07 ms    Phase: init Status: error   Error Type: Runtime.ExitError
ModuleNotFoundError: No module named '_cffi_backend'
thread '<unnamed>' panicked at /github/home/.cargo/registry/src/index.crates.io-6f17d22bba15001f/pyo3-0.18.3/src/err/mod.rs:790:5:
Python API call failed
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Traceback (most recent call last):
File "/var/runtime/bootstrap.py", line 63, in <module>
main()
File "/var/runtime/bootstrap.py", line 60, in main
awslambdaricmain.main([os.environ["LAMBDA_TASK_ROOT"], os.environ["_HANDLER"]])
File "/var/lang/lib/python3.11/site-packages/awslambdaric/__main__.py", line 21, in main
bootstrap.run(app_root, handler, lambda_runtime_api_addr)
File "/var/lang/lib/python3.11/site-packages/awslambdaric/bootstrap.py", line 472, in run
request_handler = _get_handler(handler)
^^^^^^^^^^^^^^^^^^^^^
File "/var/lang/lib/python3.11/site-packages/awslambdaric/bootstrap.py", line 53, in _get_handler
m = importlib.import_module(modname.replace("/", "."))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/var/lang/lib/python3.11/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen importlib._bootstrap>", line 1204, in _gcd_import
File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 940, in exec_module
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/var/task/lambda_function.py", line 10, in <module>
from jose import jwt
File "/opt/python/jose/jwt.py", line 6, in <module>
from jose import jws
File "/opt/python/jose/jws.py", line 5, in <module>
from jose import jwk
File "/opt/python/jose/jwk.py", line 1, in <module>
from jose.backends.base import Key
File "/opt/python/jose/backends/__init__.py", line 2, in <module>
from jose.backends.cryptography_backend import get_random_bytes  # noqa: F401
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/python/jose/backends/cryptography_backend.py", line 4, in <module>
from cryptography.exceptions import InvalidSignature, InvalidTag
File "/opt/python/cryptography/exceptions.py", line 9, in <module>
from cryptography.hazmat.bindings._rust import exceptions as rust_exceptions
pyo3_runtime.PanicException: Python API call failed

any idea what is the cause?

or is there any alternative i can use to validate cognito token in lambda function?

Thanks


Solution

  • This issue is due to Python version mismatch on the lambda function and the layer itself.

    Layer is created directly using AWS cloudshell which utilize Python 3.7 at this moment while the lambda function is on Python 3.11.

    To help as future reference when creating layer :

    • use linux to create the venv for the layer
    • use same python version for layer and function to avoid confusion

    Hope this help future AWS user which might still a newbie like me