feat: allow to disable auth during development (#21)

This commit is contained in:
Dominic Elm 2024-07-30 10:31:35 +02:00 committed by GitHub
parent 4df1da4908
commit 58af0dea8c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 11 additions and 20 deletions

View File

@ -37,10 +37,10 @@ VITE_LOG_LEVEL=debug
``` ```
If you want to run authentication against a local StackBlitz instance, add: If you want to run authentication against a local StackBlitz instance, add:
``` ```
VITE_CLIENT_ORIGIN=https://local.stackblitz.com:3000 VITE_CLIENT_ORIGIN=https://local.stackblitz.com:3000
``` ```
`
**Important**: Never commit your `.env.local` file to version control. It's already included in .gitignore. **Important**: Never commit your `.env.local` file to version control. It's already included in .gitignore.

View File

@ -47,7 +47,7 @@ export function ChatImpl({ initialMessages, storeMessageHistory }: ChatProps) {
const { messages, isLoading, input, handleInputChange, setInput, handleSubmit, stop, append } = useChat({ const { messages, isLoading, input, handleInputChange, setInput, handleSubmit, stop, append } = useChat({
api: '/api/chat', api: '/api/chat',
onError: (error) => { onError: (error) => {
logger.error(error); logger.error('Request failed\n\n', error);
toast.error('There was an error processing your request'); toast.error('There was an error processing your request');
}, },
onFinish: () => { onFinish: () => {

View File

@ -1,6 +1,6 @@
import { ClientOnly } from 'remix-utils/client-only'; import { ClientOnly } from 'remix-utils/client-only';
import { OpenStackBlitz } from './OpenStackBlitz.client';
import { IconButton } from '~/components/ui/IconButton'; import { IconButton } from '~/components/ui/IconButton';
import { OpenStackBlitz } from './OpenStackBlitz.client';
export function Header() { export function Header() {
return ( return (

View File

@ -1,12 +1,5 @@
import { env } from 'node:process';
import { isAuthenticated } from './sessions';
import { json, redirect, type LoaderFunctionArgs } from '@remix-run/cloudflare'; import { json, redirect, type LoaderFunctionArgs } from '@remix-run/cloudflare';
import { isAuthenticated } from './sessions';
export function verifyPassword(password: string, cloudflareEnv: Env) {
const loginPassword = env.LOGIN_PASSWORD || cloudflareEnv.LOGIN_PASSWORD;
return password === loginPassword;
}
type RequestArgs = Pick<LoaderFunctionArgs, 'request' | 'context'>; type RequestArgs = Pick<LoaderFunctionArgs, 'request' | 'context'>;
@ -14,7 +7,7 @@ export async function handleAuthRequest<T extends RequestArgs>(args: T, body: ob
const { request, context } = args; const { request, context } = args;
const { authenticated, response } = await isAuthenticated(request, context.cloudflare.env); const { authenticated, response } = await isAuthenticated(request, context.cloudflare.env);
if (authenticated) { if (authenticated || import.meta.env.VITE_DISABLE_AUTH) {
return json(body, response); return json(body, response);
} }
@ -25,7 +18,7 @@ export async function handleWithAuth<T extends RequestArgs>(args: T, handler: (a
const { request, context } = args; const { request, context } = args;
const { authenticated, response } = await isAuthenticated(request, context.cloudflare.env); const { authenticated, response } = await isAuthenticated(request, context.cloudflare.env);
if (authenticated) { if (authenticated || import.meta.env.VITE_DISABLE_AUTH) {
const handlerResponse = await handler(args); const handlerResponse = await handler(args);
if (response) { if (response) {

View File

@ -1,7 +1,7 @@
import { createCookieSessionStorage, redirect } from '@remix-run/cloudflare'; import { createCookieSessionStorage, redirect } from '@remix-run/cloudflare';
import { decodeJwt } from 'jose'; import { decodeJwt } from 'jose';
import { request as doRequest } from '~/lib/fetch';
import { CLIENT_ID, CLIENT_ORIGIN } from '~/lib/constants'; import { CLIENT_ID, CLIENT_ORIGIN } from '~/lib/constants';
import { request as doRequest } from '~/lib/fetch';
import { logger } from '~/utils/logger'; import { logger } from '~/utils/logger';
const DEV_SESSION_SECRET = import.meta.env.DEV ? 'LZQMrERo3Ewn/AbpSYJ9aw==' : undefined; const DEV_SESSION_SECRET = import.meta.env.DEV ? 'LZQMrERo3Ewn/AbpSYJ9aw==' : undefined;
@ -33,7 +33,7 @@ export async function isAuthenticated(request: Request, env: Env) {
try { try {
data = await refreshToken(token); data = await refreshToken(token);
} catch { } catch {
// ignore // we can ignore the error here because it's handled below
} }
if (data != null) { if (data != null) {

View File

@ -1,16 +1,16 @@
import { import {
json, json,
redirect, redirect,
redirectDocument,
type ActionFunctionArgs, type ActionFunctionArgs,
type LoaderFunctionArgs, type LoaderFunctionArgs,
redirectDocument,
} from '@remix-run/cloudflare'; } from '@remix-run/cloudflare';
import { useFetcher, useLoaderData } from '@remix-run/react'; import { useFetcher, useLoaderData } from '@remix-run/react';
import { auth, type AuthAPI } from '@webcontainer/api'; import { auth, type AuthAPI } from '@webcontainer/api';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { createUserSession, isAuthenticated, validateAccessToken } from '~/lib/.server/sessions'; import { createUserSession, isAuthenticated, validateAccessToken } from '~/lib/.server/sessions';
import { request as doRequest } from '~/lib/fetch';
import { CLIENT_ID, CLIENT_ORIGIN } from '~/lib/constants'; import { CLIENT_ID, CLIENT_ORIGIN } from '~/lib/constants';
import { request as doRequest } from '~/lib/fetch';
import { logger } from '~/utils/logger'; import { logger } from '~/utils/logger';
export async function loader({ request, context }: LoaderFunctionArgs) { export async function loader({ request, context }: LoaderFunctionArgs) {
@ -49,7 +49,7 @@ export async function action({ request, context }: ActionFunctionArgs) {
throw await response.json(); throw await response.json();
} }
} catch (error) { } catch (error) {
logger.warn('Authentication failure'); logger.warn('Authentication failed');
logger.warn(error); logger.warn(error);
return json({ error: 'invalid-token' as const }, { status: 401 }); return json({ error: 'invalid-token' as const }, { status: 401 });
@ -100,7 +100,6 @@ export default function Login() {
<div> <div>
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">Login</h2> <h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">Login</h2>
</div> </div>
{redirected ? 'Processing auth...' : <LoginForm />} {redirected ? 'Processing auth...' : <LoginForm />}
</div> </div>
</div> </div>
@ -162,7 +161,6 @@ function LoginForm() {
> >
{login?.kind === 'pending' ? 'Authenticating...' : 'Continue with StackBlitz'} {login?.kind === 'pending' ? 'Authenticating...' : 'Continue with StackBlitz'}
</button> </button>
{login?.kind === 'error' && ( {login?.kind === 'error' && (
<div> <div>
<h2> <h2>