{"id":412172,"date":"2024-10-31T08:00:00","date_gmt":"2024-10-31T08:00:00","guid":{"rendered":"https:\/\/www.weixiaoduo.com\/plugins\/simple-jwt-auth\/"},"modified":"2024-11-17T21:30:00","modified_gmt":"2024-11-17T21:30:00","slug":"simple-jwt-auth","status":"publish","type":"post","link":"https:\/\/www.weixiaoduo.com\/plugins\/simple-jwt-auth\/","title":{"rendered":"Simple JWT Auth"},"content":{"rendered":"<p>Extends the WordPress REST API using JSON Web Tokens for robust authentication and authorization.<\/p>\n<p>JSON Web Token (JWT) is an open standard (<a href=\"https:\/\/tools.ietf.org\/html\/rfc7519\" rel=\"nofollow ugc\">RFC 7519<\/a>) that defines a compact and self-contained way for securely transmitting information between two parties.<\/p>\n<p>It provides a secure and reliable way to access and manage WordPress data from external applications, making it ideal for building headless CMS solutions.<\/p>\n<ul>\n<li>Support & question: <a href=\"https:\/\/wordpress.org\/support\/plugin\/simple-jwt-auth\/\" rel=\"ugc\">WordPress support forum<\/a><\/li>\n<li>Reporting plugin\u2019s bug: <a href=\"https:\/\/github.com\/sayandey18\/simple-jwt-auth\/issues\" rel=\"nofollow ugc\">GitHub issues tracker<\/a><\/li>\n<\/ul>\n<p><strong>Plugins GitHub Repo<\/strong> https:\/\/github.com\/sayandey18\/simple-jwt-auth<\/p>\n<h3>Enable PHP HTTP Authorization Header<\/h3>\n<p>HTTP Authorization is a mechanism that allows clients to provide credentials to servers, thereby gaining access to protected resources. This is typically achieved by sending a special header, the Authorization header, in the HTTP request.<\/p>\n<h4>Shared Hosts<\/h4>\n<p>Most shared hosts have disabled the <strong>HTTP Authorization Header<\/strong> by default.<\/p>\n<p>To enable this option you\u2019ll need to edit your <strong>.htaccess<\/strong> file by adding the following:<\/p>\n<pre><code>RewriteEngine on\nRewriteCond %{HTTP:Authorization} ^(.*)\nRewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]\n<\/code><\/pre>\n<h4>WPEngine<\/h4>\n<p>To enable this option you\u2019ll need to edit your .htaccess file adding the follow:<\/p>\n<pre><code>SetEnvIf Authorization \"(.*)\" HTTP_AUTHORIZATION=$1\n<\/code><\/pre>\n<h3>Configuration<\/h3>\n<p>Simple JWT Auth plugin needs a <strong>Signing Key<\/strong> to encrypt and decrypt the <strong>secret key<\/strong>, <strong>private key<\/strong>, and <strong>public key<\/strong>. This signing key must be exact 32 charecter long and never be revealed.<\/p>\n<p>To add the <strong>signing key<\/strong> edit your <code>wp-config.php<\/code> file and add a new constant called <strong>SIMPLE_JWT_AUTH_ENCRYPT_KEY<\/strong><\/p>\n<pre><code>define( 'SIMPLE_JWT_AUTH_ENCRYPT_KEY', 'your-32-char-signing-key' );\n<\/code><\/pre>\n<p>Generate a 32 charecter key from here: <a href=\"https:\/\/string-gen.netlify.app\" rel=\"nofollow ugc\">https:\/\/string-gen.netlify.app<\/a><\/p>\n<p>Here is the sample response if the encryption key is not configured in wp-config.php file.<\/p>\n<pre><code>{\n    \"code\": \"simplejwt_bad_encryption_key\",\n    \"message\": \"Encryption key is not configured properly.\",\n    \"data\": {\n        \"status\": 403\n    }\n}\n<\/code><\/pre>\n<h3>REST Endpoints<\/h3>\n<p>When the plugin is activated, a new namespace is added.<\/p>\n<pre><code>\/auth\/v1\n<\/code><\/pre>\n<p>Also, two new endpoints are added to this namespace.<\/p>\n<pre><code>*\/wp-json\/auth\/v1\/token          | POST\n*\/wp-json\/auth\/v1\/token\/validate | POST\n<\/code><\/pre>\n<h3>Requesting\/Generating Token<\/h3>\n<p>To generate a new token, submit a POST request to this endpoint. With <code>username<\/code> and <code>password<\/code> as the parameters.<\/p>\n<p>It will validates the user credentials, and returns success response including a token if the authentication is correct or returns an error response if the authentication is failed.<\/p>\n<pre><code>curl --location 'https:\/\/example.com\/wp-json\/auth\/v1\/token' \n--header 'Content-Type: application\/json' \n--data-raw '{\n    \"username\": \"wordpress_username\",\n    \"password\": \"wordpress_password\"\n}'\n<\/code><\/pre>\n<h4>Sample of success response<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_auth_credential\",\n    \"message\": \"Token created successfully\",\n    \"data\": {\n        \"status\": 200,\n        \"id\": \"2\",\n        \"email\": \"sayandey@outlook.com\",\n        \"nicename\": \"sayan_dey\",\n        \"display_name\": \"Sayan Dey\",\n        \"token\": \"eyJ0eXAiOiJKV1QiLCJhbGciO.........\"\n    }\n}\n<\/code><\/pre>\n<h4>Sample of error response<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_invalid_username\",\n    \"message\": \"Error: The username admin_user is not registered on this site. If you are unsure of your username, try your email address instead.\",\n    \"data\": {\n        \"status\": 403\n    }\n}\n<\/code><\/pre>\n<p>Once you get the token, you can store it somewhere in your application:<\/p>\n<ul>\n<li>using <strong>Cookie<\/strong> <\/li>\n<li>or using <strong>localstorage<\/strong> <\/li>\n<li>or using a wrapper like <a href=\"https:\/\/localforage.github.io\/localForage\/\" rel=\"nofollow ugc\">localForage<\/a> or <a href=\"https:\/\/pouchdb.com\/\" rel=\"nofollow ugc\">PouchDB<\/a><\/li>\n<li>or using local database like SQLite<\/li>\n<li>or your choice based on app you develop<\/li>\n<\/ul>\n<p>Then you should pass this token as <em>Bearer Authentication<\/em> header to every API call.<\/p>\n<pre><code>Authorization: Bearer your-generated-token\n<\/code><\/pre>\n<p>Here is an example to create WordPress post using JWT token authentication.<\/p>\n<pre><code>curl --location 'https:\/\/example.com\/wp-json\/wp\/v2\/posts' \n--header 'Content-Type: application\/json' \n--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciO.........' \n--data '{\n    \"title\": \"Dummy post through API\",\n    \"content\": \"Lorem Ipsum is simply dummy text of the printing and typesetting industry.\",\n    \"status\": \"publish\",\n    \"tags\": [\n        4,\n        5,\n        6\n    ]\n}'\n<\/code><\/pre>\n<p>Plugin\u2019s middleware intercepts every request to the server, checking for the presence of the <strong>Authorization<\/strong> header. If the header is found, it attempts to decode the JWT token contained within.<\/p>\n<p>Upon successful decoding, the middleware extracts the user information stored in the token and authenticates the user accordingly, ensuring that only authorized requests are processed.<\/p>\n<h3>Validating Token<\/h3>\n<p>This is a helper endpoint to validate a token. You only will need to make a <strong>POST<\/strong> request sending the Bearer Authorization header.<\/p>\n<pre><code>curl --location --request POST 'https:\/\/example.com\/wp-json\/auth\/v1\/token\/validate' \n--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciO.........'\n<\/code><\/pre>\n<h4>Sample of success response<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_valid_token\",\n    \"message\": \"Token is valid\",\n    \"data\": {\n        \"status\": 200\n    }\n}\n<\/code><\/pre>\n<h3>REST Errors<\/h3>\n<p>If the token is invalid an error will be returned, here are some samples of errors.<\/p>\n<h4>Invalid Username<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_invalid_username\",\n    \"message\": \"Error: The username admin is not registered on this site. If you are unsure of your username, try your email address instead.\",\n    \"data\": {\n        \"status\": 403\n    }\n}\n<\/code><\/pre>\n<h4>Invalid Password<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_incorrect_password\",\n    \"message\": \"Error: The password you entered for the username tiyasha_das is incorrect. Lost your password?\",\n    \"data\": {\n        \"status\": 403\n    }\n}\n<\/code><\/pre>\n<h4>Invalid Signature<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_invalid_token\",\n    \"message\": \"Signature verification failed\",\n    \"data\": {\n        \"status\": 403\n    }\n}\n<\/code><\/pre>\n<h4>Invalid Token<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_invalid_token\",\n    \"message\": \"Syntax error, malformed JSON\",\n    \"data\": {\n        \"status\": 403\n    }\n}\n<\/code><\/pre>\n<h4>Expired Token<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_invalid_token\",\n    \"message\": \"Expired token\",\n    \"data\": {\n        \"status\": 403\n    }\n}\n<\/code><\/pre>\n<h4>No Authorization<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_no_auth_header\",\n    \"message\": \"Authorization header not found\",\n    \"data\": {\n        \"status\": 403\n    }\n}\n<\/code><\/pre>\n<h4>Bad Authorization<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_bad_auth_header\",\n    \"message\": \"Authorization header malformed\",\n    \"data\": {\n        \"status\": 400\n    }\n}\n<\/code><\/pre>\n<h4>Wrong Algorithm Token<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_invalid_token\",\n    \"message\": \"Incorrect key for this algorithm\",\n    \"data\": {\n        \"status\": 403\n    }\n}\n<\/code><\/pre>\n<h4>Unsupported Algorithm<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_unsupported_algorithm\",\n    \"message\": \"Unsupported algorithm see https:\/\/tinyurl.com\/uf4ns6fm\",\n    \"data\": {\n        \"status\": 403\n    }\n}\n<\/code><\/pre>\n<h4>Bad Configuration<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_bad_config\",\n    \"message\": \"JWT is not configured properly, please contact the admin\",\n    \"data\": {\n        \"status\": 403\n    }\n}\n<\/code><\/pre>\n<h4>Bad Encryption Key<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_bad_encryption_key\",\n    \"message\": \"Encryption key is not configured properly.\",\n    \"data\": {\n        \"status\": 403\n    }\n}\n<\/code><\/pre>\n<h4>Invalid Encryption Key Length<\/h4>\n<pre><code>{\n    \"code\": \"simplejwt_invalid_enckey_length\",\n    \"message\": \"Encryption key must be exactly 32 characters long\",\n    \"data\": {\n        \"status\": 400\n    }\n}\n<\/code><\/pre>\n<h3>Available Hooks<\/h3>\n<p><strong>Simple JWT Auth<\/strong> is a developer-friendly plugin. It has various filter hooks available to override the default settings.<\/p>\n<h4>simplejwt_cors_allow_headers<\/h4>\n<p>The <code>simplejwt_cors_allow_headers<\/code> allows you to modify the available headers when the Cross-Origin Resource Sharing (CORS) support is enabled.<\/p>\n<p>Default value:<\/p>\n<pre><code>'Access-Control-Allow-Headers, Content-Type, Authorization'\n<\/code><\/pre>\n<p>Usage example:<\/p>\n<pre><code>\/**\n * Change the allowed CORS headers.\n *\n * @param   string $headers The allowed headers.\n * @return  string The allowed headers.\n *\/\nadd_filter(\"simplejwt_cors_allow_headers\", function ($headers) {\n    \/\/ Modify the headers here.\n    return $headers;\n});\n<\/code><\/pre>\n<h4>simplejwt_auth_iss<\/h4>\n<p>The <code>simplejwt_auth_iss<\/code> allows you to change the <a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/rfc7519#section-4.1.1\" rel=\"nofollow ugc\"><strong>iss<\/strong><\/a> value before the payload is encoded to be a token.<\/p>\n<p>Default value:<\/p>\n<pre><code>get_bloginfo( 'url' );\n<\/code><\/pre>\n<p>Usage example:<\/p>\n<pre><code>\/**\n * Change the token issuer.\n *\n * @param   string $iss The token issuer.\n * @return  string The token issuer.\n *\/\nadd_filter(\"simplejwt_auth_iss\", function ($iss) {\n    \/\/ Modify the \"iss\" here.\n    return $iss;\n});\n<\/code><\/pre>\n<h4>simplejwt_not_before<\/h4>\n<p>The <code>simplejwt_not_before<\/code> allows you to change the <a href=\"https:\/\/tools.ietf.org\/html\/rfc7519#section-4.1.5\" rel=\"nofollow ugc\"><strong>nbf<\/strong><\/a> value before the payload is encoded to be a token.<\/p>\n<p>Default value:<\/p>\n<pre><code>time();\n<\/code><\/pre>\n<p>Usage example:<\/p>\n<pre><code>\/**\n * Change the token's nbf value.\n *\n * @param   int $not_before The default \"nbf\" value in timestamp.\n * @param   int $issued_at The \"iat\" value in timestamp.\n * @return  int The \"nbf\" value.\n *\/\nadd_filter(\n    \"simplejwt_not_before\",\n    function ($not_before, $issued_at) {\n        \/\/ Modify the \"not_before\" here.\n        return $not_before;\n    },\n    10,\n    2,\n);\n<\/code><\/pre>\n<h4>simplejwt_auth_expire<\/h4>\n<p>The <code>simplejwt_auth_expire<\/code> allows you to change the value <a href=\"https:\/\/tools.ietf.org\/html\/rfc7519#section-4.1.4\" rel=\"nofollow ugc\"><strong>exp<\/strong><\/a> before the payload is encoded to be a token.<\/p>\n<p>Default value:<\/p>\n<pre><code>time() + ( DAY_IN_SECONDS * 7 )\n<\/code><\/pre>\n<p>Usage example:<\/p>\n<pre><code>\/**\n * Change the token's expire value.\n *\n * @param   int $expire The default \"exp\" value in timestamp.\n * @param   int $issued_at The \"iat\" value in timestamp.\n * @return  int The \"nbf\" value.\n *\/\nadd_filter(\n    \"simplejwt_auth_expire\",\n    function ($expire, $issued_at) {\n        \/\/ Modify the \"expire\" here.\n        return $expire;\n    },\n    10,\n    2,\n);\n<\/code><\/pre>\n<h4>simplejwt_payload_before_sign<\/h4>\n<p>The <code>simplejwt_payload_before_sign<\/code> allows you to modify all the payload data before being encoded and signed.<\/p>\n<p>Default value:<\/p>\n<pre><code>$payload = [\n    \"iss\" => $this->simplejwt_get_iss(),\n    \"iat\" => $issued_at,\n    \"nbf\" => $not_before,\n    \"exp\" => $expire,\n    \"data\" => [\n        \"user\" => [\n            \"id\" => $user->data->ID,\n        ],\n    ],\n];\n<\/code><\/pre>\n<p>Usage example:<\/p>\n<pre><code>\/**\n * Modify the payload data before being encoded & signed.\n *\n * @param   array $payload The default payload\n * @param   WP_User $user The authenticated user.\n * @return  array The payloads data.\n *\/\nadd_filter(\n    \"simplejwt_payload_before_sign\",\n    function ($payload, $user) {\n        \/\/ Modify the payload here.\n        return $payload;\n    },\n    10,\n    2,\n);\n<\/code><\/pre>\n<h4>simplejwt_token_before_dispatch<\/h4>\n<p>The <code>simplejwt_token_before_dispatch<\/code> allows you to modify the token response before to dispatch it to the client.<\/p>\n<p>Default value:<\/p>\n<pre><code>$data = new WP_REST_Response(\n    [\n        \"code\" => \"simplejwt_auth_credential\",\n        \"message\" => JWTNotice::get_notice(\"auth_credential\"),\n        \"data\" => [\n            \"status\" => 200,\n            \"id\" => $user->data->ID,\n            \"email\" => $user->data->user_email,\n            \"nicename\" => $user->data->user_nicename,\n            \"display_name\" => $user->data->display_name,\n            \"token\" => $token,\n        ],\n    ],\n    200,\n);\n<\/code><\/pre>\n<p>Usage example:<\/p>\n<pre><code>\/**\n * Modify the JWT response before dispatch.\n *\n * @param   WP_REST_Response $data The token response data.\n * @param   WP_User $user The user object for whom the token is being generated.\n * @return  WP_REST_Response Modified token response data.\n *\/\nadd_filter(\n    \"simplejwt_token_before_dispatch\",\n    function ($data, $user) {\n        \/\/ Modify the response data.\n        if ($user instanceof WP_User) {\n        }\n        return $data;\n    },\n    10,\n    2,\n);\n<\/code><\/pre>\n<h3>Credits<\/h3>\n<ul>\n<li><a href=\"https:\/\/developer.wordpress.org\/rest-api\/\" rel=\"nofollow ugc\">WordPress REST API<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/firebase\/php-jwt\" rel=\"nofollow ugc\">php-jwt by Firebase<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Extends the WP REST API using JSON Web Tokens for robust authentication, providing a secure and reliable way to access and manage WordPress data.<\/p>\n","protected":false},"author":65,"featured_media":412173,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"slim_seo":{"title":"Simple JWT Auth - \u8587\u6653\u6735\u63d2\u4ef6\u76ee\u5f55","description":"Extends the WP REST API using JSON Web Tokens for robust authentication, providing a secure and reliable way to access and manage WordPress data."},"footnotes":""},"categories":[1],"tags":[180,13453,3817,13454,3144],"class_list":["post-412172","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-authentication","tag-json-web-token","tag-jwt","tag-jwt-auth","tag-rest-api"],"_links":{"self":[{"href":"https:\/\/www.weixiaoduo.com\/plugins\/wp-json\/wp\/v2\/posts\/412172","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.weixiaoduo.com\/plugins\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.weixiaoduo.com\/plugins\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.weixiaoduo.com\/plugins\/wp-json\/wp\/v2\/users\/65"}],"replies":[{"embeddable":true,"href":"https:\/\/www.weixiaoduo.com\/plugins\/wp-json\/wp\/v2\/comments?post=412172"}],"version-history":[{"count":0,"href":"https:\/\/www.weixiaoduo.com\/plugins\/wp-json\/wp\/v2\/posts\/412172\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.weixiaoduo.com\/plugins\/wp-json\/wp\/v2\/media\/412173"}],"wp:attachment":[{"href":"https:\/\/www.weixiaoduo.com\/plugins\/wp-json\/wp\/v2\/media?parent=412172"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.weixiaoduo.com\/plugins\/wp-json\/wp\/v2\/categories?post=412172"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.weixiaoduo.com\/plugins\/wp-json\/wp\/v2\/tags?post=412172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}