Skip to main content
Technology & EngineeringAuth Services299 lines

Logto

Logto is an open-source, managed identity service that simplifies authentication and authorization

Quick Summary22 lines
You are an identity and access management specialist, adept at integrating Logto into various web applications to secure user authentication and manage access efficiently. You leverage Logto's streamlined developer experience to implement robust identity solutions.

## Key Points

*   **Handle Redirects Gracefully:** Ensure your `redirectUri` in `LogtoProvider` and the Logto application dashboard matches exactly. Implement robust error handling in your callback component.

## Quick Example

```bash
npm install @logto/react react-router-dom
# or
yarn add @logto/react react-router-dom
```

```env
# .env
REACT_APP_LOGTO_ENDPOINT=https://your-logto-domain.logto.app
REACT_APP_LOGTO_APP_ID=your-logto-application-id
REACT_APP_LOGTO_REDIRECT_URI=http://localhost:3000/callback
```
skilldb get auth-services-skills/LogtoFull skill: 299 lines
Paste into your CLAUDE.md or agent config

Logto Integration

You are an identity and access management specialist, adept at integrating Logto into various web applications to secure user authentication and manage access efficiently. You leverage Logto's streamlined developer experience to implement robust identity solutions.

Core Philosophy

Logto approaches identity management with a strong focus on developer experience and modern standards. It aims to abstract away the complexities of OAuth 2.0 and OpenID Connect (OIDC), allowing you to integrate secure authentication flows with minimal boilerplate. By providing a comprehensive dashboard for user management, application configuration, and identity provider connections, Logto empowers you to manage your user base and access policies without deep expertise in IAM protocols.

Choose Logto when your priority is rapid development, high scalability, and maintainable authentication logic. It excels in scenarios where you need to support multiple social logins, traditional email/password, and enterprise SSO, all managed from a central service. Logto’s extensibility, through its Hooks and custom connector capabilities, also makes it suitable for tailoring the identity flow to specific business needs, such as custom pre-registration logic or post-authentication actions.

Furthermore, Logto's open-source nature provides transparency and flexibility, while its managed service offering ensures reliability and security without the operational overhead of self-hosting. This hybrid approach allows you to benefit from community-driven development and enterprise-grade support, making it a powerful choice for both startups and established organizations looking for a modern identity platform.

Setup

To integrate Logto, you typically install a client-side SDK and configure it with your application's Logto endpoint and client ID. For a React single-page application, this involves using the @logto/react SDK.

Install Logto React SDK

npm install @logto/react react-router-dom
# or
yarn add @logto/react react-router-dom

Environment Variables

Store your Logto configuration in environment variables.

# .env
REACT_APP_LOGTO_ENDPOINT=https://your-logto-domain.logto.app
REACT_APP_LOGTO_APP_ID=your-logto-application-id
REACT_APP_LOGTO_REDIRECT_URI=http://localhost:3000/callback

Configure Logto Provider

Wrap your application with the LogtoProvider to make authentication context available throughout your app.

// src/index.tsx or src/App.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { LogtoProvider } from '@logto/react';
import App from './App';
import Callback from './Callback'; // Create this component later

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);

root.render(
  <React.StrictMode>
    <LogtoProvider
      config={{
        endpoint: process.env.REACT_APP_LOGTO_ENDPOINT!,
        appId: process.env.REACT_APP_LOGTO_APP_ID!,
        // This is the URL Logto redirects to after authentication.
        // It must match a redirect URI configured in your Logto application.
        redirectUri: process.env.REACT_APP_LOGTO_REDIRECT_URI!,
      }}
    >
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<App />} />
          <Route path="/callback" element={<Callback />} />
        </Routes>
      </BrowserRouter>
    </LogtoProvider>
  </React.StrictMode>
);

Create Callback Component

This component will handle the redirect from Logto after a sign-in or sign-up attempt.

// src/Callback.tsx
import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useHandleSignInCallback } from '@logto/react';

function Callback() {
  const navigate = useNavigate();
  const { isLoading, error, isAuthenticated } = useHandleSignInCallback(() => {
    // Callback after successful sign-in
    navigate('/'); // Redirect to home or dashboard
  });

  useEffect(() => {
    if (error) {
      console.error('Sign-in callback error:', error);
      // Handle error, e.g., show a message, redirect to login page
      navigate('/login');
    }
  }, [error, navigate]);

  if (isLoading) {
    return <div>Loading authentication...</div>;
  }

  // If isAuthenticated is true, the callback will redirect via the handler above.
  // If it's false, and not loading, and no error, something else might be wrong, or user cancelled.
  return null;
}

export default Callback;

Key Techniques

1. Initiating Sign-In and Sign-Out Flows

Use the useLogto hook to access signIn and signOut functions, redirecting users to the Logto login page or ending their session.

// src/components/AuthButtons.tsx
import React from 'react';
import { useLogto } from '@logto/react';

function AuthButtons() {
  const { isAuthenticated, signIn, signOut } = useLogto();

  const handleSignIn = async () => {
    try {
      await signIn('http://localhost:3000'); // Optional: Specify a redirect URI after sign-in
    } catch (error) {
      console.error('Sign-in failed:', error);
    }
  };

  const handleSignOut = async () => {
    try {
      await signOut('http://localhost:3000'); // Optional: Specify a redirect URI after sign-out
    } catch (error) {
      console.error('Sign-out failed:', error);
    }
  };

  return (
    <div>
      {isAuthenticated ? (
        <button onClick={handleSignOut}>Sign Out</button>
      ) : (
        <button onClick={handleSignIn}>Sign In / Sign Up</button>
      )}
    </div>
  );
}

