• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / storage / 30945555404

04 Aug 2026 07:56PM UTC coverage: 80.435% (-0.09%) from 80.524%
30945555404

push

github

web-flow
fix: make sync possible hooks to be sync (#1298)

Signed-off-by: ferhat elmas <elmas.ferhat@gmail.com>

5630 of 7518 branches covered (74.89%)

Branch coverage included in aggregate %.

23 of 25 new or added lines in 5 files covered. (92.0%)

18 existing lines in 2 files now uncovered.

10609 of 12671 relevant lines covered (83.73%)

434.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.97
/src/http/plugins/jwt.ts
1
import { verifyJWT, verifyJWTWithCache } from '@internal/auth'
2
import { getJwtSecret } from '@internal/database'
3
import { ERRORS } from '@internal/errors'
4
import { FastifyInstance } from 'fastify'
5
import fastifyPlugin from 'fastify-plugin'
6
import { JWTPayload } from 'jose'
7
import { getConfig } from '../../config'
8

9
declare module 'fastify' {
10
  interface FastifyRequest {
11
    isAuthenticated: boolean
12
    jwt: string
13
    jwtPayload?: JWTPayload & { role?: string }
14
    owner?: string
15
  }
16

17
  interface FastifyContextConfig {
18
    allowInvalidJwt?: boolean
19
  }
20
}
21

22
interface JWTPluginOptions {
23
  enforceJwtRoles?: string[]
24
  skipIfAlreadyAuthenticated?: boolean
25
}
26

27
const { jwtCachingEnabled } = getConfig()
41✔
28

29
const BEARER = /^Bearer\s+/i
41✔
30

31
const jwtPlugin = fastifyPlugin<JWTPluginOptions>(
41✔
32
  async (fastify, opts) => {
33
    fastify.decorateRequest('jwt', '')
2,369✔
34
    fastify.decorateRequest('jwtPayload', undefined)
2,369✔
35

36
    fastify.addHook('preHandler', async (request) => {
2,369✔
37
      if (opts.skipIfAlreadyAuthenticated && request.isAuthenticated && request.jwtPayload) {
835!
38
        return
×
39
      }
40

41
      request.jwt = (request.headers.authorization || '').replace(BEARER, '')
835✔
42

43
      if (!request.jwt && request.routeOptions.config.allowInvalidJwt) {
835✔
44
        request.jwtPayload = { role: 'anon' }
4✔
45
        request.isAuthenticated = false
4✔
46
        return
4✔
47
      }
48

49
      const { secret, jwks } = await getJwtSecret(request.tenantId)
831✔
50

51
      try {
831✔
52
        const payload = await (jwtCachingEnabled
831!
53
          ? verifyJWTWithCache(request.jwt, secret, jwks || null)
×
54
          : verifyJWT(request.jwt, secret, jwks || null))
831!
55

56
        request.jwtPayload = payload
831✔
57
        request.owner = payload.sub
831✔
58
        request.isAuthenticated = true
831✔
59
      } catch (e) {
60
        request.jwtPayload = { role: 'anon' }
×
61
        request.isAuthenticated = false
×
62

63
        if (request.routeOptions.config.allowInvalidJwt) {
×
64
          return
×
65
        }
66
        const err = e as Error
×
67
        throw ERRORS.AccessDenied(err.message, err)
×
68
      }
69
    })
70

71
    if (opts.enforceJwtRoles && opts.enforceJwtRoles.length > 0) {
2,369✔
72
      fastify.register(enforceJwtRole, {
591✔
73
        roles: opts.enforceJwtRoles,
74
      })
75
    }
76
  },
77
  { name: 'auth-jwt' }
78
)
79

80
interface EnforceJWTRoleOptions {
81
  roles: string[]
82
}
83

84
export const enforceJwtRole = fastifyPlugin<EnforceJWTRoleOptions>(
41✔
85
  async (fastify, opts) => {
86
    fastify.addHook('preHandler', (request, _reply, done) => {
885✔
87
      if (!request.isAuthenticated) {
185!
NEW
88
        done(ERRORS.AccessDenied('Access denied: JWT is not authenticated').withStatusCode(403))
×
NEW
89
        return
×
90
      }
91

92
      const hasRoles = request.jwtPayload?.role && opts.roles.includes(request.jwtPayload.role)
185✔
93

94
      if (!hasRoles) {
185✔
95
        done(ERRORS.AccessDenied(`Access denied: Invalid role`).withStatusCode(403))
3✔
96
        return
3✔
97
      }
98

99
      done()
182✔
100
    })
101
  },
102
  { name: 'allow-invalid-jwt' }
103
)
104

105
export function registerJwtAuth(fastify: FastifyInstance, opts: JWTPluginOptions = {}) {
2,369✔
106
  fastify.addHook('onRoute', (routeOptions) => {
2,369✔
107
    routeOptions.schema = routeOptions.schema || {}
21,869!
108
    routeOptions.schema.security = [{ bearerAuth: [] }]
21,869✔
109
  })
110
  fastify.register(jwtPlugin, opts)
2,369✔
111
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc