> For the complete documentation index, see [llms.txt](https://docs.opendatadiscovery.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.opendatadiscovery.org/configuration-and-deployment/enable-security/authentication/login-form.md).

# Login form

This is the simplest form of authentication provided by ODD Platform.

User credentials are set by defining the `auth.login-form-credentials` property in the format `username1:password1,username2:password2,...`. All users authenticated through this method receive ADMIN privileges in the platform.

{% hint style="danger" %}
**The shipped configuration contains the default credentials `admin:admin,root:root`.** If you enable `LOGIN_FORM` authentication without overriding `auth.login-form-credentials`, the platform will accept logins from `admin/admin` and `root/root` — and both accounts have full ADMIN privileges. Change these defaults before any non-local deployment.

To override, either set `auth.login-form-credentials` explicitly (YAML or the `AUTH_LOGIN_FORM_CREDENTIALS` environment variable, shown below) or switch to `OAUTH2` or `LDAP` authentication. For any production deployment, prefer OAUTH2 or LDAP — `LOGIN_FORM` stores credentials in plain text in the platform configuration and does not support rotation, session revocation, or MFA.
{% endhint %}

{% tabs %}
{% tab title="YAML" %}

```yaml
auth:
    type: LOGIN_FORM
    login-form-credentials: susan:susan_password,dave:dave_password
```

{% endtab %}

{% tab title="Environment variables" %}

```
AUTH_TYPE=LOGIN_FORM
AUTH_LOGIN_FORM_CREDENTIALS=susan:susan_password,dave:dave_password
```

{% endtab %}
{% endtabs %}

## Authorization posture under `LOGIN_FORM`

`LOGIN_FORM` is dev/demo-oriented authentication. Three platform-side defaults diverge from the production modes (`OAUTH2`, `LDAP`) in ways that materially change what an operator should expect from a `LOGIN_FORM` deployment — none of them is a bug, but each is load-bearing on operator decisions. For the cross-mode comparison of how every auth mode grants ADMIN (including LOGIN\_FORM's "every user is ADMIN" stance), see [Admin promotion across providers](/configuration-and-deployment/enable-security/admin-promotion.md).

### Policy and Role tables are not consulted

Every user authenticated through `LOGIN_FORM` is granted `ADMIN` authority at login. The Spring Security chain in this mode does not wire the `AuthorizationCustomizer` that translates the `SecurityConstants.SECURITY_RULES` table into per-request authorization checks; under `LOGIN_FORM`, the chain is `.pathMatchers("/**").authenticated()` and nothing more. The Policies, Roles, and Permission grants an operator authors via the [Management → Policies / Roles UI](/configuration-and-deployment/enable-security/authorization/policies.md) are stored in the database but never gate the live auth chain — they take effect only after switching `auth.type` to `OAUTH2` or `LDAP`.

**Operator consequence:** evaluating a non-ADMIN Policy in `LOGIN_FORM` mode does not test what will happen in `OAUTH2` / `LDAP`. Do Policy / Role testing on the same auth mode you will run in production.

### CSRF protection is disabled

The `LOGIN_FORM` filter chain unconditionally disables CSRF (`http.csrf(...::disable)`). A signed-in operator visiting an attacker-controlled page can have state-changing `POST` / `PUT` / `DELETE` requests issued to the platform on their behalf, because the browser automatically attaches the session cookie. The platform also does not stamp `SameSite=Strict` or `Secure` cookie attributes on its default session cookies — see [Configure ODD Platform → Session and cookie configuration](/configuration-and-deployment/odd-platform.md) — so the protections that would normally compensate for missing CSRF defence are also absent in the default deployment.

**Operator consequence:** run `LOGIN_FORM` only behind a TLS-terminating reverse proxy that stamps `Secure` and `SameSite=Strict` externally, or restrict the deployment to a trusted network. Either is acceptable for dev/demo; neither is production-grade.

### `auth.login-form-redirect` is operator-trusted

After a successful sign-in, the platform sends the user to the URL configured in `auth.login-form-redirect` (or to `/` when the property is empty). The redirect target is parsed via `URI.create(...)` with no scheme allowlist, no host allowlist, and no platform-base-URL validation. An operator who templates this value from a less-trusted upstream pipeline (a CI variable, a downstream Helm value derived from arbitrary env-var input) must ensure the provenance of the input.

**Operator consequence:** treat `auth.login-form-redirect` as a high-trust string. Either set it to a fixed value at the deployment manifest, or apply your own allowlist in the configuration pipeline that produces the platform's environment variables.

## Cross-mode user-name collision (activity feed read paths)

The platform's [activity-feed](/features/active-platform-features/activity-feed.md) read paths join the `USER_OWNER_MAPPING` table on `OIDC_USERNAME` only — the join does **not** discriminate by auth provider. If your deployment has historically used multiple auth modes (for example, started on `LOGIN_FORM` with seed users, then enabled `LDAP` or `OAUTH2`), a user named `alice` who signed in via `LOGIN_FORM` and a user named `alice` who signed in via `LDAP` can resolve to the same `OwnerPojo` when activity-feed rows are rendered. The most recent `USER_OWNER_MAPPING` row for the literal username wins each lookup; results are not deterministic across replicas.

**Operator mitigation today:** never reuse usernames across auth modes when migrating. If you migrate from `LOGIN_FORM` to `LDAP` or `OAUTH2`, delete the `USER_OWNER_MAPPING` rows for the `LOGIN_FORM` usernames before introducing same-named users in the new mode.

**Forensic note:** do not rely on activity-feed Owner attribution for incident response in multi-mode deployments without verifying the auth mode of the actor through the underlying `activity.created_by` value.

A platform-side fix that discriminates the join by `PROVIDER` is tracked upstream. The same caveat applies to deployments running `LDAP` on top of an earlier `LOGIN_FORM` history — see the matching note on the [LDAP](/configuration-and-deployment/enable-security/authentication/ldap.md#cross-mode-user-name-collision-activity-feed-read-paths) page.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.opendatadiscovery.org/configuration-and-deployment/enable-security/authentication/login-form.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