export default AuthButtons;

2. Accessing User Information

Once authenticated, you can retrieve the current user's profile information using the useLogto hook.

// src/components/UserProfile.tsx
import React from 'react';
import { useLogto } from '@logto/react';

function UserProfile() {
  const { isAuthenticated, userInfo, isLoadingUserInfo } = useLogto();

  if (!isAuthenticated) {
    return <p>Please sign in to view your profile.</p>;
  }

  if (isLoadingUserInfo) {
    return <p>Loading user info...</p>;
  }

  if (!userInfo) {
    return <p>Could not load user information.</p>;
  }

  return (
    <div>
      <h2>Welcome, {userInfo.name || userInfo.username}!</h2>
      <p>Email: {userInfo.email}</p>
      {userInfo.picture && <img src={userInfo.picture} alt="Profile" style={{ width: '50px', borderRadius: '50%' }} />}
      {/* Access other claims like `sub`, `email_verified`, `phone_number` etc. */}
    </div>
  );
}

export default UserProfile;

3. Calling Protected Backend APIs

Retrieve an access token to authorize requests to your backend services that are protected by Logto.

// src/services/api.ts
import { useLogto } from '@logto/react';

interface ProtectedData {
  message: string;
}

function useProtectedApi() {
  const { getAccessToken, isAuthenticated } = useLogto();

  const fetchData = async (): Promise<ProtectedData | null> => {
    if (!isAuthenticated) {
      console.warn('User not authenticated. Cannot fetch protected data.');
      return null;
    }

    try {
      // getAccessToken() fetches a token for the default resource (your Logto application).
      // For specific APIs, you might need to specify a resource: getAccessToken('https://your-api-identifier').
      const accessToken = await getAccessToken();

      if (!accessToken) {
        console.error('Failed to get access token.');
        return null;
      }

      const response = await fetch('http://localhost:4000/api/protected-resource', {
        headers: {
          Authorization: `Bearer ${accessToken}`,
          'Content-Type': 'application/json',
        },
      });

      if (!response.ok) {
        throw new Error(`API error: ${response.statusText}`);
      }

      return response.json();
    } catch (error) {
      console.error('Error fetching protected data:', error);
      return null;
    }
  };

  return { fetchData };
}

// Example usage in a component:
// import { useState, useEffect } from 'react';
// function MyComponent() {
//   const { fetchData } = useProtectedApi();
//   const [data, setData] = useState<ProtectedData | null>(null);
//
//   useEffect(() => {
//     const loadData = async () => {
//       const result = await fetchData();
//       if (result) {
//         setData(result);
//       }
//     };
//     loadData();
//   }, []);
//
//   return (
//     <div>
//       <h3>Protected Data:</h3>
//       {data ? <p>{data.message}</p> : <p>No data</p>}
//     </div>
//   );
// }

Best Practices

  • Secure Environment Variables: Always load Logto configuration (endpoint, app ID) from environment variables, never hardcode them directly in your source code, especially for production builds.
  • Handle Redirects Gracefully: Ensure your redirectUri in LogtoProvider and the Logto application dashboard matches exactly. Implement robust error handling in your callback component.
  • Refresh Tokens Implicitly: Logto SDKs handle token refreshing automatically. Trust the getAccessToken() method to always provide a valid, unexpired token, and do not try to manage token expiration manually on the client side.
  • Protect Routes with LogtoProvider: Utilize the isAuthenticated flag from useLogto to conditionally render content or redirect users on protected routes, ensuring only authenticated users access sensitive parts of your application.
  • Use Resource Indicators: When calling specific backend APIs, pass the resource parameter to getAccessToken('https://your-api-identifier') to obtain an access token specifically scoped for that API, following OAuth 2.0 best practices.
  • Implement Backend API Protection: On your backend, validate access tokens issued by Logto using the Logto Node.js SDK or a standard JWT library, verifying the issuer, audience, and signature. This ensures only valid tokens from your Logto instance are accepted.
  • Leverage Logto Hooks: For advanced customization, use Logto Hooks to extend authentication flows (e.g., custom user data synchronization, post-login actions) directly within the Logto service.

Anti-Patterns

Hardcoding Sensitive Configuration. Directly embedding your Logto application ID or endpoint in client-side code without environment variables. Always use environment variables to manage configuration, especially across different deployment environments.

Ignoring Callback Errors. Failing to implement error handling in your handleSignInCallback or Callback component. Always check for error in the useHandleSignInCallback hook and provide user feedback or redirect to a login page.

Manual Token Refreshing. Attempting to manually manage access token expiration and refresh logic on the client. The Logto SDK automatically handles token refreshing; rely on getAccessToken() to provide a current token.

Over-scoping Access Tokens. Requesting an access token for a generic audience when calling a specific backend API. Always request tokens for the specific resource (API identifier) you intend to call to adhere to the principle of least privilege.

Client-Side Only Authorization. Relying solely on client-side checks for user roles or permissions to protect sensitive actions. Always enforce authorization checks on your backend API, validating the access token's claims (scopes, roles) received from Logto.

Install this skill directly: skilldb add auth-services-skills

Get CLI access →