npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@deskree/atomic-auth-sdk

v0.0.18

Published

Unified Ory Kratos authentication SDK for frontend projects

Downloads

35

Readme

Atomic Auth SDK

A unified authentication SDK for React applications using Ory Kratos, with full support for Next.js App Router.

Features

  • Session management with automatic refresh
  • React hooks and context for authentication state
  • Higher-Order Component (HOC) pattern for protected routes
  • API route protection for Next.js App Router
  • Email and phone verification support
  • TypeScript support
  • Secure token handling via Ory Kratos HTTP-only cookies

Installation

npm install @deskree/atomic-auth-sdk

Setup Environment

Create a .env.local file at the root of your project with the following variables:

# Required: Ory Kratos public API URL
NEXT_PUBLIC_ORY_SDK_URL=https://your-ory-instance.url

# Optional: Login redirect path
NEXT_PUBLIC_LOGIN_PATH=/auth/login

Quick Start with Next.js App Router

1. Set up Auth Configuration

// auth.ts
import { createOryAuth } from "@deskree/atomic-auth-sdk"

export const { AuthProvider, useAuth, withAuth, createAuthApi } = createOryAuth(
  {
    oryUrl: process.env.NEXT_PUBLIC_ORY_SDK_URL!,
    loginPath: process.env.NEXT_PUBLIC_LOGIN_PATH || "/auth/login",
  }
)

2. Wrap Your App with AuthProvider

// app/layout.tsx
"use client"

import { AuthProvider } from "@/auth"

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        <AuthProvider>{children}</AuthProvider>
      </body>
    </html>
  )
}

Authentication Features

Access Authentication in Components

// app/components/UserProfile.tsx
"use client"

import { useAuth } from "@/auth"

export function UserProfile() {
  const { user, logout, isAuthenticated, isLoading } = useAuth()

  if (isLoading) return <div>Loading...</div>
  if (!isAuthenticated) return <div>Not signed in</div>

  return (
    <div>
      <p>Signed in as {user?.email}</p>
      <p>Verification status: {user?.verified ? "Verified" : "Not verified"}</p>
      <button onClick={logout}>Sign Out</button>
    </div>
  )
}

Session Management

Ory Kratos automatically refreshes session cookies when they're about to expire. Our SDK takes advantage of this behavior by making periodic calls to the session endpoint:

// app/components/SessionInfo.tsx
"use client"

import { useAuth } from "@/auth"

export function SessionInfo() {
  const { session, refreshSession } = useAuth()

  if (!session) return <div>No active session</div>

  return (
    <div>
      <p>Session expires: {new Date(session.expires_at).toLocaleString()}</p>
      <button onClick={refreshSession}>Refresh Session Data</button>
    </div>
  )
}

The session refresh is handled internally by simply calling Ory Kratos's toSession() method, which not only checks the current session validity but also automatically extends the session cookie's expiration time if the session is valid. This approach is simple, reliable, and works seamlessly in both browser and server environments without requiring administrative permissions or user re-authentication.

Verification Features

Check Verification Status

// app/components/VerificationStatus.tsx
"use client"

import { useAuth } from "@/auth"

export function VerificationStatus() {
  const { user, isVerified } = useAuth()

  if (!user) return <div>Not signed in</div>

  return (
    <div>
      <p>Email verification: {isVerified ? "Verified" : "Not verified"}</p>
    </div>
  )
}

Start Verification Flow

// app/components/VerificationButton.tsx
"use client"

import { useAuth } from "@/auth"

export function VerificationButton() {
  const { startVerification } = useAuth()

  const handleStartVerification = async () => {
    try {
      // Start email verification flow
      const { verificationUrl, flowId } = await startVerification({
        returnTo: window.location.href,
      })

      if (verificationUrl) {
        // Option 1: Redirect to verification flow UI
        window.location.href = verificationUrl

        // Option 2: Store the flowId for custom verification UI
        // sessionStorage.setItem('verification_flow_id', flowId)
        // router.push('/custom-verification')
      }
    } catch (error) {
      console.error("Verification error:", error)
    }
  }

  return <button onClick={handleStartVerification}>Verify Email</button>
}

Send Verification Code

// app/components/VerificationCodeForm.tsx
"use client"

import { useState } from "react"
import { useAuth } from "@/auth"

