DEV Community

Palomino for Logto

Posted on • Originally published at blog.logto.io

Bring your own sign-in UI to Logto Cloud

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:

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.
Image description

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.
Image description
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>

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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>
);

Enter fullscreen mode Exit fullscreen mode

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>

Enter fullscreen mode Exit fullscreen mode

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);
    }
  });
};

Enter fullscreen mode Exit fullscreen mode

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

  1. Go to your application and click the "Sign in" button.
  2. You should be redirected to your custom sign-in page at http://localhost:9000/.
  3. Enter username and password, and click the "Submit" button.
  4. 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.
Image description
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.
Image description
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! 🚀

Try Logto Cloud for free

Top comments (0)