Chat
Search
Ithy Logo

Invoking Supabase Auth in Cloudflare Page Functions

Securely Manage Authentication Without Exposing Supabase APIs to Clients

secure cloud computing servers

Key Takeaways

  • Enhanced Security: Server-side handling of authentication protects sensitive API keys.
  • Efficient Session Management: Utilize HTTP-only cookies and session tokens for secure user sessions.
  • Scalable Integration: Cloudflare Workers provide a scalable environment for seamless Supabase interactions.

Introduction

Integrating Supabase Authentication within Cloudflare Page Functions allows developers to manage user authentication server-side, enhancing security by preventing direct exposure of Supabase APIs to clients. This comprehensive guide outlines the steps to achieve this integration, ensuring a secure and efficient authentication flow.

Setting Up Supabase with Cloudflare Workers

1. Initialize Supabase Project

Begin by setting up a Supabase project. Obtain your Supabase URL and Service Role Key, which are essential for secure server-side operations. Ensure these credentials are kept confidential and never exposed to the client.

2. Configure Cloudflare Pages with Workers

Create a Cloudflare Pages project if you haven't already. Within this project, you can define server-side functions using Cloudflare Workers. These Workers will act as intermediaries between your client application and Supabase, handling all authentication-related requests securely.

Securely Storing Supabase Keys

1. Use Environment Variables

Store your Supabase credentials as environment variables within the Cloudflare Pages dashboard. This practice ensures that sensitive information remains secure and is not hard-coded into your application.

# Example of setting environment variables
SUPABASE_URL=https://your-project-ref.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key

2. Accessing Environment Variables in Code

In your Cloudflare Worker functions, access these environment variables to initialize the Supabase client securely.

import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
  Deno.env.get('SUPABASE_URL'),
  Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')
);

Passing User Session Token

1. Client-Side Token Retrieval

After authenticating the user on the client side, retrieve the user's session token. This token will be used to authenticate requests to your Cloudflare Worker.

// Client-side code to get the session token
const { data: { session } } = await supabase.auth.getSession();
const accessToken = session.access_token;

// Make a request to the Cloudflare Worker with the token
fetch('/api/auth-function', {
  headers: {
    'Authorization': `Bearer ${accessToken}`
  }
});

2. Sending Token in Request Headers

Include the retrieved session token in the request headers when making API calls to your Cloudflare Worker. This ensures that each request is authenticated and authorized.

Initializing Supabase Client with Auth Context

1. Retrieve Authorization Header

Within your Cloudflare Worker, extract the `Authorization` header from incoming requests to obtain the user's session token.

// Cloudflare Worker code to extract the token
export async function onRequest(context) {
  const authHeader = context.request.headers.get('Authorization');
  if (!authHeader) {
    return new Response('Unauthorized', { status: 401 });
  }
  const token = authHeader.replace('Bearer ', '');
  
  // Initialize Supabase client with the token
  const supabase = createClient(
    Deno.env.get('SUPABASE_URL'),
    Deno.env.get('SUPABASE_SERVICE_ROLE_KEY'),
    {
      global: {
        headers: { Authorization: authHeader },
      },
    }
  );

  // Verify the user
  const { data: { user }, error } = await supabase.auth.getUser(token);
  if (error || !user) {
    return new Response('Unauthorized', { status: 401 });
  }

  // Proceed with authenticated operations
  return new Response(JSON.stringify({ message: 'Authenticated!', user }), {
    headers: { 'Content-Type': 'application/json' },
    status: 200,
  });
}

2. Using Auth Context for Database Operations

With the Supabase client initialized using the user's session token, you can perform database operations that respect the user's permissions and roles, enforced by Row Level Security (RLS) policies.


// Example of fetching user-specific data
const { data: userData, error } = await supabase
  .from('profiles')
  .select('*')
  .eq('id', user.id);

if (error) {
  return new Response(JSON.stringify({ error: error.message }), { status: 500 });
}

return new Response(JSON.stringify(userData), { status: 200 });

Handling Authentication Requests

1. Sign-Up Functionality

Create a Cloudflare Worker function to handle user registrations securely. This function will interact with Supabase to create new user accounts.

// Cloudflare Worker sign-up handler
export async function onRequestPost(context) {
  const { email, password } = await context.request.json();

  const { data, error } = await supabase.auth.signUp({
    email,
    password,
  });

  if (error) {
    return new Response(JSON.stringify({ error: error.message }), { status: 400 });
  }

  return new Response(JSON.stringify({ message: 'User created successfully', data }), { status: 200 });
}

2. Sign-In Functionality

