Build a Custom Login Page with the FlowAPI
A step-by-step guide to create a custom login page using the Hanko FlowAPI.
Introduction
This guide walks you through building a custom login page for the Hanko FlowAPI using the hanko-frontend-sdk
. The
resulting page handles email and passcode login, supports passkey autofill, and includes session management (redirect
after login and logout functionality). The FlowAPI is part of Hanko, a user authentication platform, and we’ll use a
Hanko Cloud project configured for simplicity.
By the end, you’ll have a working login page that:
- Initializes the login flow via the
/login
endpoint. - Dynamically renders UI for the states:
error
,login_init
,login_method_chooser
,onboarding_create_passkey
, andpasscode_confirmation
. - Handles user inputs, errors, and session events.
- Runs locally at
http://localhost:3000
and authenticates a test user.
Prerequisites
Before starting, ensure you have:
- Node.js installed for running a local server and installing dependencies.
- A modern browser (e.g., Chrome, Firefox) for testing passkey autofill.
- A Hanko Cloud project set up with a test user (see Step 1).
- Basic knowledge of JavaScript, HTML, and CSS.
Step 1: Set Up the Development Environment
Create a Hanko Cloud Project
- Go to cloud.hanko.io and log in.
- In the sidebar, select All Projects.
- Click Create Project to open the setup wizard.
- Choose Hanko (“Authentication and user management”) as the project type and click Create Project.
- Enter a project name (e.g., “Custom Login Page”).
- Set the App URL to
http://localhost:3000
(where the login page will run locally). - Click Create Project to complete the wizard.
Configure the Project
- In the sidebar, go to Settings > Authentication.
- Uncheck Passwords, to turn off password authentication.
- Click Save.
- Go to Settings > 2FA.
- Uncheck the entire 2FA section.
- Click Save.
- Under Device trust (further down on the same page):
- Select Never as the “Device trust policy” from the dropdown.
- Click Save.
Create a Test User
- In the sidebar, select Users.
- Click Create new to open the user creation wizard.
- Enter your real email address (in order to receive passcodes).
- Click Create new User to finish.
Obtain your API URL
- In the sidebar, select Dashboard.
- Find your project’s API URL (e.g.,
https://<project-id>.hanko.io
).
Set Up the Project Structure
Create a project folder (e.g., hanko-login-page
) and set up the following files:
Update 'package.json'
Install Dependencies
Run in the project folder:
Update 'index.html' (the login page)
Update 'success.html' (shown after login)
Update 'style.css'
Start the Local Server
Run the following to start the server at http://localhost:3000:
Open http://localhost:3000
in your browser to verify the page loads (it will be empty until we add JavaScript).
Step 2: Initialize the Login Flow
In script.js
, initialize the Hanko instance and start the login flow. If the user is on success.html
, set up logout
functionality instead.
Replace https://<your-project-id>.hanko.io
with your project’s API endpoint from the Hanko Cloud dashboard.
Step 3: Handle Flow States and Render UI
Implement handler functions to process each state and render the appropriate UI. The hanko.onAfterStateChange
event is
used to update the UI after state transitions. We’ll also create a generateInput
function to dynamically generate input
elements with validation attributes (e.g., minlength, maxlength, required) based on the FlowAPI’s input metadata.
Add the following code to the script.js
file:
- The action execution logic is embedded in each state’s form or button handlers.
- The
hanko.onAfterStateChange
event ensures the UI updates after each action, andhanko.onSessionCreated
redirects tosuccess.html
on successful login. - On
success.html
, the logout button callshanko.logout()
, andhanko.onUserLoggedOut
redirects back to theindex.html
. - Validation Errors: Each state renderer checks for
state.actions.<action>.inputs.<input>.error
and displays the message (e.g., invalid passcode). - Technical Errors: The error state handler displays
state.error.message
.
Step 4: Run and Test the Login Page
Always use your own email address in the following steps. The Hanko API sends real emails, so proceed with caution!
Run the Application
- Ensure the Hanko Cloud project is configured as described (App URL:
http://localhost:3000
, no passwords, no 2FA, device trust “Never”). - Update
API_URL
inscript.js
with your Hanko Cloud project’s API endpoint. - Rebuild the App:
- Run the local server:
- Open
http://localhost:3000
in your browser.
Test the Login Flow
- Enter the test user’s email.
- Check your email for the passcode, enter the code, and click submit.
- If prompted, register a passkey.
- On success, you’ll be redirected to
success.html
. - Click Log Out to return to the login page.
Troubleshooting
- CORS Errors: Ensure the App URL in the Hanko Cloud dashboard matches
http://localhost:3000
. - Invalid API URL: Verify the
API_URL
inscript.js
. - No Passcode Received: Confirm the test user’s email is correct and check your spam folder.
- Passkey Autofill Not Working: Use a passkey-compatible browser (e.g., Chrome) and ensure the input has
autocomplete="username webauthn"
.
Conclusion
You’ve built a working login page that:
- Uses the FlowAPI and hanko-frontend-sdk to handle email/passcode login.
- Supports passkey autofill in the
login_init
state. - Manages sessions with redirect after login and logout functionality.
- Handles errors gracefully across all specified states.
Explore next steps like enhancing the UI with advanced CSS or a framework like Bootstrap, adding support for additional states or actions (e.g., password login), or integrating the login page into a larger application. Additionally, the FlowAPI supports registration and user profile management flows.