DevaProvider

The DevaProvider is the root component that manages authentication, user state, and provides context to all SDK components and hooks.


Import

import { DevaProvider } from "@bitplanet/deva-sdk";

Props

clientId

Type: string

Required: Yes

Your application's OAuth client ID from Deva.

How to get:

  1. Sign in to deva.me

  2. Navigate to Settings → Apps

  3. Create new app or use existing

  4. Copy the client_id


redirectUri

Type: string

Required: Yes

The URI where Deva redirects after authentication.

Requirements:

  • Must be registered in your Deva app settings

  • Must be an absolute URL

  • Must match exactly (including trailing slash)

Examples:

// Development
redirectUri="http://localhost:3000"

// Production
redirectUri="https://myapp.com"

env

Type: "staging" | "production"

Required: Yes

The Deva API environment to connect to. Set via the environment variable.

Available Environments:

Environment
Purpose
API Endpoint

"staging"

For SDK setup, integration testing, and verifying your implementation

https://staging.deva.me

"production"

For deploying your real application to end users

https://www.deva.me

Configuration:

# In your .env file
VITE_DEVA_ENV="staging"   # For development/testing
VITE_DEVA_ENV="production" # For live deployment

children

Type: React.ReactNode | ((devaProps: UseDevaReturn) => React.ReactNode)

Required: Yes

Your application components. Supports both standard children and render prop pattern.

Standard Pattern:

<DevaProvider {...props}>
  <App />
</DevaProvider>

Render Prop Pattern:

<DevaProvider {...props}>
  {({ isAuthenticated, user }) => (
    <App isAuthenticated={isAuthenticated} user={user} />
  )}
</DevaProvider>

Usage

Basic Setup

import { DevaProvider } from "@bitplanet/deva-sdk";

export default function Root() {
  return (
    <DevaProvider
      clientId="your-client-id"
      redirectUri={window.location.origin}
      env="your-target-environment"
    >
      <App />
    </DevaProvider>
  );
}

With Environment Variables (Next.js)

const devaConfig = {
  clientId: process.env.NEXT_PUBLIC_DEVA_CLIENT_ID!,
  redirectUri: process.env.NEXT_PUBLIC_DEVA_REDIRECT_URI!,
  env: process.env.NEXT_PUBLIC_DEVA_ENV as "staging" | "production"
};

<DevaProvider {...devaConfig}>
  <App />
</DevaProvider>

With Render Props

<DevaProvider
  clientId="your-client-id"
  redirectUri="your-redirect-uri"
  env="your-target-environment"
>
  {({ isAuthenticated, isReady, user }) => {
    if (!isReady) {
      return <LoadingScreen />;
    }

    if (!isAuthenticated) {
      return <LoginPage />;
    }

    return <AuthenticatedApp user={user} />;
  }}
</DevaProvider>

What It Provides

The DevaProvider manages and provides:

Authentication State

  • OAuth 2.0 + OIDC authentication flow

  • Access token management

  • Refresh token handling

  • Session persistence (sessionStorage)

User Information

  • User profile data

  • User persona information

  • Authentication status

Context Values

All child components and hooks can access:

  • isAuthenticated - Boolean authentication status

  • isReady - Boolean indicating SDK initialization complete

  • accessToken - Current access token (or null)

  • user - User information (or null)

  • login() - Function to initiate login

  • logout() - Function to log out

See useDeva hook documentation


Internal Behavior

Initialization Flow

  1. Component Mounts

    • Loads OpenID configuration

    • Checks sessionStorage for existing tokens

    • Validates stored tokens

  2. Session Restoration

    • If valid tokens exist, restores session

    • Fetches user information

    • Sets isAuthenticated to true

  3. Ready State

    • Sets isReady to true when initialization complete

    • Components can now safely render

Token Management

Automatic Refresh:

  • Checks token expiration every second

  • Refreshes tokens before expiration

  • Updates sessionStorage automatically

Session Storage:

  • Stores access_token, refresh_token, id_token

  • Stores expiration times

  • Cleared on logout or browser close

OAuth Flow

Login Process:

  1. Generate PKCE code verifier and challenge

  2. Redirect to Deva authorization endpoint

  3. User authenticates and grants permissions

  4. Deva redirects back with authorization code

  5. Exchange code for tokens

  6. Fetch user information

  7. Store tokens in sessionStorage

Logout Process:

  1. Revoke access token via revocation endpoint

  2. Clear sessionStorage

  3. Reset authentication state


Error Handling

The provider handles errors internally:

OpenID Config Load Failure:

  • Provider initialization fails

  • App cannot authenticate users

  • Consider showing error message

Token Refresh Failure:

  • User is logged out automatically

  • Session cleared

  • User must log in again

Network Errors:

  • Provider retries automatically

  • Authentication state preserved when possible


Best Practices

Placement:

  • Place at the root of your application

  • Only one provider per app

  • Wrap entire app, not individual routes

Environment Variables:

  • Store credentials in environment variables

  • Never commit credentials to version control

  • Use different credentials per environment

Error Boundaries:

<ErrorBoundary>
  <DevaProvider {...config}>
    <App />
  </DevaProvider>
</ErrorBoundary>

Loading States:

<DevaProvider {...config}>
  {({ isReady, isAuthenticated }) => {
    if (!isReady) return <Loading />;
    if (!isAuthenticated) return <Login />;
    return <App />;
  }}
</DevaProvider>

TypeScript Interface

type DevaProviderProps = {
  clientId: string;
  redirectUri: string;
  children: React.ReactNode | ((devaProps: UseDevaReturn) => React.ReactNode);
  env: "staging" | "production";
};

type UseDevaReturn = {
  isAuthenticated: boolean;
  isReady: boolean;
  accessToken: string | null;
  user: UserInfo | null;
  login: () => Promise<void>;
  logout: () => Promise<void>;
};

Last updated