Skip to content

Commit

Permalink
feat(session): add support for retrieving user session (#338)
Browse files Browse the repository at this point in the history
  • Loading branch information
joeychilson authored Mar 29, 2024
1 parent ee5670b commit 07eb081
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 0 deletions.
44 changes: 44 additions & 0 deletions docs/content/4.usage/composables/useSupabaseSession.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
title: useSupabaseSession
description: Auto import and use your Supabase user's session with the useSupabaseSession composable
---

Once logged in, you can [auto-import](https://nuxt.com/docs/guide/directory-structure/composables) your user's session everywhere inside your vue files.

```vue
<script setup>
const session = useSupabaseSession()
</script>
```

::callout{icon="i-heroicons-light-bulb"}
If you just need the User's information you can use [useSupabaseUser](/usage/composables/usesupabaseuser) which returns just the User information of the session.
::

## Auth middleware

::callout{icon="i-heroicons-light-bulb"}
By default, the module is implementing a redirect middleware. All pages of your application are automatically redirected to the [login](/get-started#redirectoptions) page. However, you can allow redirection to "public" pages by setting the [exclude](/get-started#redirectoptions) redirect option. Alternatively, you can enable the redirect only for certain routes using the [include](/get-started#redirectoptions) redirect option.
::

If the [redirect](/get-started#redirect) option is disabled, you can protect your authenticated routes by creating a custom middleware in your project, here is an example:

```ts [middleware/auth.ts]
export default defineNuxtRouteMiddleware((to, _from) => {
const session = useSupabaseSession()

if (!session.value) {
return navigateTo('/login')
}
})
```

Then you can reference your middleware in your page with:

```ts [pages/dashboard.vue]
definePageMeta({
middleware: 'auth'
})
```

Learn more about [Nuxt middleware](https://nuxt.com/docs/guide/directory-structure/middleware) and [definePageMeta](https://nuxt.com/docs/guide/directory-structure/pages#page-metadata).
42 changes: 42 additions & 0 deletions docs/content/4.usage/services/3.serverSupabaseSession.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: serverSupabaseSession
description: Get your Supabase user's session from serverside with the serverSupabaseUser service
---

::callout{color="amber" icon="i-heroicons-exclamation-triangle-20-solid"}
This section assumes you're familiar with [Nitro](https://v3.nuxtjs.org/guide/concepts/server-engine), the server engine powered by Nuxt.
::

This function is similar to the [useSupabaseSession](/usage/composables/usesupabasesession) composable but is used in [server routes](https://nuxt.com/docs/guide/directory-structure/server#server-routes).

Define your server route and import the `serverSupabaseSession` from `#supabase/server`.

```ts [server/api/session.ts]
import { serverSupabaseSession } from '#supabase/server'

export default defineEventHandler(async (event) => {
return await serverSupabaseSession(event)
})
```

Then call your api route from any vue file:

```ts [pages/index.vue]
const session = ref(null)

const fetchSession = async () => {
session.value = await $fetch('/api/session')
}
```

Be careful, if you want to call this route on SSR, please read this [section](https://nuxt.com/docs/getting-started/data-fetching#isomorphic-fetch-and-fetch), you must send your browser cookies including your supabase token.

```ts [pages/index.vue]
const session = ref(null)

const { data } = await useFetch('/api/session', {
headers: useRequestHeaders(['cookie'])
})

session.value = data
```
23 changes: 23 additions & 0 deletions src/runtime/composables/useSupabaseSession.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { Session } from '@supabase/supabase-js'
import type { Ref } from 'vue'
import { useSupabaseClient } from './useSupabaseClient'
import { useState } from '#imports'

export const useSupabaseSession = () => {
const supabase = useSupabaseClient()

const sessionState = useState<Session | null>('supabase_session', () => null)

// Asyncronous refresh session and ensure user is still logged in
supabase?.auth.getSession().then(({ data: { session } }) => {
if (session) {
if (JSON.stringify(sessionState.value) !== JSON.stringify(session)) {
sessionState.value = session
}
} else {
sessionState.value = null
}
})

return sessionState as Ref<Session | null>
}
17 changes: 17 additions & 0 deletions src/runtime/server/services/serverSupabaseSession.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Session } from '@supabase/supabase-js'
import type { H3Event } from 'h3'
import { createError } from 'h3'
import { serverSupabaseClient } from '../services/serverSupabaseClient'

export const serverSupabaseSession = async (event: H3Event): Promise<Session | null> => {
const client = await serverSupabaseClient(event)

const { data: { session }, error } = await client.auth.getSession()
if (error) {
throw createError({ statusMessage: error?.message })
}

event.context._session = session ?? null

return event.context._session
}

0 comments on commit 07eb081

Please sign in to comment.