Guides
Authentication

Integrating Auth

ShellApps ID provides a unified identity system across the entire ShellApps platform. This guide covers integrating authentication into your app.

How ShellApps ID Works

ShellApps ID is the single sign-on (SSO) identity layer for all ShellApps services. Users create one account and use it across every ShellApp.

Key concepts:

  • ShellApps ID — The user's identity, managed at auth.shellapps.com (opens in a new tab)
  • Profiles — Users can have multiple profiles (personal, work, etc.) under one ID
  • Sessions — JWT-based sessions with automatic refresh
  • OAuth 2.0 — Standard OAuth 2.0 / OIDC flow for third-party apps

Adding Login / Signup to Your App

Install the Auth SDK

npm install @shellapps/auth-sdk

Configure the Auth Provider

app/auth-provider.tsx
'use client'
 
import { AuthProvider } from '@shellapps/auth-sdk'
 
export function ShellAuthProvider({ children }: { children: React.ReactNode }) {
  return (
    <AuthProvider
      appId={process.env.NEXT_PUBLIC_SHELLAPPS_APP_ID!}
      redirectUri={process.env.NEXT_PUBLIC_AUTH_REDIRECT_URI!}
    >
      {children}
    </AuthProvider>
  )
}

Add Login / Signup Buttons

components/auth-buttons.tsx
'use client'
 
import { useAuth } from '@shellapps/auth-sdk'
import { Button } from '@shellapps/react-ui'
 
export function AuthButtons() {
  const { user, login, signup, logout, isLoading } = useAuth()
 
  if (isLoading) return null
 
  if (user) {
    return (
      <div>
        <span>Hello, {user.displayName}</span>
        <Button onClick={logout} variant="ghost">Sign Out</Button>
      </div>
    )
  }
 
  return (
    <div>
      <Button onClick={login} variant="primary">Log In</Button>
      <Button onClick={signup} variant="outline">Sign Up</Button>
    </div>
  )
}

Using the Auth SDK

Access the Current User

import { useAuth } from '@shellapps/auth-sdk'
 
function Dashboard() {
  const { user, accessToken } = useAuth()
 
  // Use accessToken for API calls
  const res = await fetch('/api/data', {
    headers: { Authorization: `Bearer ${accessToken}` }
  })
}

Server-Side Authentication

app/api/protected/route.ts
import { verifyToken } from '@shellapps/auth-sdk/server'
import { NextRequest, NextResponse } from 'next/server'
 
export async function GET(req: NextRequest) {
  const token = req.headers.get('Authorization')?.replace('Bearer ', '')
 
  if (!token) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
  }
 
  try {
    const user = await verifyToken(token, {
      appId: process.env.SHELLAPPS_APP_ID!,
    })
    return NextResponse.json({ user })
  } catch {
    return NextResponse.json({ error: 'Invalid token' }, { status: 401 })
  }
}

Session Management

Sessions are managed automatically by the Auth SDK. Tokens are stored securely and refreshed in the background.

const { user, accessToken, refreshSession, isExpired } = useAuth()
 
// Force refresh if needed
if (isExpired) {
  await refreshSession()
}

Session Configuration

<AuthProvider
  appId={process.env.NEXT_PUBLIC_SHELLAPPS_APP_ID!}
  redirectUri="/auth/callback"
  sessionConfig={{
    autoRefresh: true,
    refreshInterval: 300, // seconds
    persistSession: true,
    storage: 'cookie', // 'cookie' | 'localStorage'
  }}
>

Profile Switching

Users with multiple profiles can switch between them without re-authenticating.

import { useAuth } from '@shellapps/auth-sdk'
 
function ProfileSwitcher() {
  const { user, profiles, switchProfile, activeProfile } = useAuth()
 
  return (
    <select
      value={activeProfile.id}
      onChange={(e) => switchProfile(e.target.value)}
    >
      {profiles.map((profile) => (
        <option key={profile.id} value={profile.id}>
          {profile.displayName} ({profile.type})
        </option>
      ))}
    </select>
  )
}

Protecting Routes

Client-Side Route Protection

components/protected-route.tsx
'use client'
 
import { useAuth } from '@shellapps/auth-sdk'
import { redirect } from 'next/navigation'
 
export function ProtectedRoute({ children }: { children: React.ReactNode }) {
  const { user, isLoading } = useAuth()
 
  if (isLoading) return <div>Loading...</div>
  if (!user) redirect('/login')
 
  return <>{children}</>
}

Middleware-Based Protection

middleware.ts
import { withAuth } from '@shellapps/auth-sdk/middleware'
 
export default withAuth({
  appId: process.env.SHELLAPPS_APP_ID!,
  protectedRoutes: ['/dashboard/:path*', '/settings/:path*'],
  loginPage: '/login',
})
 
export const config = {
  matcher: ['/dashboard/:path*', '/settings/:path*'],
}

Next Steps


© 2026 Shell Technology. All rights reserved.