mkdir -p plash-auth-tutorial
cd plash-auth-tutorial
TODO: More explanation on the T&C’s between plash<->devs<->users<->plash
Setting up Google OAuth authentication traditionally requires: - Google Cloud Console project setup and OAuth consent screen configuration - Secure credential management and rotation in production - Managing redirect URLs across development, staging, and production environments - Complex local testing workarounds (OAuth typically breaks without HTTPS and registered domains)
Plash Auth eliminates this complexity by providing a simple wrapper around the OAuth flow. We handle all the Google Cloud setup, credential management, and redirect configuration for you.
Plash provides a streamlined OAuth flow:
The system automatically adapts to your environment—real OAuth in production, mock auth for local development and testing.
Trade-offs: Plash Auth provides the user’s globally unique Google ID for authentication. If you need access to user data (name, email) or Google services (Drive, Gmail), you’ll need to implement your own OAuth flow (FastHTML OAuth documentation).
For most applications that just need secure user authentication, Plash Auth is the simplest solution.
This tutorial will show you how to add Google OAuth authentication to your FastHTML apps deployed on Plash. With Plash’s built-in auth system, you can easily implement secure sign-in functionality without managing OAuth secrets or redirect URLs yourself.
Prerequisites:
In this tutorial we’ll focus on FastHTML. But any Plash app can technically make use of Plash Auth.
Let’s create a new directory for our auth example:
Create your main.py
file with the auth functionality:
import os
# Check environment variable
plash_production = os.getenv('PLASH_PRODUCTION')
if plash_production:
from plash_cli.auth import make_plash_signin_url, goog_id_from_signin_reply, APP_SIGNIN_PATH
else:
from plash_cli.auth_mock import make_plash_signin_url, goog_id_from_signin_reply, APP_SIGNIN_PATH
from fasthtml.common import *
app, rt = fast_app()
@rt
def index(session):
user_id = session.get('user_id')
if user_id:
return Div(
H1("Welcome to My Plash App!"),
P(f"You are logged in as user: {user_id}"),
A("Protected Page", href="/protected"),
Br(), Br(),
A("Logout", href="/logout")
)
else:
return Div(
H1("Welcome to My Plash App!"),
P("Please sign in to access the app."),
A("Sign in with Google", href=make_plash_signin_url(session))
)
@rt('/protected')
def protected_page(session):
user_id = session.get('user_id')
if not user_id:
return RedirectResponse('/', status_code=303)
return Div(
H1("Protected Page"),
P(f"This page is only accessible to authenticated users."),
P(f"Your user ID: {user_id}"),
A("Back to Home", href="/")
)
@rt('/logout')
def logout(session):
session.pop('user_id', None)
return RedirectResponse('/', status_code=303)
@rt(APP_SIGNIN_PATH)
def plash_signin_completed(session, signin_reply: str):
uid = goog_id_from_signin_reply(session, signin_reply)
if uid is None:
return Div(
H2("Login Failed"),
P("There was an error signing you in. Please try again."),
A("Try Again", href="/")
)
else:
session['user_id'] = uid
return RedirectResponse('/', status_code=303)
serve()
Create your requirements.txt
file with the necessary packages:
We’re using the feat-add-oauth
branch of plash_cli which contains the latest auth functionality. Once this feature is merged, you can use the main branch.
Let’s break down the key components of our auth app:
Plash automatically sets the PLASH_PRODUCTION
environment variable when your app runs in production. This allows your app to use real OAuth in production and mock auth for local testing.
make_plash_signin_url(session)
: Generates a sign-in URL that starts the OAuth flowgoog_id_from_signin_reply(session, signin_reply)
: Verifies the OAuth response and returns the user’s Google IDAPP_SIGNIN_PATH
: The path (/signin_completed
) where Plash redirects after authenticationThe app stores the user ID in the session after successful authentication:
To let only logged-in users access a given route, you can check if the user_id
is set in the session.
Now let’s deploy the app to see authentication in action:
Visit your deployed app and test the authentication flow:
You should see:
“Invalid request” error during OAuth - Make sure your app is deployed and accessible at the URL Plash expects - Check that your requirements.txt includes the correct plash_cli version
Mock auth not working locally - Ensure PLASH_PRODUCTION
environment variable is not set when testing locally - Verify you’re importing from plash_cli.auth_mock
in development mode
Session not persisting - Make sure you’re using FastHTML’s session management correctly - Check that cookies are enabled in your browser