Update (19th December 2024): Asymmetric Keys will not be released in Q4 2024 because it needs further development work. We will finalize the timeline and announce the updated timeline in Q1 2025.
Update (2nd October 2024): We have decided to push back the launch from 7th October 2024 to Q4 2024 to roll this out meticulously; we want to perform exhaustive security checks and spend more time dogfooding internally.
Asymmetric key changelog
Introduction
We are introducing asymmetric key cryptography to Supabase Auth in Q4 2024 on 7th October 2024. This will be provided as an additional option to the JWT secret currently shown in the JWT settings page.
Why are we doing this?
Supabase Auth has always been using a symmetric secret (known as the JWT secret) for signing and verifying JWTs. While this is simple and convenient (since the same secret is used for both signing and verifying), it presents the following problems:
- Extra network request required to verify the user’s JWT with the symmetric secret. Currently, one needs to make a request to Supabase Auth in order to verify the user’s JWT or copy the JWT secret into their environment. While the latter suggestion improves performance, it can result in security implications if the secret is accidentally leaked, which requires all your keys to be rolled.
- Difficult to roll with zero downtime. Since the symmetric secret cannot be shared publicly, developers need to wrangle with rolling the secret across their environments while ensuring that the new secret is used.
Benefits of using asymmetric keys
Asymmetric keys rely on public / private key cryptography, which means that the private key is only used for signing, while the public key is only used for verifying. This solves the above problems in the following way:
- Usage of asymmetric key cryptography rather than a shared symmetric secret for signing and verifying JWTs. Since asymmetric keys don’t use a shared secret, there is less risk of the secret being leaked.
- Faster JWT verification times since there’s no need to make a network call to Supabase Auth via
getUser()
. The public key can be used for verifying the JWT. Note that adding the symmetric secret to your server-side environment to verify the JWT also has the same effect but is potentially less secure since there is an increased risk of the secret being leaked if it is used in multiple applications. - Zero-downtime key rotation. Public keys can be exposed in a JSON Web Key Set (JWKs) format, which allows any one of them to be used for verification. When the asymmetric key is rotated, we can still keep the previously used public key in the JWKs endpoint to verify existing JWTs. New JWTs will be signed by the new asymmetric key.
These will include the following changes:
- A public JWKs endpoint for retrieving the public JWK to verify JWTs. This will be exposed through the
https://<project_ref>.supabase.co/auth/v1/.well-known/jwks.json
endpoint. The symmetric secret will not be exposed through this endpoint for security reasons. - A new method called
getClaims()
, which handles verifying the JWT and returning the claims in it. - Ability to download the public keys in different formats through the dashboard (e.g. PEM, JWKs).
Migration to Asymmetric JWTs
New projects that are created after 1st May 2025 will be created with an RSA asymmetric key by default. Existing projects can choose to start using asymmetric keys by doing the following:
- Ensure that you are using the new API keys.
- Update all your clients to use at least supabase-js version x.x.x (the version number will be updated closer to the release date). In this version, we are introducing a new method called
getClaims
which handles verifying both symmetric and asymmetric JWTs:-
Example successful response payload for
getClaims()
_29{_29"data": {_29"iss": "https://projectref.supabase.co",_29"sub": "565dafb5-fd66-4274-9c37-f0ff720f5637",_29"aud": "authenticated",_29"exp": 1824717902,_29"iat": 1724717902,_29"email": "foo@example.com",_29"phone": "",_29"app_metadata": {_29"provider": "email",_29"providers": ["email"]_29},_29"user_metadata": {_29..._29},_29"role": "authenticated",_29"aal": "aal1",_29"amr": [_29{_29"method": "oauth",_29"timestamp": 1724717902_29}_29],_29"session_id": "479c1cbf-bd52-42d4-894f-1519f39b3241",_29"is_anonymous": false_29},_29"error": null_29} -
Using
getClaims()
to verify the JWT_13import { createClient } from 'supabase/supabase-js'_13_13const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)_13_13// previously, using getUser() requires making an_13// additional network request to Supabase Auth to verify the JWT_13//_13// const { data, error } = await supabase.auth.getUser()_13_13// getClaims() will always return the JWT payload if the JWT is verified_13// If it's an asymmetric JWT, getClaims() will verify using the JWKs endpoint._13// If it's a symmetric JWT, getClaims() calls getUser() to verify the JWT._13const { data, error } = await supabase.auth.getClaims(jwks)
-
- Create an asymmetric key through the dashboard. At this point the symmetric JWT moves to a
Previously Used
state. Existing JWTs signed with the symmetric JWT continue to be valid, but new JWTs are signed via the asymmetric JWT. Note: The UI mockup below is subjected to change and is just meant to illustrate the different possible states of a signing key.
- After the JWT expiry period, you can safely revoke the “Previously Used” symmetric JWT, since new JWTs will now be signed with the asymmetric key.
Frequently Asked Questions
- What do I need to do before I can start using asymmetric keys in Supabase Auth?
- See migration section above for the detailed steps
- Can I create a symmetric key after I create an asymmetric key?
- Yes. You will still be able to create a new symmetric key under the JWT settings page in the dashboard. New projects will be created with an asymmetric key by default on 1st May 2025.
- Will the private asymmetric key be exposed?
- No. Only the public keys will be exposed in various formats (e.g. PEM, JWKs) since those are needed for verification.
- Will I be able to bring my own private key?
- Yes, you can bring your own private key as long as it complies with the key types allowed.
- What key types can I use to create asymmetric JWTs?
- By default, asymmetric keys will be created with RS256 by default. You can optionally choose to use ECC or Ed25519. ECC keys are more performant, but not as widely supported as RS256. You can also fallback to HS256 (symmetric keys).