JWKS Endpoint Returns Empty Key Set for Local Supabase
Bug report
- [x] I confirm this is a bug with Supabase, not with my own application.
- [x] I confirm I have searched the Docs, GitHub Discussions, and Discord.
Describe the bug
When following the guide to verify a jwt key https://supabase.com/docs/guides/auth/jwts#verifying-a-jwt-from-supabase on the local Supabase instance (https://127.0.0.1:8000/auth/v1/.well-known/jwks.json) the result is:
{
"keys": []
}
Running supabase status will display the publishable and secret keys.
This does work on the cloud Supabase instance, the issue is only affecting local dev.
To Reproduce
Steps to reproduce the behavior, please provide code snippets or a repository:
- Run
supabase start - Go to
/auth/v1/.well-known/jwks.json - See empty keys array
Expected behavior
Public key should be returned.
System information
- Version of supabase cli: 2.63.1
Additional context
/auth/v1/.well-known/jwks.json works on hosted Supabase.
can i work on this issue
I'm guessing you haven't added signing key in config.toml.
- You will have to generate a new signing key using the command in this guide: https://supabase.com/docs/guides/auth/signing-keys#how-to-create-mint-jwts-if-access-to-the-private-key-or-shared-secret-is-not-possible
- Save the key in a file and add the path in config.toml (
signing_keys_pathfield is already present in config.toml, you just need to uncomment it and update the signing key file path if necessary)[auth] signing_keys_path = "./signing_key.json"
Restart and now you should get a public key when you visit https://127.0.0.1:8000/auth/v1/.well-known/jwks.json
Yes I figured it out after a lot of searching. This should be automated as it breaks the local dev experience
On Mon, Dec 1, 2025 at 21:16 Inder Singh @.***> wrote:
singh-inder left a comment (supabase/cli#4614) https://github.com/supabase/cli/issues/4614#issuecomment-3646715877
I'm guessing you haven't added signing_keys_path in config.toml.
- You will have to generate a new signing key using the command in this guide: https://supabase.com/docs/guides/auth/signing-keys#how-to-create-mint-jwts-if-access-to-the-private-key-or-shared-secret-is-not-possible
- Save the key in a file and add the path in config.toml ( signing_keys_path field is already present in config.toml, you just need to uncomment it and update the signing key file path if necessary)
[auth]signing_keys_path = "./signing_key.json"
Restart and now you should get a public key when you visit https://127.0.0.1:8000/auth/v1/.well-known/jwks.json
— Reply to this email directly, view it on GitHub https://github.com/supabase/cli/issues/4614#issuecomment-3646715877, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGJQUBJOD37QGGV2XICDDL37Q5SRAVCNFSM6AAAAACNSZBKF6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTKOJWGUYDENRZGA . You are receiving this because you authored the thread.Message ID: @.***>
@whollacsek Sir, I have made improvements and would like to continue working on this. Could you please assign the issue to me?
@sweatybridge
Moving to cli repo. We can look into generating a signing key by default.
I'm guessing you haven't added signing key in config.toml.
- You will have to generate a new signing key using the command in this guide: https://supabase.com/docs/guides/auth/signing-keys#how-to-create-mint-jwts-if-access-to-the-private-key-or-shared-secret-is-not-possible
- Save the key in a file and add the path in config.toml (
signing_keys_pathfield is already present in config.toml, you just need to uncomment it and update the signing key file path if necessary) [auth] signing_keys_path = "./signing_key.json"Restart and now you should get a public key when you visit
https://127.0.0.1:8000/auth/v1/.well-known/jwks.json
@singh-inder @kallebysantos if I check this in and I use the config as code to control my hosted Supabase, will this impact the configuration on my Supabase project?
I am looking for a way to only set the 'custom' private key locally so I have the same behaviour locally but let the Supabase project manage the key for me.
minor thing on the above which I guess @sweatybridge will look into is that the cli produces 1 key (i.e. a JSON dictionary) but a key file (the signing_key.json) should be an array.
below is the current message which is a bit misleading:
{ .... the produced key }
To enable JWT signing keys in your local project:
1. Save the generated key to supabase/signing_key.json
2. Update your supabase/config.toml with the new keys path
[auth]
signing_keys_path = "./signing_key.json"
I'm guessing you haven't added signing key in config.toml.
- You will have to generate a new signing key using the command in this guide: https://supabase.com/docs/guides/auth/signing-keys#how-to-create-mint-jwts-if-access-to-the-private-key-or-shared-secret-is-not-possible
- Save the key in a file and add the path in config.toml (
signing_keys_pathfield is already present in config.toml, you just need to uncomment it and update the signing key file path if necessary) [auth] signing_keys_path = "./signing_key.json"Restart and now you should get a public key when you visit
https://127.0.0.1:8000/auth/v1/.well-known/jwks.json@singh-inder @kallebysantos if I check this in and I use the config as code to control my hosted Supabase, will this impact the configuration on my Supabase project?
I am looking for a way to only set the 'custom' private key locally so I have the same behaviour locally but let the Supabase project manage the key for me.
the answer is yes and I worked around with setting it to empty string using branches:
[remotes.staging.auth]
signing_keys_path = ""
@sweatybridge think it would be a good idea to allow to create a local branch, or create 'reserved' keyword for the branch, so that one could set up local environment definitions. as it stands we have to set up for local by default and override per environment. let me know if you'd like me to create a ticket with that suggestion.
This whole situation could be avoided if the local dev instance simply generate it's own dummy key like what is already the case with the secret key and anon key. We shouldn't be expected to run a separate command for local dev to work.
On Tue, Jan 6, 2026 at 04:20 Joel Ramos @.***> wrote:
joelpramos left a comment (supabase/cli#4614) https://github.com/supabase/cli/issues/4614#issuecomment-3711956962
I'm guessing you haven't added signing key in config.toml.
- You will have to generate a new signing key using the command in this guide: https://supabase.com/docs/guides/auth/signing-keys#how-to-create-mint-jwts-if-access-to-the-private-key-or-shared-secret-is-not-possible
- Save the key in a file and add the path in config.toml ( signing_keys_path field is already present in config.toml, you just need to uncomment it and update the signing key file path if necessary) [auth] signing_keys_path = "./signing_key.json"
Restart and now you should get a public key when you visit https://127.0.0.1:8000/auth/v1/.well-known/jwks.json
@singh-inder https://github.com/singh-inder @kallebysantos https://github.com/kallebysantos if I check this in and I use the config as code to control my hosted Supabase, will this impact the configuration on my Supabase project?
I am looking for a way to only set the 'custom' private key locally so I have the same behaviour locally but let the Supabase project manage the key for me.
the answer is yes and I worked around with setting it to empty string using branches:
[remotes.staging.auth] signing_keys_path = ""
@sweatybridge https://github.com/sweatybridge think it would be a good idea to allow to create a local branch, or create 'reserved' keyword for the branch, so that one could set up local environment definitions. as it stands we have to set up for local by default and override per environment. let me know if you'd like me to create a ticket with that suggestion.
— Reply to this email directly, view it on GitHub https://github.com/supabase/cli/issues/4614#issuecomment-3711956962, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGJQUFTRHX2RZFEQUDPACD4FLBRVAVCNFSM6AAAAACO3N5JD6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTOMJRHE2TMOJWGI . You are receiving this because you authored the thread.Message ID: @.***>