---
description: Authenticate to WinRM with NTLM or Kerberos (SPNEGO), including domain accounts, ordered fallback, and Kerberos configuration.
date_published: 2026-07-29
date_modified: 2026-07-29
canonical_url: https://metricshub.org/winrm-java/authentication.html
---

# Authentication

On this Page

- [Ordered fallback](#ordered-fallback)
- [User name and domain](#user-name-and-domain)
- [NTLM](#ntlm)
- [Kerberos (SPNEGO)](#kerberos-spnego) 
  
    - [Kerberos configuration](#kerberos-configuration)
- [Authentication failures](#authentication-failures)
- [Choosing the scheme on the command line](#choosing-the-scheme-on-the-command-line)
- [See also](#see-also)

The client authenticates with either **NTLM** or **Kerberos (SPNEGO)**. The scheme is chosen with `authentication(...)` on the [WinRMClient](apidocs/org/metricshub/winrm/WinRMClient.html) builder, which takes one or more [AuthScheme](apidocs/org/metricshub/winrm/AuthScheme.html) values:

```java
import org.metricshub.winrm.AuthScheme;

WinRMClient.builder("server.example.com")
    .credentials("DOMAIN\\Administrator", password)
    .authentication(AuthScheme.NTLM)                       // NTLM only (also the default)
    // .authentication(AuthScheme.KERBEROS)                // Kerberos only
    // .authentication(AuthScheme.KERBEROS, AuthScheme.NTLM) // ordered fallback
    .build();
```

When `authentication(...)` is not called, **NTLM** is used.

## Ordered fallback

Several schemes form an **ordered fallback list**: each is tried in the given order until one succeeds. `authentication(KERBEROS, NTLM)` attempts Kerberos first and falls back to NTLM — for example when the KDC is unreachable or the clock skew is too large.

## User name and domain

The user name may be given as `DOMAIN\user` or as a bare `user`. When a backslash is present, the part before it is treated as the Windows domain and the part after it as the account name. In Java, remember to escape the backslash in a string literal:

```java
"DOMAIN\\Administrator"   // domain = DOMAIN, user = Administrator
"Administrator"           // no domain
```

The password is a `char[]`, and the builder deliberately does **not** copy it: after closing the client you can wipe the single authoritative copy of the secret (`Arrays.fill(password, '\0')`).

## NTLM

NTLM is the default. It works over both transports:

- **HTTP** — the WinRM payload is protected with **NTLM message encryption**, so credentials and data are not sent in the clear even without TLS.
- **HTTPS** — NTLM runs inside the TLS tunnel. See [TLS / HTTPS](tls.html).

NTLM needs no extra configuration beyond the user name and password.

## Kerberos (SPNEGO)

Kerberos authentication uses SPNEGO through the JDK's GSS-API and **requires HTTPS**. Connect by the **FQDN the KDC knows** (the service principal is `HTTP/<hostname>`), not by IP address:

```java
try (WinRMClient client = WinRMClient.builder("server.internal.example.com")
        .https()
        .credentials("DOMAIN\\Administrator", password)
        .authentication(AuthScheme.KERBEROS)
        // .ticketCache(Path.of("/tmp/krb5cc_1000"))   // optional
        .build()) {
    ...
}
```

Requesting Kerberos on a plain-HTTP client fails at `build()` with a clear message: there is no Kerberos message encryption over HTTP.

### Kerberos configuration

By default, Kerberos relies on the **ambient JDK Kerberos configuration** — the platform `krb5.conf` (or the file named by `-Djava.security.krb5.conf`), or the realm and KDC given directly with `-Djava.security.krb5.realm` and `-Djava.security.krb5.kdc`:

```bash
java -Djava.security.krb5.realm=EXAMPLE.COM \
     -Djava.security.krb5.kdc=dc01.example.com \
     -cp ... MyApp
```

The optional `ticketCache(Path)` builder option points at a Kerberos ticket cache to use for the connection; without it, Kerberos logs in with the user name and password.

## Authentication failures

A rejected credential (after every scheme of the fallback list was tried) surfaces as a [WinRMAuthenticationException](apidocs/org/metricshub/winrm/exceptions/WinRMAuthenticationException.html) whose message has the stable form `Authentication error on <endpoint> with user name "<user>"`.

## Choosing the scheme on the command line

The standalone jar selects the scheme with `--ntlm` (the default) or `--kerberos`. The two are mutually exclusive, and `--kerberos` requires `--https`:

```bash
java -jar winrm-java-2.0.00-standalone.jar \
  -h server.example.com -u 'DOMAIN\user' -pf password.txt \
  --https --kerberos \
  command whoami
```

Instead of relying on the ambient configuration, the CLI can set the JDK Kerberos configuration for the current invocation:

| Option | Meaning |
| --- | --- |
| `--kerberos-kdc <host>` | Sets the KDC and, unless `--kerberos-realm` is given, infers the realm from the KDC's DNS suffix. |
| `--kerberos-realm <realm>` | Overrides the inferred realm. Requires `--kerberos-kdc`. |

```bash
java -jar winrm-java-2.0.00-standalone.jar \
  -h server.internal.example.com -u 'DOMAIN\user' -pf password.txt \
  --https --kerberos --kerberos-kdc dc01.internal.example.com \
  command whoami
```

Here the realm is inferred as `INTERNAL.EXAMPLE.COM` by dropping the KDC's first DNS label and upper-casing the rest. This follows a common Active Directory naming convention but is not guaranteed by Kerberos — pass `--kerberos-realm` when the realm does not match the KDC's DNS suffix, or when the KDC is not a fully qualified DNS name.

## See also

- [Preparing the Windows Host](preparing-the-host.html) — the privileges the account needs, and why local administrator accounts are often denied
- [TLS / HTTPS](tls.html) — required for Kerberos and recommended for NTLM
- [Timeouts and Errors](timeouts-and-errors.html) — how authentication failures surface
