> Markdown version of [Session Expiration](https://vaadin.com/docs/next/hilla/lit/guides/security/session-expiration). Section index: [llms.txt](https://vaadin.com/docs/next/hilla/llms.txt)

# Handling Session Expiration

You can use the built-in [middleware](https://vaadin.com/docs/next/hilla/guides/client-middleware.md) `InvalidSessionMiddleWare` to detect when a user session expires.

This middleware requires a function as a constructor parameter (type of `OnInvalidSessionCallback`). The function should return a promise of `LoginResult`, containing the metadata of a login result, including:

- `error`

  Indicates whether the login attempt has failed.

- `token`

  In the event of a successful login, this is the cross-site request forgery (CSRF) prevention token, which can be extracted from the `index.html` page. See [CSRF protection of browser-callable services](https://vaadin.com/docs/next/hilla/guides/security/configuring.md#csrf) for more information.

- `errorTitle`

  A short text describing a login error.

- `errorMessage`

  A more detailed explanation of the login error.

## <a id="example"></a>Example

As an example, you can use the `InvalidSessionMiddleware` to show a login view to the user.

`connect-client.ts`

```typescript
import { ConnectClient, InvalidSessionMiddleware } from '@vaadin/hilla-frontend';
import { setSessionExpired } from '../auth';
const client = new ConnectClient({
  prefix: 'connect',
  middlewares: [
    new InvalidSessionMiddleware(async () => {
      setSessionExpired();
      const { LoginView } = await import('./login-overlay');
      return LoginView.showOverlay();
    }),
  ],
});
export default client;
```

`login-overlay.ts`

```typescript
import { LitElement } from 'lit';
import { customElement } from 'lit/decorators.js';
import type { LoginResult } from '@vaadin/hilla-frontend';
import { Router } from '@vaadin/router';

@customElement('login-view')
export class LoginView extends LitElement {
  private returnUrl = '/';

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  private onSuccess = (_: LoginResult) => {
    Router.go(this.returnUrl);
  };

  private static overlayResult?: Promise<LoginResult>;

  // Show the login view as an overlay, when the session has
  // expired, and a user tries to invoke an endpoint call.
  // Close the login overly once the login attempt has succeeded.
  static async showOverlay(): Promise<LoginResult> {
    if (this.overlayResult) {
      return this.overlayResult;
    }
    const overlay = new this();
    return (this.overlayResult = new Promise((resolve) => {
      overlay.onSuccess = (result) => {
        this.overlayResult = undefined;
        overlay.remove();
        resolve(result);
      };
      document.body.append(overlay);
    }));
  }
}
```
