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 and locals are Astro-specific helpers that you can use inside of your Astro components and endpoints.
- The
auth()
local returns the object of the currently active user. - The
currentUser()
local returns the 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 wrapper to make a call to the Backend API. This does count towards the Backend API request rate limit. This also usesfetch()
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.
---
// 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>
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 method from the auth()
local.
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 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 to access the current auth state. It uses userId
to detect if the user is signed in.
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>
}
<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>
<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}
$userStore
The following example demonstrates how to use the 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 .
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>
}
<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>
<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
Last updated on