export function VerificationCodeForm() {
  const [email, setEmail] = useState("")
  const [flowId, setFlowId] = useState("")
  const [codeSent, setCodeSent] = useState(false)
  const [code, setCode] = useState("")
  const [verificationStatus, setVerificationStatus] = useState("")

  const { startVerification, sendVerificationCode, verifyCode } = useAuth()

  const handleStartVerification = async () => {
    try {
      const { flowId } = await startVerification({})
      if (flowId) {
        setFlowId(flowId)
      }
    } catch (error) {
      console.error("Error starting verification:", error)
    }
  }

  const handleSendCode = async () => {
    if (!email || !flowId) return

    try {
      const { success } = await sendVerificationCode(email, flowId)
      if (success) {
        setCodeSent(true)
        setVerificationStatus("Verification code sent to your email")
      }
    } catch (error) {
      console.error("Error sending code:", error)
      setVerificationStatus("Failed to send verification code")
    }
  }

  const handleVerifyCode = async () => {
    if (!code || !flowId) return

    try {
      const { success } = await verifyCode(flowId, code)
      if (success) {
        setVerificationStatus("Email verified successfully!")
      } else {
        setVerificationStatus("Invalid verification code")
      }
    } catch (error) {
      console.error("Error verifying code:", error)
      setVerificationStatus("Verification failed")
    }
  }

  return (
    <div>
      {!flowId ? (
        <button onClick={handleStartVerification}>Start Verification</button>
      ) : !codeSent ? (
        <div>
          <input
            type="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            placeholder="Enter your email"
          />
          <button onClick={handleSendCode}>Send Verification Code</button>
        </div>
      ) : (
        <div>
          <input
            type="text"
            value={code}
            onChange={(e) => setCode(e.target.value)}
            placeholder="Enter verification code"
          />
          <button onClick={handleVerifyCode}>Verify Code</button>
        </div>
      )}
      {verificationStatus && <p>{verificationStatus}</p>}
    </div>
  )
}

API Reference

useAuth() Hook

const {
  // Authentication state
  isLoading: boolean,          // Whether authentication state is loading or not
  isAuthenticated: boolean,    // Whether user is authenticated
  user: SessionUser | null,    // Current user information
  session: Session | null,     // Full Ory session object
  isVerified: boolean,         // Whether user is verified
  error: Error | null,         // Any authentication error

  // Authentication actions
  login: (returnTo?: string) => Promise<void>,  // Redirect to login
  logout: () => Promise<void>,                  // Log out user

  // Session management
  refreshSession: () => Promise<void>,          // Refresh session data

  // Verification
  startVerification: (options: { returnTo?: string }) => Promise<{
    verificationUrl: string | null,
    error: Error | null,
    flowId: string | null
  }>,
  sendVerificationCode: (email: string, flowId: string) => Promise<{
    success: boolean,
    error: Error | null,
    flow: any
  }>,
  verifyCode: (flowId: string, code: string) => Promise<{
    success: boolean,
    error: Error | null,
    flow: any
  }>,
  getVerificationFlow: (flowId: string) => Promise<{
    flow: any,
    error: Error | null
  }>,
  checkVerification: () => Promise<boolean>     // Check if user is verified
} = useAuth()

SessionUser Type

interface SessionUser {
  id: string
  email: string
  verified: boolean // Whether email is verified
  name?: {
    first?: string
    last?: string
  }
}

Security Considerations

  1. Token Storage: Session tokens are handled by Ory Kratos with HTTP-only cookies, preventing JavaScript access.

  2. Auto-extension: The auto-extension feature helps prevent session expiration during active usage.

  3. API Protection: Use the createAuthApi middleware to ensure only authenticated users can access your API endpoints.

  4. Route Protection: For client-side protection, use the useAuth hook's isAuthenticated property with useEffect and the router to handle redirection.

How It Works

The SDK leverages Ory Kratos's cookie-based session management:

  1. Authentication: When a user logs in through Ory Kratos, a session cookie is set
  2. Session Validation: The SDK validates the session by making requests to Kratos's /sessions/whoami endpoint
  3. Session Extension: Sessions are automatically extended before they expire (if enabled)
  4. Local Storage: Basic user info is stored in localStorage for quick access, but the actual authentication relies on secure HTTP-only cookies

License

MIT