Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@ CRYSTALLIZE_TENANT_ID=xXx
CRYSTALLIZE_ACCESS_TOKEN_ID=xXx
CRYSTALLIZE_ACCESS_TOKEN_SECRET=xXx

#Stripe
# Stripe
NEXT_PUBLIC_STRIPE_PUBLIC_KEY=xXx
STRIPE_SECRET_KEY=xXx
STRIPE_WEBHOOK_SECRET=xXx

#Mailer
# Mailer
MAILER_DSN=xXx

CANONICAL_URL=https://example.com

# Basic Auth
BASIC_AUTH=
BASIC_USER=demo
BASIC_PASSWORD=demo
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,12 @@ Check out our [Next.js deployment documentation](https://nextjs.org/docs/deploym

## Testing
Attributes with `data-testid` have been added to elements to simplify test implementation. You can use any testing library of your choice to create the tests.


## Basic Auth
For basic authentication,
you can use the `BASIC_AUTH` and `BASIC_USER` and `BASIC_PASSWORD` environment variables to enable basic auth.
To enable it, set the `BASIC_AUTH` to some string, preferable `true`,
and choose a **username** and **password** to the other two variables.

To disable it, set `BASIC_AUTH` to empty string.
9 changes: 9 additions & 0 deletions app/api/auth/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export async function GET(request: Request) {
return new Response('Auth Required', {
status: 401,
headers: {
'WWW-authenticate': 'Basic realm="Secure Area"',
},
});

}
42 changes: 36 additions & 6 deletions middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,48 @@
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

const BASIC_AUTH = Boolean(process.env.BASIC_AUTH);
const BASIC_USER = process.env.BASIC_USER;
const BASIC_PASSWORD = process.env.BASIC_PASSWORD;

export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// If the path ends with .pdf, log or handle it
if (pathname.endsWith('.pdf')) {
request.nextUrl.pathname = `/pdf${pathname.replace(/\.pdf$/, '/pdf')}`;
return NextResponse.rewrite(request.nextUrl);
const basicAuth = request.headers.get('authorization');
const url = request.nextUrl;

// If basic auth is enabled, check the request headers
if (BASIC_AUTH && BASIC_USER && BASIC_PASSWORD) {
// If the request is authenticated, let the user continue
if (basicAuth) {
const authValue = basicAuth.split(' ')[1];
const [user, pwd] = atob(authValue).split(':');

// If the user is authenticated, allow the request to continue
if (user === BASIC_USER && pwd === BASIC_PASSWORD) {
// If the path ends with .pdf, handle it
if (url.pathname.endsWith('.pdf')) {
url.pathname = `/pdf${url.pathname.replace(/\.pdf$/, '/pdf')}`;
return NextResponse.rewrite(url);
}

return NextResponse.next();
}
}

// If the request is not authenticated, ask for credentials
url.pathname = '/api/auth';
return NextResponse.rewrite(url);
}

// If the path ends with .pdf, handle it
if (url.pathname.endsWith('.pdf')) {
url.pathname = `/pdf${url.pathname.replace(/\.pdf$/, '/pdf')}`;
return NextResponse.rewrite(url);
}

return NextResponse.next();
}

// Limit middleware to only product routes if desired
export const config = {
matcher: ['/products/:path*', '/entertainment/:path*'],
matcher: ['/', '/index', '/:path*'],
};