Skip to main content
Docs

Read session and user data in your Astro app with Clerk

Clerk provides helpers that you can use to access the active session and user data in your Astro application.

Server-side

The auth() and currentUser() locals are Astro-specific helpers that you can use inside of your Astro components and endpoints.

  • The auth() local returns the Auth object of the currently active user.
  • The currentUser() local returns the Backend User object of the currently active user. This is helpful if you want to render user information, like their first and last name, directly from the server. Under the hood, currentUser() uses the clerkClient wrapper to make a call to the Backend API. This does count towards the Backend API request rate limit. This also uses fetch() so it is automatically deduped per request.

The following example demonstrates how to protect a page from unauthenticated users and access the current user's information.

src/pages/me.astro
---
// Get the userId from auth() -- if null, the user is not signed in
const { userId } = Astro.locals.auth()

// Protect the route by checking if the user is signed in
if (!userId) {
  return Astro.redirect('/login')
}

// Get the Backend User object when you need access to the user's information
const user = await Astro.locals.currentUser()
---

<!-- Use `user` to render user details or create UI elements -->
<div>Welcome, {user.firstName}!</div>
src/api/me.ts
export async function GET({ locals }) {
  // Get the userId from auth() -- if null, the user is not signed in
  const { userId } = locals.auth()

  // Protect the route by checking if the user is signed in
  if (!userId) {
    return new Response('Unauthorized', { status: 401 })
  }

  // Get the Backend User object when you need access to the user's information
  const user = await locals.currentUser()

  // Add your Route Handler's logic with the returned `user` object

  return new Response(JSON.stringify(user))
}

Retrieve data from external sources

Clerk provides integrations with a number of popular databases.

To retrieve a token from a JWT template and fetch data from an external source, use the getToken() method from the auth() local.

src/pages/api/route.ts
export async function GET({ locals }) {
  // Get the userId and getToken() from auth()
  const { userId, getToken } = locals.auth()

  // Protect the route by checking if the user is signed in
  if (!userId) {
    return new Response('Unauthorized', { status: 401 })
  }

  // Use `getToken()` to get a token from the JWT template
  const token = await getToken({ template: 'supabase' })

  // Fetch data from Supabase and return it
  const data = { supabaseData: 'Hello World' }

  return new Response(JSON.stringify(data))
}

Client-side

Clerk Astro provides a set of useful stores that give you access to many important objects, such as the Clerk, User, and Session object.

$authStore

The following example demonstrates how to use the $authStore to access the current auth state. It uses userId to detect if the user is signed in.

components/external-data.tsx
import { useStore } from '@nanostores/react'
import { $authStore } from '@clerk/astro/client'

export default function ExternalData() {
  const { userId } = useStore($authStore)

  if (userId === undefined) {
    // Handle loading state however you like
    return <div>Loading...</div>
  }

  if (userId === null) {
    // Handle signed out state however you like
    return <div>Sign in to view this page</div>
  }

  return <div>...</div>
}
components/external-data.vue
<script setup>
import { useStore } from '@nanostores/vue'
import { $authStore } from '@clerk/astro/client'

const auth = useStore($authStore)
</script>

<template>
  <div v-if="auth.userId === undefined">Loading...</div>
  <div v-else-if="auth.userId === null">Sign in to view this page</div>
  <div v-else>...</div>
</template>
components/external-data.svelte
<script>
  // The $ prefix is reserved in Svelte for its own reactivity system.
  // Alias the imports to avoid conflicts.
  import { $authStore as auth } from '@clerk/astro/client'
</script>

{#if $auth.userId === undefined}
  <div>Loading...</div>
{:else if $auth.userId === null}
  <div>Sign in to view this page</div>
{:else}
  <div>...</div>
{/if}

The following example demonstrates how to use the $userStore to access the User object. It returns undefined while Clerk is still loading and null if the user is not signed in.

For more information, see the User reference.

user.tsx
import { useStore } from '@nanostores/react'
import { $userStore } from '@clerk/astro/client'

export default function User() {
  const user = useStore($userStore)

  if (user === undefined) {
    // Handle loading state however you like
    return null
  }

  if (user === null) {
    return <div>Not signed in</div>
  }

  return <div>Hello {user.fullName}!</div>
}
user.vue
<script setup>
import { useStore } from '@nanostores/vue'
import { $userStore } from '@clerk/astro/client'

const user = useStore($userStore)
</script>

<template>
  <div v-if="user === undefined">
    <!-- Handle loading state however you like -->
  </div>
  <div v-else-if="user === null">Not signed in</div>
  <div v-else>Hello {{ user.fullName }}!</div>
</template>
user.svelte
<script>
  // The $ prefix is reserved in Svelte for its own reactivity system.
  // Alias the imports to avoid conflicts.
  import { $userStore as user } from '@clerk/astro/client'
</script>

{#if $user === undefined}
  <!-- Handle loading state however you like -->
{:else if $user === null}
  <div>Not signed in</div>
{:else}
  <div>Hello {$user.fullName}!</div>
{/if}

Feedback

What did you think of this content?

Last updated on