Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(supabase-mw): Return tuple from initSupabaseMw to prevent accidental misconfiguration #10687

Merged
merged 1 commit into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/auth-providers/supabase/middleware/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ NOTE: This README needs to be updated when the Supabase Web Auth will create a c
import type { TagDescriptor } from '@redwoodjs/web'

import App from './App'
import createSupabaseAuthMiddleware from '@redwoodjs/auth-supabase-middleware'
import initSupabaseMiddleware from '@redwoodjs/auth-supabase-middleware'
import { Document } from './Document'

import { getCurrentUser } from '$api/src/lib/auth'
Expand All @@ -21,7 +21,7 @@ interface Props {
}

export const registerMiddleware = () => {
const supabaseAuthMiddleware = createSupabaseAuthMiddleware({
const supabaseAuthMiddleware = initSupabaseMiddleware({
// Optional. If not set, Supabase will use its own `currentUser` function
// instead of your app's
getCurrentUser,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
MiddlewareResponse,
} from '@redwoodjs/vite/middleware'

import createSupabaseAuthMiddleware from '../index'
import initSupabaseAuthMiddleware from '../index'
import type { SupabaseAuthMiddlewareOptions } from '../index'
const FIXTURE_PATH = path.resolve(
__dirname,
Expand All @@ -33,8 +33,6 @@ vi.mock('jsonwebtoken', () => {
}
})

// })

vi.mock('@redwoodjs/auth-supabase-api', () => {
return {
authDecoder: vi.fn(() => {
Expand Down Expand Up @@ -75,7 +73,7 @@ const options: SupabaseAuthMiddlewareOptions = {

describe('createSupabaseAuthMiddleware()', () => {
it('creates middleware for Supabase SSR auth', async () => {
const middleware = createSupabaseAuthMiddleware(options)
const [middleware] = initSupabaseAuthMiddleware(options)
const request = new Request('http://localhost:8911', {
method: 'GET',
headers: new Headers(),
Expand All @@ -94,7 +92,7 @@ describe('createSupabaseAuthMiddleware()', () => {
})

it('passes through non-authenticated requests', async () => {
const middleware = createSupabaseAuthMiddleware(options)
const [middleware] = initSupabaseAuthMiddleware(options)
const request = new Request('http://localhost:8911', {
method: 'GET',
headers: new Headers(),
Expand All @@ -104,13 +102,13 @@ describe('createSupabaseAuthMiddleware()', () => {

const result = await middleware(req, res)
expect(result).toEqual(res)
expect(result.body).toEqual('original response body')
expect(result?.body).toEqual('original response body')

const serverAuthState = req.serverAuthState.get()
expect(serverAuthState).toEqual(middlewareDefaultAuthProviderState)
})
it('passes through when no auth-provider cookie', async () => {
const middleware = createSupabaseAuthMiddleware(options)
const [middleware] = initSupabaseAuthMiddleware(options)
const request = new Request('http://localhost:8911', {
method: 'GET',
headers: new Headers({
Expand All @@ -124,14 +122,14 @@ describe('createSupabaseAuthMiddleware()', () => {

const result = await middleware(req, res)
expect(result).toEqual(res)
expect(result.body).toEqual('original response body when no auth provider')
expect(result?.body).toEqual('original response body when no auth provider')

const serverAuthState = req.serverAuthState.get()
expect(serverAuthState).toEqual(middlewareDefaultAuthProviderState)
})

it('passes through when unsupported auth-provider', async () => {
const middleware = createSupabaseAuthMiddleware(options)
const [middleware] = initSupabaseAuthMiddleware(options)
const request = new Request('http://localhost:8911', {
method: 'GET',
headers: new Headers({ cookie: 'auth-provider=unsupported' }),
Expand All @@ -143,15 +141,15 @@ describe('createSupabaseAuthMiddleware()', () => {

const result = await middleware(req, res)
expect(result).toEqual(res)
expect(result.body).toEqual(
expect(result?.body).toEqual(
'original response body for unsupported provider',
)
const serverAuthState = req.serverAuthState.get()
expect(serverAuthState).toEqual(middlewareDefaultAuthProviderState)
})

it('handles current user GETs', async () => {
const middleware = createSupabaseAuthMiddleware(options)
const [middleware] = initSupabaseAuthMiddleware(options)
const request = new Request(
'http://localhost:8911/middleware/supabase/currentUser',
{
Expand All @@ -163,7 +161,7 @@ describe('createSupabaseAuthMiddleware()', () => {
const res = new MiddlewareResponse()

const result = await middleware(req, res)
expect(result.body).toEqual(
expect(result?.body).toEqual(
JSON.stringify({
currentUser: { id: 1, email: 'user-1@example.com' },
}),
Expand All @@ -175,7 +173,7 @@ describe('createSupabaseAuthMiddleware()', () => {
})

it('authenticated request sets currentUser', async () => {
const middleware = createSupabaseAuthMiddleware(options)
const [middleware] = initSupabaseAuthMiddleware(options)
const request = new Request('http://localhost:8911/authenticated-request', {
method: 'GET',
headers: new Headers({
Expand Down Expand Up @@ -210,7 +208,7 @@ describe('createSupabaseAuthMiddleware()', () => {
},
}

const middleware = createSupabaseAuthMiddleware(optionsWithUserMetadata)
const [middleware] = initSupabaseAuthMiddleware(optionsWithUserMetadata)
const request = new Request('http://localhost:8911/authenticated-request', {
method: 'GET',
headers: new Headers({
Expand Down Expand Up @@ -240,6 +238,7 @@ describe('createSupabaseAuthMiddleware()', () => {
})

it('an exception when getting the currentUser clears out serverAuthState and cookies', async () => {
vi.spyOn(console, 'error').mockImplementation(() => {})
const optionsWithUserMetadata: SupabaseAuthMiddlewareOptions = {
getCurrentUser: async () => {
// this simulates a decoding error or some other issue like tampering with the cookie so the Supabase session is invalid
Expand All @@ -248,7 +247,7 @@ describe('createSupabaseAuthMiddleware()', () => {
},
}

const middleware = createSupabaseAuthMiddleware(optionsWithUserMetadata)
const [middleware] = initSupabaseAuthMiddleware(optionsWithUserMetadata)

// the default cookie name will always be sb-<project_ref>-auth-token (e.g. sb-example-auth-token )
const request = new Request('http://localhost:8911/authenticated-request', {
Expand Down Expand Up @@ -292,5 +291,7 @@ describe('createSupabaseAuthMiddleware()', () => {
'expires',
new Date(0),
)

vi.resetAllMocks()
})
})
14 changes: 10 additions & 4 deletions packages/auth-providers/supabase/middleware/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { AUTH_PROVIDER_HEADER } from '@redwoodjs/api'
import { authDecoder } from '@redwoodjs/auth-supabase-api'
import type { GetCurrentUser } from '@redwoodjs/graphql-server'
import type {
Middleware,
MiddlewareRequest,
MiddlewareResponse,
} from '@redwoodjs/vite/middleware'
Expand All @@ -15,10 +16,13 @@ export interface SupabaseAuthMiddlewareOptions {
/**
* Create Supabase Auth Middleware that sets the `serverAuthState` based on the Supabase cookie.
*/
const createSupabaseAuthMiddleware = ({
const initSupabaseAuthMiddleware = ({
getCurrentUser,
}: SupabaseAuthMiddlewareOptions) => {
return async (req: MiddlewareRequest, res: MiddlewareResponse) => {
}: SupabaseAuthMiddlewareOptions): [Middleware, '*'] => {
const middleware = async (
req: MiddlewareRequest,
res: MiddlewareResponse,
) => {
const type = 'supabase'
const cookieHeader = req.headers.get('cookie')

Expand Down Expand Up @@ -77,5 +81,7 @@ const createSupabaseAuthMiddleware = ({

return res
}

return [middleware, '*']
}
export default createSupabaseAuthMiddleware
export default initSupabaseAuthMiddleware
Loading