> Markdown version of [Servlet-Container Authentication](https://vaadin.com/docs/next/flow/advanced/servlet-container-authentication). Section index: [llms.txt](https://vaadin.com/docs/next/flow/llms.txt)

# Configuring Servlet-Container Authentication

Servlet containers have different mechanisms to create the user `Principal` object and run security checks when authentication is required for secured endpoints.

For reference, this page has configuration examples of custom session-based authentication with two popular containers.

## <a id="session-based-authentication"></a>Session-Based Authentication

### <a id="configuring-a-custom-servlet-filter"></a>Configuring a Custom Servlet Filter

For customized authentication, you need to implement a custom `HttpServletRequest` to wrap the default authentication using a `WebFilter`.

The following example contains a customized `Principal` object. It’s assumed that this principal is set as a `Session` attribute at some point by the application.

`CustomPrincipal.java`

```java
public class CustomPrincipal implements Principal {
    private final String name;
    private final List<String> roles;

    public CustomPrincipal(String name, String ...roles) {
        this.name = name;
        this.roles = Arrays.asList(roles);
    }

    public String getName() {
        return name;
    }

    public boolean isUserInRole(String role) {
        return roles.contains(role);
    }
}
```

`CustomHttpServletRequest.java`

```java
public class CustomHttpServletRequest extends HttpServletRequestWrapper {
    public CustomHttpServletRequest(HttpServletRequest request) {
        super(request);
    }

    @Override
    public Principal getUserPrincipal() {
        Principal myUser = (Principal) getSession().getAttribute("User");
        return myUser != null ? myUser : super.getUserPrincipal();
    }

    @Override
    public boolean isUserInRole(String role) {
        return getUserPrincipal() instanceof CustomPrincipal
                && ((CustomPrincipal) getUserPrincipal()).isUserInRole(role)
                || super.isUserInRole(role);
    }
}
```

`CustomWebFilter.java`

```java
@WebFilter("/connect")
public class CustomWebFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        chain.doFilter(new CustomHttpServletRequest((HttpServletRequest) request), response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException { }

    @Override
    public void destroy() { }
}
```

### <a id="configuring-a-client-log-in-form"></a>Configuring a Client Log-in Form

Create a form to ask the user for a username/password pair and send it to the server side. The following snippet shows how to code a log-in web component.

`frontend/my-login.ts`

```typescript
import { html, LitElement } from 'lit';
import { customElement, query } from 'lit/decorators.js';

@customElement("my-login")
export class MyLogin extends LitElement {
  @query('#username')
  private username: any;
  @query('#password')
  private password: any;

  render() {
    return html`
      <input id="username" name="username" />
      <input id="password" name="password" type="password" />
      <button @click="${this.login}">login</button>
    `;
  }

  private login() {
    fetch('/connect/login', {
      method: 'POST',
      body: `username=${this.username.value}&password=${this.password.value}`
    })
    .then(() => console.log("User Logged-in"));
  }
}
```

Next, change the above filter to handle the request and set the appropriate principal object in the session.

`CustomWebFilter.java`

```java
@WebFilter("/connect")
public class CustomWebFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        // Check username/password and set the `User` attribute in session
        if ("foo".equals(request.getParameter("username")) &&
            "abc123".equals(request.getParameter("password"))) {
            ((HttpServletRequest) request).getSession()
                .setAttribute("User", new CustomPrincipal("foo"));
        }

        // wrap original request with our custom implementation
        chain.doFilter(new CustomHttpServletRequest((HttpServletRequest) request), response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException { }
    @Override
    public void destroy() { }
}
```

## <a id="configuring-servlet-container-authentication"></a>Configuring Servlet Container Authentication

The following sections show how to configure authentication in Jetty and Tomcat servers using the [Basic HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) schema.

> **Note:** Basic HTTP authentication is considered insecure. For public and production deployments, it’s recommended to use form-based mechanisms or client-side certificates. Most servlet containers can be configured to use these.

### <a id="configuring-jetty"></a>Configuring Jetty

$JETTY\_HOME/etc/jetty-users.properties

```properties
test: password1,user
admin: password2,user,admin
```

$JETTY\_HOME/etc/jetty.xml

```xml
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
  <Set name="contextPath">/connect</Set>
  <Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/my-app</Set>

  <Get name="securityHandler">
    <Set name="loginService">
      <New class="org.eclipse.jetty.security.HashLoginService">
        <Set name="name">my-app</Set>
        <Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/jetty-users.properties</Set>
      </New>
    </Set>
  </Get>
</Configure>
```

> **Note:** A 'realm' is a repository of user information. `HashLoginService` is a log-in service that loads usernames from a Java properties file, whereas `JDBCLoginService` can read users from a JDBC data source.

### <a id="configuring-tomcat"></a>Configuring Tomcat

`$CATALINA_HOME/conf/tomcat-users.xml`

```xml
<tomcat-users>
  <role rolename="admin" />
  <role rolename="user" />
  <user name="test" password="password1" roles="user" />
  <user name="admin" password="password2" roles="user,admin" />
</tomcat-users>
```

$CATALINA\_HOME/conf/server.xml

```xml
<Context path="/connect">
  <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
         resourceName="UserDatabase" />
</Context>
```

> **Note:** Change the realm implementation if you prefer to have a different user data source. The provided `UserDatabaseRealm` can get users from a JDBC database.

`A0A3832E-663B-47A6-B108-78F36B608B77`
