How to Implement Basic Authorization in Astro
LaunchFast Logo LaunchFast

How to Implement Basic Authorization in Astro

Rishi Raj Jain
How to Implement Basic Authorization in Astro

When building web applications, there are times when you need to protect your routes before launching to production. Whether you’re working on a client project that needs to be hidden from the public or you want to add a simple authentication layer to your development environment, basic authorization is a quick and effective solution.

High Quality Starter Kits with built-in authentication flow (Auth.js), object uploads (AWS, Clouflare R2, Firebase Storage, Supabase Storage), integrated payments (Stripe, LemonSqueezy), email verification flow (Resend, Postmark, Sendgrid), and much more. Compatible with any database (Redis, Postgres, MongoDB, SQLite, Firestore).
Next.js Starter Kit
SvelteKit Starter Kit
Need a custom landing page built?

In this guide, we’ll walk through how to implement basic authentication in your Astro application using middleware. This approach is perfect for temporary protection during development or staging phases.

Table Of Contents

What is Basic Authentication?

Basic authentication is a simple authentication scheme built into the HTTP protocol. It works by:

  1. Client Request: The browser sends a request to a protected route
  2. Server Challenge: The server responds with a 401 Unauthorized status and a WWW-Authenticate header
  3. Browser Prompt: The browser shows a login dialog to the user
  4. Credentials: The user enters username/password, which gets encoded and sent with subsequent requests
  5. Validation: The server validates the credentials and either allows or denies access

Step-by-Step Implementation

Step 1: Create a new Astro application

Let’s get started by creating a new Astro project. Execute the following command:

Terminal window
npm create astro@latest my-app

npm create astro is the recommended way to scaffold an Astro project quickly.

When prompted, choose:

  • Empty when prompted on how to start the new project.
  • Yes when prompted if plan to write Typescript.
  • Strict when prompted how strict Typescript should be.
  • Yes when prompted to install dependencies.
  • Yes when prompted to initialize a git repository.

Once that’s done, you can move into the project directory and start the app:

Terminal window
cd my-app
npm run dev

The app should be running on localhost:4321.

Step 2: Integrate Node.js adapter in your Astro project

To enable server-side rendering in your Astro project via the Node.js adapter. Execute the following command:

Terminal window
npx astro add node

When prompted, choose the following:

  • Yes when prompted whether to install the Node.js dependencies.
  • Yes when prompted whether to make changes to Astro configuration file.

This will install the necessary dependencies and update your astro.config.mjs file.

Step 3: Create a Middleware File

Create a new file called middleware.ts in your src/ directory with the following code:

src/middleware.ts
import { defineMiddleware } from 'astro:middleware'
// Define protected routes that require "basic authentication"
// (only to put the pages behind a basic auth before you actually launch your application to the world)
const PROTECTED_ROUTES = [
// '/',
// '/signin'
]
// Basic credentials (in production, use environment variables)
const VALID_CREDENTIALS = {
username: 'admin',
password: 'password123',
}
export const onRequest = defineMiddleware(async (context, next) => {
const { url, request } = context
const pathname = new URL(url).pathname
// Check if the current route is protected
const isProtectedRoute = PROTECTED_ROUTES.some((route) =>
(route === '/' ? pathname === route : pathname.startsWith(route))
)
// For protected routes, check authentication
if (isProtectedRoute) {
const authHeader = request.headers.get('authorization')
if (!authHeader || !authHeader.startsWith('Basic ')) {
// Return 401 Unauthorized with WWW-Authenticate header
return new Response('Authentication required', {
status: 401,
headers: {
'WWW-Authenticate': 'Basic realm="Secure Area"',
'Content-Type': 'text/plain',
},
})
}
// Extract and decode credentials
const encodedCredentials = authHeader.substring(6)
const decodedCredentials = atob(encodedCredentials)
const [username, password] = decodedCredentials.split(':')
// Validate credentials
if (username !== VALID_CREDENTIALS.username || password !== VALID_CREDENTIALS.password) {
return new Response('Invalid credentials', {
status: 401,
headers: {
'WWW-Authenticate': 'Basic realm="Secure Area"',
'Content-Type': 'text/plain',
},
})
}
}
// Continue to the next middleware/route handler
return next()
})

Step 4: Configure Protected Routes

In the middleware file, you can specify which routes should be protected by uncommenting or adding routes to the PROTECTED_ROUTES array:

src/middleware.ts
const PROTECTED_ROUTES = [
'/', // Protect the homepage
'/admin', // Protect all routes starting with /admin
'/dashboard', // Protect all routes starting with /dashboard
'/api', // Protect all API routes
]

For production use, it’s better to use environment variables instead of hardcoded credentials. Create a .env file:

.env
BASIC_AUTH_USERNAME=admin
BASIC_AUTH_PASSWORD=your-secure-password

Then update the middleware to use these environment variables:

middleware.ts
const VALID_CREDENTIALS = {
username: import.meta.env.BASIC_AUTH_USERNAME || 'admin',
password: import.meta.env.BASIC_AUTH_PASSWORD || 'password123',
}

How It Works

1. Route Protection Logic

The middleware checks if the current route is in the PROTECTED_ROUTES array:

const isProtectedRoute = PROTECTED_ROUTES.some((route) =>
(route === '/' ? pathname === route : pathname.startsWith(route))
)

This allows for flexible route matching:

  • Exact matches: '/' matches only the homepage
  • Prefix matches: '/admin' matches /admin, /admin/users, /admin/settings, etc.

2. Authentication Flow

When a user visits a protected route:

  1. No Auth Header: If no Authorization header is present, the server returns a 401 response with a WWW-Authenticate header
  2. Browser Prompt: The browser shows a login dialog
  3. Credentials Sent: User enters credentials, browser sends them encoded in base64
  4. Validation: Server decodes and validates the credentials
  5. Access Granted/Denied: If valid, the request continues; if invalid, another 401 is returned

Conclusion

Basic authentication in Astro is a straightforward way to protect your routes during development or staging. While it’s not suitable for production user authentication, it’s perfect for:

  • Development Protection: Hide work-in-progress features
  • Client Demos: Protect client projects before launch
  • Staging Environments: Secure staging sites
  • Admin Areas: Quick protection for admin interfaces

The middleware approach we’ve implemented is clean, efficient, and easy to customize for your specific needs. Remember to use environment variables for credentials and consider more robust authentication solutions for production applications.

Learn More Cloudflare D1 Database Support Now Available in LaunchFast Starter Kits
Cloudflare D1 Database Support Now Available in LaunchFast Starter Kits July 3, 2025
Mailgun Email Support Now Available in LaunchFast Starter Kits
Mailgun Email Support Now Available in LaunchFast Starter Kits June 7, 2025
Query Cloud Firestore with Astro on Cloudflare Workers
Query Cloud Firestore with Astro on Cloudflare Workers April 25, 2025