supabase / auth

A JWT based API for managing users and issuing JWT tokens
https://supabase.com/docs/guides/auth
MIT License
1.5k stars 366 forks source link

minting custom JWTs #277

Closed awalias closed 2 years ago

awalias commented 2 years ago

as discussed here: https://github.com/supabase/supabase/discussions/3899#discussioncomment-1645752

it would be good to have an admin endpoint that can mint tokens with custom claims. This is mainly a convenience function so that the user doesn't need to fetch the jwt_secret from supabase, or swap it out if it's rolled. Would increase usability, and more and more users are asking for advice on how to do this: a simple method/end-point would make the DX much nicer

I want to send a body:

{
  'sub': 'abc',
  'custom-claim-1': 'xyz',
  'foo': 'bar',
  'role': 'authenticated'
}

gotrue might simply sign and return the access_token

potential issues:

another option would be to have a more integrated approach:

mstade commented 2 years ago

I feel like I should provide some context and color to the above, since the issue originated from a comment of mine. We basically have two use cases for minting specific JWT tokens:

  1. Signing in – i.e. authenticating with our application and issuing both access and refresh tokens, such that the client can stay logged in
  2. Performing an action on behalf of another user – e.g. an admin or support user needs to do something on behalf of another user – in which case only an access token is necessary

In the case of (1), it's the same as if you'd just use the signIn() method, but in the case of (2) the need for blacklisting/revocation might be more relevant.

The way we solve this today is by creating the tokens as necessary in an identity provider we've deployed ourselves, using the JWT secret as given by Supabase. In order to use the identity provider, you must be a registered client, which essentially also equates to a user in Supabase, albeit with different profile metadata than a human user. The main issues we have with this are:

  1. We can't easily change the JWT secret if its compromised
  2. We can't automatically roll the JWT secret on a regular basis
  3. We don't get any meaningful audit logs for "regular" users

With an official minting function these could potentially all be remedied, since then Supabase could deal with things like audit logging, JWT secret rolling etc.

I am conflicted about all this though. On the one hand, it would be a pretty flexible solution to allow developers using the Supabase platform to implement almost any custom auth solution, or hook into their existing auth infrastructure. On the other hand, I can't help but feel it seems like a workaround more than a solution. It's a bit hard to put into words without writing an essay, but really what we'd like the ability to do one of:

  1. Hook into/override the interactions in the authentication flow, such that login/consent/etc can be completely custom
  2. Just point Supabase to any compliant OpenID Connect/OAuth2/SAML identity provider of our choice, rather than big tech providers like Google, Apple, Facebook etc. – e.g. a generic OIDC adapter that you just point to the /.well-known/openid-configuration endpoint of the provider

It's a bit unfortunate also that the only way to sign JWTs is by secret, rather than a public/private key pair which is typically a recommended practice. Obviously a key pair isn't any safer if the private key is leaked, but at least you don't need a secret to verify tokens then, which is the case with simple HMAC signing.

mstade commented 2 years ago

If there is a function to create custom access tokens and/or sign in on behalf of another user, then it should be protected such that only whitelisted users of the system may call it. They should probably also be restricted to which claims they can set on the token (if any) and for which users they may generate tokens. This sort of implies a kind of role/attribute based authorization scheme for this purpose, which doesn't really exist today does it?

A user probably shouldn't be able to create a new access token for themselves – it'd defeat the purpose of refresh tokens and would enable anyone who happens to get ahold of an access token to keep refreshing that in perpetuity.

I dunno, it seems this kind of feature can easily balloon into something unwieldy to be honest. It might be a decent workaround for our use case, but as a generic feature I'm not so sure.

hf commented 2 years ago

We're not planning to officially support minting of custom JWTs at this point. If you want to do it today, you have to use the long-winded way of signing with the JWT secret, at your own risk.

In the next major version of GoTrue we are going to be adding support for asymmetric JWTs and at that point we'll likely provide an admin API endpoint which will enable you to mint JWT tokens safely.

mstade commented 2 years ago

@hf will the asymmetric JWT work also mean there will be a JWKS endpoint? Is there more information about this work you could link to? Plenty of questions around key generation, rotation, storage etc. 😅

hf commented 2 years ago

@hf will the asymmetric JWT work also mean there will be a JWKS endpoint? Is there more information about this work you could link to? Plenty of questions around key generation, rotation, storage etc. 😅

Yes, there will be a JWKS and OIDC endpoint. It's a giant piece of work on our side and the document is unfortunately internal only at this point. Work on it has been deprioritized at this time as we are working on MFA and SAML support.

It is an important feature for us, and we'll probably update this issue with more information on timelines when we start planning for it again.