Authentication for Windows-hosted apps: IIS, AD, JWT and OIDC
Choose Windows/AD auth, Basic, JWT or OIDC deliberately, avoid double-hop surprises, and test 401 vs 403.
- Build
- 26100.33650
- Edition
- Standard / Datacenter
- Architecture
- x64
- Support
- Documentation (E1)
- Evidence
- E1Official documentation
- Verified
- 2026-10-29
- Page type
- Concept
The short answer
Section titled “The short answer”| Need | Choice |
|---|---|
| Internal Windows users, domain | Windows auth (Negotiate/Kerberos) |
| Legacy app, no SSO | Basic only over TLS, never public |
| SPA/API | OIDC authorization code + PKCE, JWT access tokens |
| Server-to-server | Client credentials/mTLS, not a shared password |
| Public consumer login | OIDC/IdP with MFA; do not build your own password store |
Authentication answers “who”; authorization answers “what”. A 401 means not authenticated; 403 means authenticated but not allowed.
IIS Windows auth
Section titled “IIS Windows auth”Enable only the providers you need:
Enable-WindowsOptionalFeature -Online -FeatureName IIS-WindowsAuthentication -AllIn IIS: disable Anonymous, enable Windows Authentication; choose Negotiate/Kerberos (NTLM fallback only if needed). For Kerberos:
- SPN registered for the service account/host;
- DNS name matches the SPN;
- delegation configured only if you need double-hop.
Double-hop (IIS → SQL/file share as the user) fails without constrained delegation. Prefer a service identity for the backend instead of impersonating the user everywhere.
Basic auth
Section titled “Basic auth”Basic sends Base64 credentials; without TLS it is plaintext. Use it only for a legacy device on a private network, over HTTPS, with a scoped account. Never expose it to the internet.
JWT/OIDC
Section titled “JWT/OIDC”- Validate signature, issuer, audience, expiry and clock skew.
- Do not trust
alg: noneor a token just because it decodes. - Keep access tokens short; use refresh tokens carefully.
- Store browser tokens in HttpOnly/Secure/SameSite cookies where possible; avoid localStorage for long-lived tokens.
- Put authorization checks server-side; hiding a button is not authorization.
Proxy auth
Section titled “Proxy auth”- Authenticate at the edge/IdP, then pass a signed identity (header/JWT) to the app.
- Strip client-supplied identity headers at the proxy; only the proxy may set them.
- Do not let the app trust
X-Userfrom the internet.
Verify
Section titled “Verify”curl.exe -I https://app.example/curl.exe -I -u user:pass https://app.example/privateCheck the challenge, cookie flags (Secure, HttpOnly, SameSite), token expiry, and that a low-privilege user gets 403, not data.
Lab boundary
Section titled “Lab boundary”E1. The lab used a local admin for WAC; it did not configure AD/Kerberos/OIDC for a web app. The decision table is the design to validate on Server 2025.