[GH-ISSUE #70] Supabase issues #562

Closed
opened 2026-04-16 11:07:07 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @maelp on GitHub (Apr 8, 2025).
Original GitHub issue: https://github.com/Dokploy/templates/issues/70

Seems that at https://github.com/Dokploy/templates/blob/main/blueprints/supabase/template.toml#L30 we look for JWT_EXP but the env var seems to be defined as JWT_EXPIRY(?) https://github.com/Dokploy/templates/blob/main/blueprints/supabase/template.toml#L30

Also it's weird that the ANON_KEY and SERVICE_KEY are hard-coded? aren't they supposed to be created from the JWT_SECRET using something like

#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.12"
# dependencies = [
#     "click",
#     "pyjwt",
# ]
# ///

import base64
import click
import jwt
import time
from datetime import timedelta
from jwt import InvalidTokenError


@click.command()
@click.argument("b64_key")
def generate_tokens(b64_key):
    """
    Generate ANON_KEY and SERVICE_KEY using a base64-encoded secret key,
    and validate them to ensure correctness.
    """
    try:
        signing_key = b64_key  # base64.b64decode(b64_key, validate=True)
    except Exception as e:
        click.echo(f"❌ Invalid base64 key: {e}")
        return

    now = int(time.time())
    future = now + int(timedelta(days=365.25 * 100).total_seconds())  # 1000 years

    def make_token(role: str) -> str:
        payload = {"role": role, "iss": "supabase", "iat": now, "exp": future}
        headers = {"alg": "HS256", "typ": "JWT"}
        return jwt.encode(payload, signing_key, algorithm="HS256", headers=headers)

    def validate_token(token: str, role: str):
        try:
            decoded = jwt.decode(token, signing_key, algorithms=["HS256"])
            if decoded["role"] == role and decoded["iss"] == "supabase":
                click.echo(f"✅ {role.upper()} token is valid")
            else:
                click.echo(f"⚠️  {role.upper()} token decoded but payload mismatch")
        except InvalidTokenError as e:
            click.echo(f"❌ {role.upper()} token is invalid: {e}")

    anon_token = make_token("anon")
    service_token = make_token("service_role")

    click.echo("\nGenerated tokens:")
    click.echo(f"ANON_KEY = {anon_token}")
    click.echo(f"SERVICE_KEY = {service_token}")

    click.echo("\nValidating tokens...")
    validate_token(anon_token, "anon")
    validate_token(service_token, "service_role")


if __name__ == "__main__":
    generate_tokens()
Originally created by @maelp on GitHub (Apr 8, 2025). Original GitHub issue: https://github.com/Dokploy/templates/issues/70 Seems that at https://github.com/Dokploy/templates/blob/main/blueprints/supabase/template.toml#L30 we look for JWT_EXP but the env var seems to be defined as JWT_EXPIRY(?) https://github.com/Dokploy/templates/blob/main/blueprints/supabase/template.toml#L30 Also it's weird that the ANON_KEY and SERVICE_KEY are hard-coded? aren't they supposed to be created from the JWT_SECRET using something like ```py #!/usr/bin/env -S uv run --script # /// script # requires-python = ">=3.12" # dependencies = [ # "click", # "pyjwt", # ] # /// import base64 import click import jwt import time from datetime import timedelta from jwt import InvalidTokenError @click.command() @click.argument("b64_key") def generate_tokens(b64_key): """ Generate ANON_KEY and SERVICE_KEY using a base64-encoded secret key, and validate them to ensure correctness. """ try: signing_key = b64_key # base64.b64decode(b64_key, validate=True) except Exception as e: click.echo(f"❌ Invalid base64 key: {e}") return now = int(time.time()) future = now + int(timedelta(days=365.25 * 100).total_seconds()) # 1000 years def make_token(role: str) -> str: payload = {"role": role, "iss": "supabase", "iat": now, "exp": future} headers = {"alg": "HS256", "typ": "JWT"} return jwt.encode(payload, signing_key, algorithm="HS256", headers=headers) def validate_token(token: str, role: str): try: decoded = jwt.decode(token, signing_key, algorithms=["HS256"]) if decoded["role"] == role and decoded["iss"] == "supabase": click.echo(f"✅ {role.upper()} token is valid") else: click.echo(f"⚠️ {role.upper()} token decoded but payload mismatch") except InvalidTokenError as e: click.echo(f"❌ {role.upper()} token is invalid: {e}") anon_token = make_token("anon") service_token = make_token("service_role") click.echo("\nGenerated tokens:") click.echo(f"ANON_KEY = {anon_token}") click.echo(f"SERVICE_KEY = {service_token}") click.echo("\nValidating tokens...") validate_token(anon_token, "anon") validate_token(service_token, "service_role") if __name__ == "__main__": generate_tokens() ```
Author
Owner

@Siumauricio commented on GitHub (Jun 1, 2025):

Recently a new template was implemented, and the old template was corrected, you can try it and check if you still have this problem.

So let's close this for now

<!-- gh-comment-id:2927920393 --> @Siumauricio commented on GitHub (Jun 1, 2025): Recently a new template was implemented, and the old template was corrected, you can try it and check if you still have this problem. So let's close this for now
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/templates#562