Skip to main content

Introduction

This guide shows you how to build a custom login page using the Hanko Flow API and the hanko-frontend-sdk. You’ll create a complete authentication interface that supports multiple login methods including email/passcode authentication, passwords, and passkeys with autofill capabilities. The page will include full session management with login redirects and logout functionality. By the end, you’ll have a working login page that:
  • Initializes the login flow via the /login endpoint.
  • Dynamically renders the UI based on the current flow state.
  • 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

1

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.
2

Configure the project

To reduce the complexity of this example, we disable certain login features:
  • In the sidebar, 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.
3

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.
  • From the list of users, click on the newly created entry.
  • Under “Passwords”, click on Set password.
  • Enter a password and click Create password
4

Obtain your API URL

  1. In the sidebar, select Dashboard.
  2. Find your project’s API URL (e.g., https://<project-id>.hanko.io).
5

Set up the project structure

Create a project folder (e.g., hanko-login-page) and set up the following files:
6

Update 'package.json'

7

Install dependencies

Run in the project folder:
8

Update 'index.html' (the login page)

9

Update 'success.html' (shown after login)

10

Update 'style.css'

11

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, and hanko.onSessionCreated redirects to success.html on successful login.
  • On success.html, the logout button calls hanko.logout(), and hanko.onUserLoggedOut redirects back to the index.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!
1

Run the application

  • Ensure the Hanko Cloud project is configured as described (App URL: http://localhost:3000, no 2FA, device trust “Never”).
  • Update API_URL in script.js with your Hanko Cloud project’s API endpoint.
  • Rebuild the App:
  • Run the local server:
  • Open http://localhost:3000 in your browser.
2

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.
3

Troubleshooting

  • CORS Errors: Ensure the App URL in the Hanko Cloud dashboard matches http://localhost:3000.
  • Invalid API URL: Verify the API_URL in script.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 passwords, passkeys and 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.

References