This tutorial will guide you through the process of creating and deploying your own custom sign-in UI to Logto Cloud.
Background
Logto provides an out-of-box sign-in experience UI that covers all Logto features, including sign-in, registration, password recovery, single sign-on (SSO), and more. Users can also customize the look and feel of the sign-in experience UI using our "Custom CSS" feature.
However, some users still want to deeply customize their sign-in experience (both UI and auth flows) to match their branding and specific business requirements. We've heard you! And we're excited to announce that the "Bring your own UI" feature is now available in Logto Cloud.
In this tutorial, we'll guide you through the steps to create and deploy your own custom sign-in UI to Logto Cloud.
Prerequisites
Before you start, ensure you have the following:
- A Logto Cloud account with a subscription plan
- An application integrated with Logto (Quick-starts)
- Logto tunnel CLI installed
- Basic knowledge of HTML, CSS, and JavaScript
For simplicity, we will use the classic "username & password" sign-in method in the following steps. Remember to change your sign-in method in Logto Console.
Create your custom sign-in UI
The minimum requirement for a sign-in UI is to have an index.html
file, with a sign-in form that includes at least a username input, a password input, and a submit button. I used ChatGPT to generate a sample HTML, and here I come with this pinky lovely sign-in page.
I have omitted the CSS styles for simplicity, and here is how simple the HTML looks like:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Fun Sign-in Page</title>
</head>
<body>
<div>
<h1>Welcome Back</h1>
<form id="signInForm">
<div>
<label for="username">Username</label>
<input type="text" name="username" required />
</div>
<div>
<label for="password">Password</label>
<input type="password" name="password" required />
</div>
<button type="submit">Sign in</button>
</form>
</div>
</body>
</html>
You can also start with a boilerplate from your favorite front-end framework, such as Create React App, Next.js, or Vue CLI.
Since Logto is open source, another recommendation is to clone the Logto Experience project, and modify the code to fit your needs. This is the full feature Logto built-in sign-in experience UI, written in React and TypeScript.
Setup Logto tunnel CLI
Logto tunnel CLI is a tool that not only servers your HTML pages, but also allows you to interact with Logto's Experience API from your HTML pages in local dev environment.
Assuming your index.html
page is located in /path/to/your/custom-ui
, and your Logto tenant ID is foobar
, you can run the command this way:
npx @logto/tunnel --path /path/to/your/custom-ui --endpoint https://foobar.logto.app/ -p 9000
Or, if you are using a UI framework that has a built-in development server, and your page is served at http://localhost:4000
, you can run the command like this:
npx @logto/tunnel --uri http://localhost:4000 --endpoint https://foobar.logto.app/ -p 9000
After running the command, the tunnel service will be started on your local machine http://localhost:9000/
.
Trigger sign-in from your application
Go to the application you created earlier, and change the Logto endpoint from https://foobar.logto.app/
to http://localhost:9000/
in your Logto SDK config.
Let's take our React sample project as an example:
import { LogtoProvider, LogtoConfig } from '@logto/react';
const config: LogtoConfig = {
// endpoint: 'https://foobar.logto.app/', // original Logto Cloud endpoint
endpoint: 'http://localhost:9000/', // tunnel service address
appId: '<your-application-id>',
};
const App = () => (
<LogtoProvider config={config}>
<YourAppContent />
</LogtoProvider>
);
Click the "Sign in" button in your application. Instead of seeing the built-in Logto sign-in UI, you should now be redirected to your custom sign-in page.
Interact with Logto Experience API
In this step, we will interact with Logto Experience API in your custom UI. First, let's create a script.js
file and add the reference in your index.html
.
<html>
<!-- Omitted code ... -->
<body>
<!-- Omitted code ... -->
<script src="script.js"></script>
</body>
</html>
Put the following code in your script.js
file.
window.onload = function () {
const form = document.getElementById('loginForm');
form.addEventListener('submit', async function (event) {
event.preventDefault();
const formData = new FormData(event.target);
try {
await fetch('/api/experience', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ interactionEvent: 'SignIn' }),
});
const verificationResponse = await fetch('/api/experience/verification/password', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
identifier: { type: 'username', value: formData.get('username') },
password: formData.get('password'),
}),
});
const { verificationId } = await verificationResponse.json();
await fetch('/api/experience/identification', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ verificationId }),
});
const submitReponse = await fetch('/api/experience/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
});
const { redirectTo } = await submitReponse.json();
window.location.replace(redirectTo);
} catch (error) {
console.error('Oops!', error);
}
});
};
This script will complete the username and password sign-in flow with the help of these APIs:
-
PUT /api/experience
- Start the sign-in interaction -
POST /api/experience/verification/password
- Verify the username and password -
POST /api/experience/identification
- Identify user for the current interaction -
POST /api/experience/submit
- Submit the sign-in interaction Refer to Logto Experience API docs for more details.
Test your custom sign-in page
- Go to your application and click the "Sign in" button.
- You should be redirected to your custom sign-in page at
http://localhost:9000/
. - Enter username and password, and click the "Submit" button.
- If everything is set up correctly, you should be redirected back to your application, with authenticated user information.
Deploy your custom sign-in UI to Logto Cloud
Once you have finished developing and testing your custom sign-in UI locally, you can deploy it to Logto Cloud. Simply create a zip file of your custom UI folder and upload it to the "Custom UI" section in your Logto Console.
After uploading, save the changes, and your custom sign-in UI will go live in your Logto Cloud tenant, replacing the built-in Logto sign-in experience.
Finally, go back to your application and change the endpoint URI back to your Logto cloud endpoint: https://foobar.logto.app/
. This time, you can stop the Logto tunnel service, and your application should now work directly with the custom UI hosted online.
Conclusion
In this tutorial, we've walked you through the process of implementing and deploying your own custom sign-in UI to Logto Cloud.
With this feature, you can now deeply customize your sign-in UI and auth flows to match your branding and specific business requirements.
Happy coding! 🚀