Every headless WordPress guide eventually asks the same question: should the external app authenticate with Application Passwords or with a JWT? The honest answer requires being precise about what each option actually is. Application Passwords are a real, built-in WordPress core feature, confirmed since WordPress 5.6, generated under a user’s profile in wp-admin, requiring no plugin at all. JWT authentication for the WP REST API is not a core feature. It exists only through third-party, community-maintained plugins. Both can work. They are not equivalent in what they cost you to run, and this lesson lays out that tradeoff without pretending JWT is something it isn’t.
Course 4’s authentication lesson (how Application Passwords work, generated under Users → Profile → Application Passwords). This lesson builds on that directly for the headless-specific decision.
Step 1: Application Passwords, recapped for the headless case
An Application Password is a randomly generated credential tied to a specific
WP_User, sent as HTTP Basic Auth:
Authorization: Basic base64(username:xxxx xxxx xxxx xxxx xxxx xxxx)
Nothing about this changes for a headless caller. Your Next.js server, your mobile app, or your edge function sends the same header, WordPress resolves it to the same real user account, with that user’s actual roles and capabilities. No plugin is required, no extra endpoint needs registering, and no separate secret-signing scheme needs maintaining. This is why it’s the default recommendation in this course, and in the official WordPress core proposal that shipped it.
Basic Auth is reversible base64, not encrypted on its own, HTTPS is what protects it in transit. And an Application Password authenticates as one specific WordPress user, so for a service-to-service integration (a Next.js backend, an edge function), create a dedicated, least-privilege WordPress account for that integration rather than reusing an administrator’s own password.
Step 2: What JWT authentication for the WP REST API actually is
There is no JWT support in WordPress core. What people mean when they say “JWT auth for
WordPress” is a third-party plugin, most commonly “JWT Authentication for WP REST API,”
that adds the entire mechanism itself: a secret signing key you define as a PHP
constant, a new endpoint (typically /wp-json/jwt-auth/v1/token) that accepts a
username and password and returns a signed token, and a filter that makes the REST API
accept Authorization: Bearer <token> on subsequent requests. Every part of that,
the endpoint, the secret, the validation logic, is the plugin’s code, not WordPress
core’s. If that plugin stops being maintained, is removed, or has a security issue,
your authentication layer goes with it.
// File: wp-config.php (JWT plugin's own required constant, not a core setting)
define( 'JWT_AUTH_SECRET_KEY', 'a-long-random-string-you-generate-and-guard' );
POST /wp-json/jwt-auth/v1/token
Content-Type: application/json
{ "username": "someuser", "password": "their-account-password" }
The response is a signed JWT the client then sends as Authorization: Bearer <token> on
every subsequent request, until it expires.
Two things to weigh honestly here. First, JWT_AUTH_SECRET_KEY is a new secret you now
own, leak it and anyone can mint valid tokens for any user. Second, the token endpoint
itself takes a real account password directly in the request body, so it needs the
same HTTPS discipline as Application Passwords, with the added exposure of a raw
password in a request payload rather than a purpose-built credential.
Step 3: The tradeoffs, side by side
| Factor | Application Passwords (core) | JWT plugin (third-party) |
|---|---|---|
| Ships with WordPress | Yes, since 5.6, no plugin | No, requires installing and maintaining a plugin |
| Secrets to manage | One, the generated Application Password itself | Two, the plugin’s signing key plus the credential used to obtain a token |
| Expiry | Does not expire on its own, revoked manually under the user’s profile | Tokens typically expire, forcing a refresh flow you build or the plugin provides |
| Maintenance dependency | WordPress core’s own release and security process | Whatever release cadence and security response the specific plugin’s maintainer provides |
| Best fit | Server-to-server integrations, a small number of dedicated service accounts | Consumer apps where many individual end users log in with their own WordPress credentials often |
Step 4: When each approach genuinely makes sense
For a Next.js backend, an edge function, or any server-to-server integration where a small, known number of dedicated accounts call WordPress, Application Passwords are the simpler, core-supported, lower-dependency choice. There is nothing a JWT plugin does better for this case.
Where JWT plugins get a genuine argument is a consumer-facing mobile or web app with many individual end users, each logging in with their own WordPress account frequently, where you specifically want short-lived tokens and an explicit refresh cycle rather than a long-lived Basic Auth credential sitting on a device indefinitely. That’s a real design tradeoff, not a myth, but it comes with the plugin-maintenance and secret-count cost from Step 3, go in with that cost acknowledged rather than assumed away.
Test it: confirm which one your integration actually needs
Before writing any client code, answer these two questions for your own project: how many distinct callers will authenticate (a handful of services, or many individual end users), and do you need forced token expiry as a security property, or is manually-revocable-on-demand (Application Passwords) good enough. If you can’t answer “yes, we specifically need forced expiry,” default to Application Passwords and move on to Lesson 3.
A lot of “headless WordPress” tutorials default to JWT simply because a specific blog post did, not because it’s WordPress’s own recommended approach. WordPress core’s own 2020 proposal that shipped Application Passwords is explicit that this is the intended mechanism for external applications. Check what a source is actually claiming before copying its authentication choice.
Recap
Application Passwords are core, official, and require no plugin, and remain the right default for authenticating external apps to WordPress, headless or not. JWT authentication for the WP REST API is a third-party plugin capability, not a WordPress feature, adding a second secret and a maintenance dependency in exchange for token expiry and a refresh flow. Choose JWT deliberately, for a specific reason, not by default. The next lesson puts Application Passwords to work in a real Next.js server integration.
Resources & further reading
- Application Passwords proposal, WordPress core, make.wordpress.org
- Application Passwords integration guide, make.wordpress.org
- WordPress REST API handbook, developer.wordpress.org