diff --git a/internal/db/start/start.go b/internal/db/start/start.go index 7febc9294..344227040 100644 --- a/internal/db/start/start.go +++ b/internal/db/start/start.go @@ -272,7 +272,7 @@ func InitSchema14(ctx context.Context, conn *pgx.Conn) error { return file.ExecBatch(ctx, conn) } -func initRealtimeJob(host string) utils.DockerJob { +func initRealtimeJob(host, jwks string) utils.DockerJob { return utils.DockerJob{ Image: utils.Config.Realtime.Image, Env: []string{ @@ -284,6 +284,7 @@ func initRealtimeJob(host string) utils.DockerJob { "DB_NAME=postgres", "DB_AFTER_CONNECT_QUERY=SET search_path TO _realtime", "DB_ENC_KEY=" + utils.Config.Realtime.EncryptionKey, + fmt.Sprintf("API_JWT_JWKS=%s", jwks), "API_JWT_SECRET=" + utils.Config.Auth.JwtSecret.Value, "METRICS_JWT_SECRET=" + utils.Config.Auth.JwtSecret.Value, "APP_NAME=realtime", @@ -341,7 +342,11 @@ func initSchema15(ctx context.Context, host string) error { // Apply service migrations var initJobs []utils.DockerJob if utils.Config.Realtime.Enabled { - initJobs = append(initJobs, initRealtimeJob(host)) + jwks, err := utils.Config.Auth.ResolveJWKS(context.Background()) + if err != nil { + return err + } + initJobs = append(initJobs, initRealtimeJob(host, jwks)) } if utils.Config.Storage.Enabled { initJobs = append(initJobs, initStorageJob(host)) diff --git a/internal/start/start.go b/internal/start/start.go index 5e07d9dd1..c1a57293f 100644 --- a/internal/start/start.go +++ b/internal/start/start.go @@ -87,6 +87,7 @@ type kongConfig struct { ApiHost string ApiPort uint16 BearerToken string + QueryToken string } var ( @@ -145,7 +146,7 @@ func run(ctx context.Context, fsys afero.Fs, excludedContainers []string, dbConf excluded[name] = true } - jwks, err := utils.Config.Auth.ResolveJWKS(ctx, fsys) + jwks, err := utils.Config.Auth.ResolveJWKS(ctx) if err != nil { return err } @@ -362,6 +363,13 @@ EOF utils.Config.Auth.PublishableKey.Value, utils.Config.Auth.AnonKey.Value, ), + QueryToken: fmt.Sprintf( + `$((function() return (query_params.apikey == '%s' and '%s') or (query_params.apikey == '%s' and '%s') or query_params.apikey end)())`, + utils.Config.Auth.SecretKey.Value, + utils.Config.Auth.ServiceRoleKey.Value, + utils.Config.Auth.PublishableKey.Value, + utils.Config.Auth.AnonKey.Value, + ), }); err != nil { return errors.Errorf("failed to exec template: %w", err) } diff --git a/internal/start/templates/kong.yml b/internal/start/templates/kong.yml index fb76e42ea..21489ce08 100644 --- a/internal/start/templates/kong.yml +++ b/internal/start/templates/kong.yml @@ -132,9 +132,9 @@ services: - name: request-transformer config: replace: - headers: - - "Authorization: {{ .BearerToken }}" - - name: realtime-v1-longpoll + querystring: + - "apikey:{{ .QueryToken }}" + - name: realtime-v1-longpoll-not-working _comment: "Realtime: /realtime/v1/* -> ws://realtime:4000/socket/longpoll" url: http://{{ .RealtimeId }}:4000/socket protocol: http diff --git a/pkg/config/config.go b/pkg/config/config.go index d21f1847c..ea49a76ca 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -28,7 +28,6 @@ import ( "github.com/go-errors/errors" "github.com/go-viper/mapstructure/v2" "github.com/joho/godotenv" - "github.com/spf13/afero" "github.com/spf13/viper" "github.com/supabase/cli/pkg/cast" "github.com/supabase/cli/pkg/fetcher" @@ -1428,7 +1427,7 @@ type ( // ResolveJWKS creates the JWKS from the JWT secret and Third-Party Auth // configs by resolving the JWKS via the OIDC discovery URL. // It always returns a JWKS string, except when there's an error fetching. -func (a *auth) ResolveJWKS(ctx context.Context, fsys afero.Fs) (string, error) { +func (a *auth) ResolveJWKS(ctx context.Context) (string, error) { var jwks remoteJWKS if issuerURL := a.ThirdParty.IssuerURL(); issuerURL != "" {