Skip to content

Instantly share code, notes, and snippets.

@AksAman
Created December 22, 2023 12:59
Show Gist options
  • Select an option

  • Save AksAman/8cbb9c80f320a2aac98faa61661cdec4 to your computer and use it in GitHub Desktop.

Select an option

Save AksAman/8cbb9c80f320a2aac98faa61661cdec4 to your computer and use it in GitHub Desktop.
Verify Next Auth JWT on python based backends
import json
import os
import time
from typing import Any
from Crypto.Protocol.KDF import HKDF # pip install pycryptodome cryptography
from Crypto.Hash import SHA256
from jose import jwe # pip install python-jose
from dataclasses import dataclass, field
DEFAULT_NEXT_AUTH_CONTEXT = "NextAuth.js Generated Encryption Key"
@dataclass
class NextAuthVerifier:
next_auth_secret: str | None = field(
default_factory=lambda: os.getenv("NEXTAUTH_SECRET")
)
context: str = field(default=str.encode(DEFAULT_NEXT_AUTH_CONTEXT))
key_len: int = field(default=32)
def __get_derived_key__(self) -> bytes:
# Think about including the context in your environment variables.
return HKDF(
master=self.next_auth_secret.encode(),
key_len=self.key_len,
salt="".encode(),
hashmod=SHA256,
num_keys=1,
context=self.context,
)
def decrypt(self, token: str) -> dict[str, Any] | None:
try:
key = self.__get_derived_key__()
raw_payload = jwe.decrypt(jwe_str=token, key=key).decode()
return json.loads(raw_payload)
except Exception as e:
# can replace this with your own error handling
print(e)
return None
def is_expired(self, payload: dict[str, Any]) -> bool:
exp = payload.get("exp")
if not exp:
raise ValueError("exp not found in payload")
return time.time() > exp
# usage
if __name__ == "__main__":
decrypter = NextAuthVerifier(secret=os.getenv("NEXTAUTH_SECRET"))
token = "eyJhbGciOiJkaXIiLsadadsOiJBMjU2R0NNIn0...." # can be from request.headers["Authorization"]
payload = decrypter.decrypt(token=token)
print(payload)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment