> Markdown version of [Login](https://vaadin.com/docs/latest/components/login). Section index: [llms.txt](https://vaadin.com/docs/latest/components/llms.txt)

# Login

Login is a component that contains a log-in form. You can use it to authenticate the user with a username and password. It’s compatible with password managers, supports internationalization, and works on all device sizes.

**Lit** — `login-basic.ts`

```html
<!-- no-autofocus is used to prevent the example from stealing focus when browsing the documentation -->
<vaadin-login-form no-autofocus></vaadin-login-form>
```

**Flow** — `LoginBasic.java`

```java
LoginForm loginForm = new LoginForm();
add(loginForm);
```

**React** — `login-basic.tsx`

```tsx
{/* no-autofocus is used to prevent the example from stealing focus when browsing the
documentation */}
<LoginForm no-autofocus />
```

## <a id="basic-login-component"></a>Basic Login Component

The basic Login component consists of a title (i.e., "Log In"), two input fields ("Username" and "Password"), and two buttons ("Log In" and "Forgot Password").

You can customize the form’s title and labels using internationalization.

**Lit** — `login-internationalization.ts`

```typescript
private i18n: LoginI18n = {
  form: {
    title: 'Kirjaudu sisään',
    username: 'Käyttäjänimi',
    password: 'Salasana',
    submit: 'Kirjaudu sisään',
    forgotPassword: 'Unohtuiko salasana?',
  },
  errorMessage: {
    title: 'Väärä käyttäjätunnus tai salasana',
    message: 'Tarkista että käyttäjätunnus ja salasana ovat oikein ja yritä uudestaan.',
    username: 'Käyttäjätunnus vaaditaan',
    password: 'Salasana vaaditaan',
  },
};

protected override render() {
  return html`
    <!-- no-autofocus is used to prevent the example from stealing focus when browsing the documentation -->
    <vaadin-login-form .i18n="${this.i18n}" no-autofocus></vaadin-login-form>
  `;
}
```

**Flow** — `LoginInternationalization.java`

```java
LoginI18n i18n = LoginI18n.createDefault();

LoginI18n.Form i18nForm = i18n.getForm();
i18nForm.setTitle("Kirjaudu sisään");
i18nForm.setUsername("Käyttäjänimi");
i18nForm.setPassword("Salasana");
i18nForm.setSubmit("Kirjaudu sisään");
i18nForm.setForgotPassword("Unohtuiko salasana?");
i18n.setForm(i18nForm);

LoginI18n.ErrorMessage i18nErrorMessage = i18n.getErrorMessage();
i18nErrorMessage.setTitle("Väärä käyttäjätunnus tai salasana");
i18nErrorMessage.setMessage(
        "Tarkista että käyttäjätunnus ja salasana ovat oikein ja yritä uudestaan.");
i18nErrorMessage.setUsername("Käyttäjätunnus vaaditaan");
i18nErrorMessage.setPassword("Salasana vaaditaan");
i18n.setErrorMessage(i18nErrorMessage);

LoginForm loginForm = new LoginForm();
loginForm.setI18n(i18n);
```

**React** — `login-internationalization.tsx`

```tsx
const i18n = {
  form: {
    title: 'Kirjaudu sisään',
    username: 'Käyttäjänimi',
    password: 'Salasana',
    submit: 'Kirjaudu sisään',
    forgotPassword: 'Unohtuiko salasana?',
  },
  errorMessage: {
    title: 'Väärä käyttäjätunnus tai salasana',
    message: 'Tarkista että käyttäjätunnus ja salasana ovat oikein ja yritä uudestaan.',
    username: 'Käyttäjätunnus vaaditaan',
    password: 'Salasana vaaditaan',
  },
};

function Example() {
  return (
    <>
      {/* no-autofocus is used to prevent the example from stealing focus when browsing the documentation */}
      <LoginForm i18n={i18n} no-autofocus />
    </>
  );
}
```

The basic Login component can be used to create log-in pages featuring rich content.

**Lit** — `login-rich-content.ts`

```html
<!-- See login-rich-content.css -->
<!-- no-autofocus is used to prevent the example from stealing focus when browsing the documentation -->
<div class="login-rich-content">
  <vaadin-login-form theme="dark" no-autofocus></vaadin-login-form>
</div>
```

`login-rich-content.css`

```css
.login-rich-content {
  background-image: url("../../../src/main/resources/images/earth.jpg");
  background-position: center;
  background-size: cover;
  display: flex;
  height: 500px;
}
.login-rich-content vaadin-login-form {
  align-items: center;
  display: flex;
  max-width: 300px;
  background: var(--vaadin-background-color);
}
.login-rich-content vaadin-login-form::part(form) {
  height: 100%;
  justify-content: center;
}
```

**Flow** — `LoginRichContent.java`

```java
// See login-rich-content.css
addClassName("login-rich-content");

LoginForm loginForm = new LoginForm();
loginForm.getElement().getThemeList().add("dark");
```

**React** — `login-rich-content.tsx`

```tsx
<div className="login-rich-content">
  <LoginForm theme="dark" no-autofocus />
</div>
```

> **Note: Password Managers**
>
> Login is incompatible with password managers if placed inside another component’s shadow root. \[[1](#_footnotedef_1)]

### <a id="handle-the-login-event"></a>Handle the Login Event

When the user submits the login form, the Login component fires a login event with the entered username and password. Listen for this event to authenticate the credentials and handle the result.

The log-in button is disabled after submission to prevent multiple submissions while the login attempt is being processed. If authentication fails, make the form available for another attempt.

**Lit** — `login-event.ts`

```html
<!-- no-autofocus is used to prevent the example from stealing focus when browsing the documentation -->
<vaadin-login-form
  no-autofocus
  .disabled=${this.disabled}
  @login=${this.onLogin}
  @disabled-changed=${this.onDisabledChanged}
></vaadin-login-form>
```

**Flow** — `LoginEventExample.java`

```java
var loginForm = new LoginForm();
loginForm.addLoginListener(this::onLogin);
add(loginForm);
```

**React** — `login-event.tsx`

```tsx
{/* no-autofocus is used to prevent the example from stealing focus when browsing the
documentation */}
<LoginForm
  no-autofocus
  disabled={disabled.value}
  onDisabledChanged={(event: LoginFormDisabledChangedEvent) => {
    disabled.value = event.detail.value;
  }}
  onLogin={() => {
    setTimeout(() => {
      disabled.value = false; // Re-enable login button
    }, 1000);
  }}
/>
```

## <a id="modal-overlay"></a>Modal Overlay

Login features its own modal overlay which is also [modal on server side](https://vaadin.com/docs/latest/flow/advanced/server-side-modality.md#server-side-modality). Use it to create simple log-in pages — which are full-screen on mobile devices — or to handle authentication without a dedicated log-in page. You can also use it to handle re-authentication when the user’s session has expired.

The overlay can be opened programmatically or through user interaction (e.g., by using a log-in button).

**Lit** — `login-overlay-basic.ts`

```html
<vaadin-button
  theme="primary"
  @click="${() => {
    this.loginOpened = true;
  }}"
>
  Log in
</vaadin-button>
<vaadin-login-overlay
  .opened="${this.loginOpened}"
  @login="${() => {
    this.loginOpened = false;
  }}"
></vaadin-login-overlay>
```

**Flow** — `LoginOverlayBasic.java`

```java
LoginOverlay loginOverlay = new LoginOverlay();
add(loginOverlay);

Button login = new Button("Log in");
login.addClickListener(event -> loginOverlay.setOpened(true));
```

**React** — `login-overlay-basic.tsx`

```tsx
<Button
  theme="primary"
  onClick={() => {
    loginOpened.value = true;
  }}
>
  Log in
</Button>

<LoginOverlay
  opened={loginOpened.value}
  onLogin={() => {
    loginOpened.value = false;
  }}
/>
```

### <a id="header"></a>Header

The overlay has a header and the log-in form. By default, the header contains placeholders for the application’s title and description. Both properties are configurable.

**Lit** — `login-overlay-header.ts`

```html
<!-- no-autofocus is used to prevent the example from stealing focus when browsing the documentation -->
<vaadin-login-overlay
  title="TaskMob"
  description="Built with ♥ by Vaadin"
  opened
  no-autofocus
></vaadin-login-overlay>
```

**Flow** — `LoginOverlayHeader.java`

```java
LoginOverlay loginOverlay = new LoginOverlay();
loginOverlay.setTitle("TaskMob");
loginOverlay.setDescription("Built with ♥ by Vaadin");
```

**React** — `login-overlay-header.tsx`

```tsx
<LoginOverlay title="TaskMob" description="Built with ♥ by Vaadin" opened no-autofocus />
```

### <a id="custom-form-area"></a>Custom Form Area

The overlay provides a custom form area for adding fields in addition to username and password. This area is placed above the "Submit" button. Use the `name` attribute to ensure the custom field’s `value` is submitted with the form.

**Lit** — `login-overlay-custom-form-area.ts`

```html
<!-- no-autofocus is used to prevent the example from stealing focus when browsing the documentation -->
<vaadin-login-overlay opened no-autofocus>
  <vaadin-integer-field
    slot="custom-form-area"
    name="code"
    label="One-time code"
  ></vaadin-integer-field>
</vaadin-login-overlay>
```

**Flow** — `LoginOverlayCustomFormArea.java`

```java
LoginOverlay loginOverlay = new LoginOverlay();
IntegerField code = new IntegerField("One-time code");
code.getElement().setAttribute("name", "code");
loginOverlay.getCustomFormArea().add(code);
```

**React** — `login-overlay-custom-form-area.tsx`

```tsx
<LoginOverlay opened no-autofocus>
  <IntegerField slot="custom-form-area" name="code" label="One-time code" />
</LoginOverlay>
```

### <a id="footer"></a>Footer

The footer area can be used for placing additional custom content, such as text, buttons, etc.

**Lit** — `login-overlay-footer.ts`

```html
<!-- no-autofocus is used to prevent the example from stealing focus when browsing the documentation -->
<vaadin-login-overlay opened no-autofocus>
  <p slot="footer" style="text-align: center">Never tell your password to anyone</p>
</vaadin-login-overlay>
```

**Flow** — `LoginOverlayFooter.java`

```java
LoginOverlay loginOverlay = new LoginOverlay();
Paragraph text = new Paragraph("Never tell your password to anyone");
text.getStyle().set("text-align", "center");
loginOverlay.getFooter().add(text);
```

**React** — `login-overlay-footer.tsx`

```tsx
<LoginOverlay opened no-autofocus>
  <p slot="footer" style={{ textAlign: 'center' }}>
    Never tell your password to anyone
  </p>
</LoginOverlay>
```

## <a id="validation"></a>Validation

Login shows an error message when authentication fails. The error message includes a title in addition to the message. It’s displayed directly below the title of the form.

**Lit** — `login-validation.ts`

```html
<!-- no-autofocus is used to prevent the example from stealing focus when browsing the documentation -->
<vaadin-login-overlay opened error no-autofocus></vaadin-login-overlay>
```

**Flow** — `LoginValidation.java`

```java
loginOverlay.setError(true);
```

**React** — `login-validation.tsx`

```tsx
function Example() {
  return <LoginOverlay opened error no-autofocus />;
}
```

The error message is customizable using internationalization. It should contain instructions on how to resolve the problem.

More information can be provided to the user, for example, by linking to a page with helpful material or by displaying contact information.

**Lit** — `login-additional-information.ts`

```typescript
@query('vaadin-login-overlay')
private login!: LoginOverlay;

protected override firstUpdated() {
  this.login.i18n = {
    ...this.login.i18n,
    additionalInformation: `Contact admin@company.com if you're experiencing issues logging into your account`,
  };
}

protected override render() {
  return html`<vaadin-login-overlay opened></vaadin-login-overlay>`;
}
```

**Flow** — `LoginAdditionalInformation.java`

```java
LoginI18n i18n = LoginI18n.createDefault();
i18n.setAdditionalInformation(
        "Contact admin@company.com if you're experiencing issues logging into your account");

LoginOverlay loginOverlay = new LoginOverlay();
loginOverlay.setI18n(i18n);
```

**React** — `login-additional-information.tsx`

```tsx
const loginRef = useRef<LoginOverlayElement>(null);

useEffect(() => {
  if (loginRef.current) {
    loginRef.current.i18n = {
      ...loginRef.current.i18n,
      additionalInformation: `Contact admin@company.com if you're experiencing issues logging into your account`,
    };
  }
}, [loginRef.current]);

return <LoginOverlay ref={loginRef} opened />;
```

## <a id="internationalization-i18n"></a>Internationalization (i18n)

Login’s titles, descriptions, labels, and messages are all customizable using internationalization.

**Lit** — `login-overlay-internationalization.ts`

```typescript
private i18n: LoginI18n = {
  header: {
    title: 'Sovelluksen nimi',
    description: 'Sovelluksen kuvaus',
  },
  form: {
    title: 'Kirjaudu sisään',
    username: 'Käyttäjänimi',
    password: 'Salasana',
    submit: 'Kirjaudu sisään',
    forgotPassword: 'Unohtuiko salasana?',
  },
  errorMessage: {
    title: 'Väärä käyttäjätunnus tai salasana',
    message: 'Tarkista että käyttäjätunnus ja salasana ovat oikein ja yritä uudestaan.',
    username: 'Käyttäjätunnus vaaditaan',
    password: 'Salasana vaaditaan',
  },
  additionalInformation: 'Jos tarvitset lisätietoja käyttäjälle.',
};

protected override render() {
  return html`
    <!-- no-autofocus is used to prevent the example from stealing focus when browsing the documentation -->
    <vaadin-login-overlay .i18n="${this.i18n}" opened no-autofocus></vaadin-login-overlay>
  `;
}
```

**Flow** — `LoginOverlayInternationalization.java`

```java
LoginI18n i18n = LoginI18n.createDefault();

LoginI18n.Header i18nHeader = new LoginI18n.Header();
i18nHeader.setTitle("Sovelluksen nimi");
i18nHeader.setDescription("Sovelluksen kuvaus");
i18n.setHeader(i18nHeader);

LoginI18n.Form i18nForm = i18n.getForm();
i18nForm.setTitle("Kirjaudu sisään");
i18nForm.setUsername("Käyttäjänimi");
i18nForm.setPassword("Salasana");
i18nForm.setSubmit("Kirjaudu sisään");
i18nForm.setForgotPassword("Unohtuiko salasana?");
i18n.setForm(i18nForm);

LoginI18n.ErrorMessage i18nErrorMessage = i18n.getErrorMessage();
i18nErrorMessage.setTitle("Väärä käyttäjätunnus tai salasana");
i18nErrorMessage.setMessage(
        "Tarkista että käyttäjätunnus ja salasana ovat oikein ja yritä uudestaan.");
i18nErrorMessage.setUsername("Käyttäjätunnus vaaditaan");
i18nErrorMessage.setPassword("Salasana vaaditaan");
i18n.setErrorMessage(i18nErrorMessage);

i18n.setAdditionalInformation("Jos tarvitset lisätietoja käyttäjälle.");

LoginOverlay loginOverlay = new LoginOverlay();
loginOverlay.setI18n(i18n);
```

**React** — `login-overlay-internationalization.tsx`

```tsx
const i18n = {
  header: {
    title: 'Sovelluksen nimi',
    description: 'Sovelluksen kuvaus',
  },
  form: {
    title: 'Kirjaudu sisään',
    username: 'Käyttäjänimi',
    password: 'Salasana',
    submit: 'Kirjaudu sisään',
    forgotPassword: 'Unohtuiko salasana?',
  },
  errorMessage: {
    title: 'Väärä käyttäjätunnus tai salasana',
    message: 'Tarkista että käyttäjätunnus ja salasana ovat oikein ja yritä uudestaan.',
    username: 'Käyttäjätunnus vaaditaan',
    password: 'Salasana vaaditaan',
  },
  additionalInformation: 'Jos tarvitset lisätietoja käyttäjälle.',
};

return (
  <>
    {/* no-autofocus is used to prevent the example from stealing focus when browsing the documentation */}
    <LoginOverlay i18n={i18n} opened no-autofocus />
  </>
);
```

### <a id="header-2"></a>Header

The header is only shown for modal log-in forms.

| Property    | Default Value               |
| ----------- | --------------------------- |
| Title       | *"App name"*                |
| Description | *"Application description"* |

### <a id="form"></a>Form

Customize the form’s title, input field, and button labels.

| Property        | Default Value       |
| --------------- | ------------------- |
| Title           | *"Log in"*          |
| Username        | *"Username"*        |
| Password        | *"Password"*        |
| Submit          | *"Log in"*          |
| Forgot password | *"Forgot password"* |

### <a id="error-message"></a>Error Message

Login’s error message is shown when authentication fails. It includes a title in addition to the message.

| Property | Default Value                                                                    |
| -------- | -------------------------------------------------------------------------------- |
| Title    | *"Incorrect username or password"*                                               |
| Message  | *"Check that you have entered the correct username and password and try again."* |

### <a id="additional-information"></a>Additional Information

This property is hidden unless its value is explicitly set.

| Property               | Default Value |
| ---------------------- | ------------- |
| Additional information | -             |

## <a id="technical"></a>Technical

### <a id="handling-events"></a>Handling Events

#### <a id="login-event"></a>Login Event

You can add a listener to log-in events or define an action for which a `POST` request is fired. From the event, you can prevent the `POST` request.

The log-in button is disabled when clicked, to prevent multiple submissions. To restore it, call `component.setEnabled(true)`.

#### <a id="forgotten-password"></a>Forgotten Password

You can add an event listener, which gives you the opportunity to provide your users with instructions for password recovery.

#### <a id="cross-site-request-forgery-csrf-tokens"></a>Cross-Site Request Forgery (CSRF) Tokens

If the page contains the following meta tags with a CSRF token, the token is automatically included in a form `POST` request:

```html
<meta name="_csrf_parameter" content="_csrf">
<meta name="_csrf" content="71dac59f-34ee-4b31-b478-2891cbd0c55d">
```

This token is submitted as `_csrf=71dac59f-34ee-4b31-b478-2891cbd0c55d`, that is, using the `_csrf_parameter` content as the variable name and the `_csrf` content as the value.

`B6AA0496-4D82-4C93-B8FB-64148FF9C88C`

---

[1](#_footnoteref_1). When added to a web component that uses shadow root, password managers are unable to find the input fields and therefore won’t work.
