Methods

API reference for authentication methods available through the useDeva() hook.


Overview

The SDK provides two primary authentication methods accessed via the useDeva hook:

  • login() - Initiates OAuth authentication flow

  • logout() - Revokes tokens and clears authentication state


login()

Initiates the OAuth 2.0 + OIDC authentication flow with PKCE.

Signature

login: () => Promise<void>

Usage

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

function LoginButton() {
  const { login, isAuthenticated } = useDeva();

  if (isAuthenticated) {
    return null;
  }

  return <button onClick={login}>Login with Deva</button>;
}

Behavior

When Called:

  1. Clears any existing authentication state

  2. Generates PKCE code verifier and challenge

  3. Redirects browser to Deva authorization endpoint

  4. User authenticates on Deva platform

  5. User grants permissions to your app

  6. Deva redirects back to your redirectUri with authorization code

  7. SDK exchanges code for access and refresh tokens

  8. SDK fetches user information

  9. Tokens stored in sessionStorage

  10. isAuthenticated becomes true

Parameters:

  • None

Returns:

  • Promise<void> - Resolves immediately after redirect

Errors:

  • Throws if OpenID configuration not loaded

  • Network errors handled internally with retries

Example Flow

function App() {
  const { login, isReady, isAuthenticated } = useDeva();

  if (!isReady) {
    return <div>Loading...</div>;
  }

  if (!isAuthenticated) {
    return (
      <div>
        <h1>Welcome</h1>
        <button onClick={login}>Sign In</button>
      </div>
    );
  }

  return <Dashboard />;
}

logout()

Revokes the access token and clears all authentication state.

Signature

logout: () => Promise<void>

Usage

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

function LogoutButton() {
  const { logout, user } = useDeva();

  return (
    <div>
      <span>Logged in as {user?.preferred_username}</span>
      <button onClick={logout}>Logout</button>
    </div>
  );
}

Behavior

When Called:

  1. Sends revocation request to Deva OAuth server

  2. Clears sessionStorage (access_token, refresh_token, id_token)

  3. Resets internal authentication state

  4. isAuthenticated becomes false

  5. user becomes null

  6. accessToken becomes null

Parameters:

  • None

Returns:

  • Promise<void> - Resolves when logout complete

Errors:

  • Network errors logged but do not throw

  • Logout completes even if revocation fails

  • Local state always cleared

Example with Confirmation

function LogoutButton() {
  const { logout } = useDeva();
  const [isLoggingOut, setIsLoggingOut] = useState(false);

  const handleLogout = async () => {
    if (confirm("Are you sure you want to log out?")) {
      setIsLoggingOut(true);
      await logout();
      // Redirect or show message
    }
  };

  return (
    <button onClick={handleLogout} disabled={isLoggingOut}>
      {isLoggingOut ? "Logging out..." : "Logout"}
    </button>
  );
}

Internal Methods

These methods are used internally by the SDK and not directly exposed:

refreshToken()

Purpose: Automatically refreshes expired access tokens

Behavior:

  • Called automatically before token expires

  • Checks token expiration every second via useInterval

  • Exchanges refresh_token for new access_token

  • Updates sessionStorage with new tokens

  • Happens transparently without user interaction

When It Runs:

  • Token is about to expire (checked every second)

  • Returns new tokens and updates state

  • If refresh fails, user is logged out

revokeToken()

Purpose: Revokes access token on logout

Behavior:

  • Called by logout() method

  • Sends POST request to revocation endpoint

  • Includes access_token and client_id

  • Invalidates token on server


Authentication State

Access authentication state via useDeva() hook:

const {
  isAuthenticated,  // true if user has valid token
  isReady,          // true when SDK initialized
  accessToken,      // current access token
  user,             // user information object
  login,            // login function
  logout            // logout function
} = useDeva();

isAuthenticated

Type: boolean

Values:

  • true - User has valid access token

  • false - User not logged in or token expired

Usage:

if (isAuthenticated) {
  return <AuthenticatedContent />;
}
return <LoginPrompt />;

isReady

Type: boolean

Values:

  • true - SDK initialization complete

  • false - SDK still initializing

Usage:

if (!isReady) {
  return <LoadingSpinner />;
}
// SDK ready, safe to check isAuthenticated

accessToken

Type: string | null

Value: JWT access token or null if not authenticated

Usage:

const { accessToken } = useDeva();

// Use for custom API calls
fetch("https://api.deva.me/custom", {
  headers: {
    Authorization: `Bearer ${accessToken}`
  }
});

Note: Components and hooks use this automatically. Manual use only needed for custom API calls.


Authentication Patterns

Protected Routes

function ProtectedRoute({ children }) {
  const { isReady, isAuthenticated, login } = useDeva();

  if (!isReady) {
    return <LoadingScreen />;
  }

  if (!isAuthenticated) {
    return (
      <div>
        <p>Please log in to continue</p>
        <button onClick={login}>Login</button>
      </div>
    );
  }

  return <>{children}</>;
}

Conditional Rendering

function App() {
  const { isAuthenticated, login, logout } = useDeva();

  return (
    <div>
      <header>
        {isAuthenticated ? (
          <button onClick={logout}>Logout</button>
        ) : (
          <button onClick={login}>Login</button>
        )}
      </header>
      <main>
        {isAuthenticated ? <Dashboard /> : <LandingPage />}
      </main>
    </div>
  );
}

Automatic Redirect

function App() {
  const { isReady, isAuthenticated, login } = useDeva();

  useEffect(() => {
    if (isReady && !isAuthenticated) {
      login(); // Auto-redirect to login
    }
  }, [isReady, isAuthenticated, login]);

  if (!isReady || !isAuthenticated) {
    return <LoadingScreen />;
  }

  return <Dashboard />;
}

Security Considerations

Token Storage:

  • Tokens stored in sessionStorage (not localStorage)

  • Cleared when browser/tab closes

  • Not accessible to other domains

PKCE Flow:

  • No client secret exposed in browser

  • Code verifier prevents interception attacks

  • State parameter prevents CSRF

Automatic Refresh:

  • Tokens refreshed before expiration

  • Seamless user experience

  • No re-authentication required

Best Practices:

  • Always use HTTPS in production

  • Never log tokens to console

  • Don't store tokens in component state

  • Let SDK manage token lifecycle


Last updated