Skip to main content
Docs

After-auth flows

You can configure your application to require users to complete specific actions after signing in or signing up. Users who don't complete these required actions will have their session remain in a pending status, which is treated as a signed-out state by default.

Currently available configurations include:

With <SignIn /> and <SignUp>

After-auth flows are embedded within <SignIn /> and <SignUp> by default. Currently, you cannot eject from these components to custom pages, but we're working on adding this capability.

Protections against pending sessions

By default, pending sessions are treated as signed-out state by default across utilities and control components.

Control components

src/settings.tsx
import { Protect } from '@clerk/clerk-react'

export default function Page() {
  return (
    <Protect>
      <p>User has no session or a pending session</p>
    </Protect>
  )
}
src/settings.tsx
import { SignedOut } from '@clerk/clerk-react'

export default function Page() {
  return (
    <SignedOut>
      <p>User has no session or a pending session</p>
    </SignedOut>
  )
}
src/settings.tsx
import { SignedIn } from '@clerk/clerk-react'

export default function Page() {
  return (
    <SignedIn>
      <p>User has a session that has fullfilled all after-auth actions</p>
    </SignedIn>
  )
}

Control components have treatPendingAsSignedOut prop that defaults to true, but you can opt-out of that behavior.

src/settings.tsx
import { Protect } from '@clerk/clerk-react'

export default function Page() {
  return (
    <Protect treatPendingAsSignedOut={false}>
      <p>User has no session</p>
    </Protect>
  )
}
src/settings.tsx
import { SignedOut } from '@clerk/clerk-react'

export default function Page() {
  return (
    <SignedOut treatPendingAsSignedOut={false}>
      <p>User has no session</p>
    </SignedOut>
  )
}

Server-side protections

Once a session is on a pending status, then server utilities such as auth() treat it as signed-out state by default.

Those utilities also accept a treatPendingAsSignedOut option that defaults to true, but you can opt-out of that behavior.

Taking disabling personal workspace as example:

middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'

const isProtectedRoute = createRouteMatcher(['/dashboard(.*)', '/forum(.*)'])

export default clerkMiddleware(async (auth, req) => {
  // `auth.protect` will redirect users to select an organization
  // if they don't have one, preventing access to protected pages
  if (isProtectedRoute(req)) await auth.protect()
})
app/middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'

const isProtectedRoute = createRouteMatcher(['/dashboard(.*)', '/forum(.*)'])

export default clerkMiddleware(async (auth, req) => {
  const { userId, redirectToSignIn } = await auth()

  // `userId` won't be available if the user has a pending session
  // without an organization
  if (!userId && isProtectedRoute(req)) {
    return redirectToSignIn()
  }
})
app/page.tsx
import { auth } from '@clerk/nextjs/server'

export default async function Page() {
  const { userId, orgId } = await auth()

  if (!userId) {
    return (
      <p>
        User has no session or a pending session meaning that it might not have an organization
        selected
      </p>
    )
  }

  return (
    <p>
      <p>User has a valid session and {orgId} is defined</p>
    </p>
  )
}

Feedback

What did you think of this content?

Last updated on