Similarly, implement a sign-in function that authenticates users and returns session tokens.

// Cloudflare Worker sign-in handler
export async function onRequestPost(context) {
  const { email, password } = await context.request.json();

  const { data, error } = await supabase.auth.signInWithPassword({
    email,
    password,
  });

  if (error) {
    return new Response(JSON.stringify({ error: error.message }), { status: 400 });
  }

  // Optionally set HTTP-only cookies here for session management
  return new Response(JSON.stringify({ message: 'Login successful', data }), { status: 200 });
}

3. Token Verification

Implement a function to verify the authenticity of session tokens sent from the client.


// Cloudflare Worker token verification
export async function onRequestPost(context) {
  const { token } = await context.request.json();

  const { data, error } = await supabase.auth.getUser(token);

  if (error || !data.user) {
    return new Response(JSON.stringify({ error: 'Invalid token' }), { status: 401 });
  }

  return new Response(JSON.stringify({ message: 'Token is valid', user: data.user }), { status: 200 });
}

Secure Communication Between Client and Worker

1. Use HTTPS Protocol

Ensure all communications between the client and Cloudflare Workers are conducted over HTTPS to protect data in transit.

2. Implement Rate Limiting and Validation

Protect your Workers from abuse by implementing rate limiting and validating all incoming requests. This can prevent malicious activities such as brute-force attacks.


// Example of rate limiting in a Cloudflare Worker
const RATE_LIMIT = 100; // requests
const WINDOW_SIZE = 60 * 1000; // 1 minute

let requestCounts = {};

export async function onRequest(context) {
  const ip = context.request.headers.get('CF-Connecting-IP');
  const now = Date.now();

  if (!requestCounts[ip]) {
    requestCounts[ip] = [];
  }

  // Remove outdated requests
  requestCounts[ip] = requestCounts[ip].filter(timestamp => now - timestamp < WINDOW_SIZE);

  if (requestCounts[ip].length >= RATE_LIMIT) {
    return new Response('Too Many Requests', { status: 429 });
  }

  requestCounts[ip].push(now);
  
  // Proceed with handling the request
  // ...
}

Managing Sessions and Tokens

1. Use HTTP-Only Cookies

Store session tokens in HTTP-only cookies to prevent client-side scripts from accessing them, mitigating the risk of XSS attacks.


// Setting an HTTP-only cookie in Cloudflare Worker
return new Response('Login successful', {
  status: 200,
  headers: {
    'Set-Cookie': `access_token=${token}; HttpOnly; Secure; Path=/; Max-Age=3600`,
    'Content-Type': 'application/json'
  },
});

2. Session Expiry and Refresh

Implement session expiry and token refresh mechanisms to ensure that user sessions remain secure over time.


// Example of session expiry check
if (Date.now() > sessionExpiry) {
  return new Response('Session expired', { status: 401 });
}

// Function to refresh token
async function refreshToken(oldToken) {
  // Logic to refresh the token using Supabase's API
}

Additional Security Measures

1. Regularly Rotate Supabase Keys

Periodically rotate your Supabase Service Role Keys to minimize the risk of compromised credentials.

2. Implement Logging and Monitoring

Use Cloudflare's logging and monitoring tools to keep track of authentication requests and detect any suspicious activities.


// Example of logging in Cloudflare Worker
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  console.log(`Received request from ${request.headers.get('CF-Connecting-IP')}`);
  // Handle the request
}

Testing and Deployment

1. Deploy to Cloudflare Pages

Deploy your Cloudflare Pages project, ensuring that all environment variables are correctly set and that your Workers are properly configured.

2. Test Authentication Flow

Thoroughly test the authentication flow by signing up, signing in, and accessing protected routes to ensure that everything functions as expected.

# Example of testing with cURL
curl -X POST https://your-cloudflare-worker.com/api/auth-function \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com", "password":"securepassword"}'

Benefits of Server-Side Authentication

Managing authentication on the server side offers numerous advantages:

  • Enhanced Security: Sensitive API keys are never exposed to the client, reducing the risk of unauthorized access.
  • Customizable Logic: Server-side functions allow for the integration of custom authentication workflows, logging, and additional security checks.
  • Scalability: Cloudflare Workers provide a scalable environment capable of handling high volumes of authentication requests with low latency.

Conclusion

Integrating Supabase Authentication with Cloudflare Page Functions offers a robust and secure method for managing user authentication without exposing Supabase APIs to the client. By following the steps outlined in this guide, developers can ensure that their applications maintain high security standards while providing seamless authentication experiences for users.


References


Last updated January 14, 2025
Ask Ithy AI
Export Article
Delete Article