|  | 
|  | 1 | +-- app.settings.jwt_secret has been removed, see https://github.com/orgs/supabase/discussions/30606 | 
|  | 2 | +-- now we fetch the secret from vault. The redeem_access_token function is the same as before | 
|  | 3 | +-- (see file 20230906110845_access_token.sql) except the part where we fetch the jwt_secret. | 
|  | 4 | +create or replace function public.redeem_access_token( | 
|  | 5 | +    access_token text | 
|  | 6 | +) | 
|  | 7 | +    returns text | 
|  | 8 | +    language plpgsql | 
|  | 9 | +    security definer | 
|  | 10 | +    strict | 
|  | 11 | +as $$ | 
|  | 12 | +declare | 
|  | 13 | +    token_id uuid; | 
|  | 14 | +    token bytea; | 
|  | 15 | +    tokens_row app.user_id_and_token_hash; | 
|  | 16 | +    token_valid boolean; | 
|  | 17 | +    now timestamp; | 
|  | 18 | +    one_hour_from_now timestamp; | 
|  | 19 | +    issued_at int; | 
|  | 20 | +    expiry_at int; | 
|  | 21 | +    jwt_secret text; | 
|  | 22 | +begin | 
|  | 23 | +    -- validate access token | 
|  | 24 | +    if length(access_token) != 64 then | 
|  | 25 | +        raise exception 'Invalid token'; | 
|  | 26 | +    end if; | 
|  | 27 | + | 
|  | 28 | +    if substring(access_token from 1 for 4) != 'dbd_' then | 
|  | 29 | +        raise exception 'Invalid token'; | 
|  | 30 | +    end if; | 
|  | 31 | + | 
|  | 32 | +    token_id := substring(access_token from 5 for 32)::uuid; | 
|  | 33 | +    token := app.base64url_decode(substring(access_token from 37)); | 
|  | 34 | + | 
|  | 35 | +    select t.user_id, t.token_hash | 
|  | 36 | +    into tokens_row | 
|  | 37 | +    from app.access_tokens t | 
|  | 38 | +    where t.id = token_id; | 
|  | 39 | + | 
|  | 40 | +    -- TODO: do a constant time comparison | 
|  | 41 | +    if tokens_row.token_hash != sha256(token) then | 
|  | 42 | +        raise exception 'Invalid token'; | 
|  | 43 | +    end if; | 
|  | 44 | + | 
|  | 45 | +    -- Generate JWT token | 
|  | 46 | +    now := current_timestamp; | 
|  | 47 | +    one_hour_from_now := now + interval '1 hour'; | 
|  | 48 | +    issued_at := date_part('epoch', now); | 
|  | 49 | +    expiry_at := date_part('epoch', one_hour_from_now); | 
|  | 50 | + | 
|  | 51 | +    -- read the jwt secret from vault | 
|  | 52 | +    select decrypted_secret | 
|  | 53 | +    into jwt_secret | 
|  | 54 | +    from vault.decrypted_secrets | 
|  | 55 | +    where name = 'app.jwt_secret'; | 
|  | 56 | + | 
|  | 57 | +    return sign(json_build_object( | 
|  | 58 | +        'aud', 'authenticated', | 
|  | 59 | +        'role', 'authenticated', | 
|  | 60 | +        'iss', 'database.dev', | 
|  | 61 | +        'sub', tokens_row.user_id, | 
|  | 62 | +        'iat', issued_at, | 
|  | 63 | +        'exp', expiry_at | 
|  | 64 | +    ), jwt_secret); | 
|  | 65 | +end; | 
|  | 66 | +$$; | 
0 commit comments