jwt-auth
jwt-auth copied to clipboard
Requesting a token does not work using Authorization header to pass credentials
When trying to pass the credentials to /wp-json/jwt-auth/v1/token
via "Authorization: Basic ....." header, the endpoint will not authenticate as $request->get_param()
does not work with headers.
As per README.md, you are required to submit the credentials as parameters.
To generate token, submit a POST request to this endpoint. With username and password as the parameters.
It doesn't however specify to new users, that Basic Auth doesn't count as parameters, but POST Body or URL GET Params do. I'd suggest updating the README.md to guide the user in the right direction.
IMHO, the Plugin should however also respect the Authorization header, since it's the standard method for authenticating WordPress REST-API and many other third party APIs. This could be achieved by checking $username and $password for null and trying to parse the Authorization header, similar to how i did in my first comment
--- Original Issue ---
The jwt-auth plugin always returns an error while trying to authenticate using the /wp-json/jwt-auth/v1/token
endpoint using the current WordPress version (currently 6.4.2)
{
"success": false,
"statusCode": 403,
"code": "invalid_username",
"message": "Error: Unknown username. Check again or try your email address.",
"data": []
}
Upon further inspection, I've noticed that the get_token
method, responsible for this endpoint uses $request->get_param()
for both username and password. These calls to get_param
will always return null since they are not responsible for parsing headers.
~As of WordPress 6.4.2, this plugin will not work.~
After a while debugging the issue, i have came up with a solution to get this endpoint to function using Authorization header.
I've added another method to class-auth.php
that parses the user and password from the Authorization header and replaced the calls to $request->get_param()
with my method (this will break the current behavior of sending the credentials in the POST body, so using this method as a fallback would be a better approach):
public function parse_authorization_header(): array
{
$headers = getallheaders();
if (isset($headers['Authorization'])) {
list($type, $data) = explode(" ", $headers['Authorization'], 2);
if (strcasecmp($type, "Basic") == 0) {
return explode(':', base64_decode($data));
}
}
return array(null, null);
}
and in the get_token method i've replaced
$username = $request->get_param('username');
$password = $request->get_param( 'password' );
with
list($username, $password) = $this->parse_authorization_header();
~and the endpoint /wp-json/jwt-auth/v1/token
will work again in WordPress 6.4.2~
This was a wrong assumption, that the plugin works using Basic Auth
@wavedeck Why are you sending the username and password in the headers? The username and password should be spent in the body of the POST request...
Thx! Sending the username and password in the body works. In that case, my issue is not an actual bug / incompatibility but rather misinformation and unclear docs. Since the default way, WordPress and many other APIs handle authentication is through "Authorization" header, and its a best practice to do so, i have assumed, that your endpoints work similarly.
The docs describe:
To generate token, submit a POST request to this endpoint. With username and password as the parameters.
Parameters can be a lot of things.. in the case of get_parameter()
in WordPress the Body, Query Parameters or Params set by some Middleware in the request.
In that case I'd suggest to update the README.md to further specify sending the values in the POST Body to avoid further confusion. It cost me quite some time to figure out why this happened, since I first assumed something is wrong with my credentials.
Alternatively, it would be helpful to additionally parse the Authorization Header if the user credentials are null to prevent issues like mine from happening further.