Blog>
Snippets

Implementing Authentication Flow with React Server Components

Show an authentication flow example with a React Server Component handling user sign-in and storing session information server-side.
// SignIn.server.js
import { useState } from 'react';
import { redirect, useSearchParams } from 'react-router-dom';
import { signInUser } from './auth'; // This is a mock function to authenticate the user

export default function SignIn() {
  const [searchParams] = useSearchParams();
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState(null);

  async function handleSubmit(event) {
    event.preventDefault();
    const result = await signInUser(username, password);
    if (result.success) {
      // Redirect to the URL from which the user came, or to the home page
      const redirectUrl = searchParams.get('from') || '/';
      throw redirect(redirectUrl);
    } else {
      setError(result.error);
    }
  }

  // Your form inputs and submit button would go here

  // Return a simple form for demonstration purposes
  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
        placeholder="Username"
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="Password"
      />
      <button type="submit">Sign In</button>
      {error && <p>{error}</p>}
    </form>
  );
}
This piece of code defines a SignIn server component that renders a form for users to input their username and password. It uses the 'useState' hook from React to manage form state and control input. It handles form submission using 'handleSubmit' function, where the mocked 'signInUser' function is used to authenticate the user against a backend system (not provided). On successful authentication, the user is redirected to the page they came from, or to the homepage. If authentication fails, an error message is displayed.
// auth.js
export async function signInUser(username, password) {
  // Mocking an API call for user authentication
  const response = await fakeApiCall(username, password);
  if (response.ok) {
    return { success: true };
  } else {
    return { success: false, error: 'Invalid credentials' };
  }
}

// This is a placeholder for an API call
async function fakeApiCall(username, password) {
  return new Promise((resolve) => {
    setTimeout(() => {
      if (username === 'user' && password === 'password') { // Replace with real validation
        resolve({ ok: true });
      } else {
        resolve({ ok: false });
      }
    }, 1000);
  });
}
This piece of code provides a mock implementation of the 'signInUser' function, which simulates an authentication API call to sign in a user. The fakeApiCall simulates a network call and resolves with a successful response if the username and password match the placeholder values. This is to be replaced with an actual API call to authenticate against a real server.