Home > Backend Development > PHP Tutorial > PHP Authorization with JWT (JSON Web Tokens)

PHP Authorization with JWT (JSON Web Tokens)

Christopher Nolan
Release: 2025-02-08 09:57:09
Original
980 people have browsed it

PHP Authorization with JWT (JSON Web Tokens)

Application authentication used to rely solely on credentials such as username/mailbox and password, and the session was used to maintain user status until the user logs out. After that, we started using the authentication API. Recently, JSON Web Tokens (JWT) are increasingly used to authenticate server requests.

This article will introduce what JWT is and how to use PHP for JWT-based user request authentication.

Key points

  1. Evolution of Authentication Methods: This article outlines the evolution of user authentication methods, from traditional sessions to using JSON Web Tokens (JWT), highlighting the use of secure and efficient web applications Transformation in how user authentication and session management is done.
  2. Advantages and applications of JWT: This article explains the advantages of JWT over other authentication methods, such as the ability to store information and metadata, compatibility with OAUTH2, and the provision of expired controls, and illustrates the How JWT enhances the security and flexibility of the user authentication process.
  3. Practical Applications in PHP: This article provides a comprehensive guide to implementing JWT in PHP-based applications, covering the generation, use and verification of JWT. This includes detailed code examples and explanations, providing readers with a clear roadmap for integrating JWT-based authentication in their own web projects.

JWT and Session

First of all, why is the conversation not that good? There are three main reasons:

  • The data is stored on the server in plain text. Even if the data is not usually stored in a public folder, anyone with sufficient server access can read the contents of the session file.
  • They involve file system read/write requests. Each time a session starts or its data is modified, the server needs to update the session file. The same is true every time the app sends a session cookie. If the number of users is large, it may end up causing the server to slow down unless you use alternate session storage options such as Memcached and Redis.
  • Distributed/clustered applications. Since session files are stored on the file system by default, it is difficult to build distributed or clustered infrastructure for highly available applications (which require technologies such as load balancers and clustered servers). Other storage media and special configurations must be implemented, and their meaning must be fully understood.

JWT

Now, let's start learning JWT. The JSON Web Token Specification (RFC 7519) was first released on December 28, 2010, and the most recent update was in May 2015.

JWT has many advantages over API keys, including:

  • API keys are random strings, while JWTs contain information and metadata. This information and metadata may describe various contents, such as the identity of the user, authorization data, and the validity of the token in a time range or relative to the domain.
  • JWT does not require a centralized issuance or revocation agency.
  • JWT is compatible with OAUTH2.
  • JWT data can be checked.
  • JWT has expired control.
  • JWT is suitable for space-constrained environments, such as HTTP Authorization headers.
  • Data is transferred in JavaScript Object Notation (JSON) format.
  • JWT is represented using Base64url encoding.

What does JWT look like?

This is a JWT example:

<code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MTY5MjkxMDksImp0aSI6ImFhN2Y4ZDBhOTVjIiwic2NvcGVzIjpbInJlcG8iLCJwdWJsaWNfcmVwbyJdfQ.XCEwpBGvOLma4TCoh36FU7XhUbcskygS81HE1uHLf0E</code>
Copy after login
Copy after login
Copy after login
Copy after login

At first glance, this string seems to be just a random group of characters connected with periods or dot characters. So it doesn't seem to be any different from the API key. However, if you look closely, you will see that there are three separate strings.

JWT header

The first string is the JWT header. It is a Base64 URL-encoded JSON string. It specifies the encryption algorithm used to generate the signature and the type of the token, which is always set to JWT. The algorithm can be symmetrical or asymmetrical.

The symmetric algorithm uses a single key to create and verify tokens. This key is shared between the creator and consumer of the JWT. Be sure to make sure only the creator and consumer know the key. Otherwise, anyone can create a valid token. The asymmetric algorithm uses a private key to sign the token and uses a public key to verify the token. These algorithms should be used when the shared key is impractical or when other parties only need to verify the integrity of the token.

JWT's payload

The second string is the payload of JWT. It is also a Base64 URL-encoded JSON string. It contains some standard fields called "declaration". There are three types of declarations:

registered

, public and private. The registration statement is predefined. You can find a list of them in the RFC of JWT. Here are some commonly used statements:

iat: Date and timestamp issued by the token.
  • key: A unique string that can be used to verify the token, but this is contrary to the issuer institution without a centralized.
  • iss: A string containing the issuer's name or identifier. Can be a domain name that can be used to discard tokens from other applications.
  • nbf: The token should start to be considered a valid date and timestamp. Should be equal to or greater than iat.
  • exp: The date and timestamp that the token should stop valid. Should be greater than iat and nbf.
  • You can define public declarations as needed. However, they cannot be the same as a registered statement or a public statement that already exists. You can create a private statement as you like. They are for both parties only: producers and consumers.

JWT's signature

JWT's signature is an encryption mechanism designed to protect the JWT's data using a digital signature unique to the content of the token. Signature ensures the integrity of the JWT so that the user can verify that it has not been tampered with by the malicious actor.

JWT's signature is a combination of three things:

  • JWT's header
  • JWT's payload
  • A secret value

These three are digitally signed using the algorithm specified in the JWT header ( not encrypted). If we decode the example above, we will get the following JSON string:

JWT's header

<code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MTY5MjkxMDksImp0aSI6ImFhN2Y4ZDBhOTVjIiwic2NvcGVzIjpbInJlcG8iLCJwdWJsaWNfcmVwbyJdfQ.XCEwpBGvOLma4TCoh36FU7XhUbcskygS81HE1uHLf0E</code>
Copy after login
Copy after login
Copy after login
Copy after login

JWT's data

<code>{
    "alg": "HS256",
    "typ": "JWT"
}</code>
Copy after login
Copy after login
Copy after login

You can try jwt.io yourself, where you can try encoding and decoding your own JWT.

Use JWT in PHP-based applications

Now that you have learned what JWT is, it's time to learn how to use them in your PHP application. Feel free to clone the code of this article, or follow our steps before delving into it.

You can take a number of ways to integrate JWT, but here are the ones we will take.

Apart from the login and logout pages, all requests to the application need to be authenticated via JWT. If the user makes a request without a JWT, they will be redirected to the login page.

After the user fills in and submits the login form, the form will be submitted via JavaScript to the login endpoint authenticate.php in our application. The endpoint then pulls the credentials (username and password) from the request and checks that they are valid.

If valid, it will generate a JWT and send it back to the client. When the client receives the JWT, it stores the JWT and uses it for every future request to the application.

For a simple scenario, the user can only request one resource - a properly named PHP file resource.php. It doesn't do much, it just returns a string containing the current timestamp at the time of the request.

There are several ways to use JWT when making a request. In our application, the JWT will be sent in the Bearer authorization header.

If you are not familiar with Bearer Authorization, it is a form of HTTP authentication where a token (such as JWT) is sent in the request header. The server can check the token and determine whether the "holder" access to the token should be granted.

This is an example of a header:

<code>{
    "iat": 1416929109,
    "jti": "aa7f8d0a95c",
    "scopes": [
        "repo",
        "public_repo"
    ]
}</code>
Copy after login
Copy after login
Copy after login

For every request our application receives, PHP will try to extract the token from the Bearer header. If it exists, it is verified. If valid, the user will see a normal response to the request. However, if the JWT is invalid, the user is not allowed to access the resource.

Please note that JWT is not intended to replace session cookies.

Prerequisites

First of all, we need to install PHP and Composer on our system.

In the root directory of the project, run composer install. This will introduce Firebase PHP-JWT, a third-party library that simplifies JWT operations, and laminas-config for simplifying access to configuration data in applications.

Login form

Pictures

After installing the library, let us gradually complete the login code in authenticate.php. We first make the usual setup to ensure that the autoloader generated by Composer is available.

<code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MTY5MjkxMDksImp0aSI6ImFhN2Y4ZDBhOTVjIiwic2NvcGVzIjpbInJlcG8iLCJwdWJsaWNfcmVwbyJdfQ.XCEwpBGvOLma4TCoh36FU7XhUbcskygS81HE1uHLf0E</code>
Copy after login
Copy after login
Copy after login
Copy after login

After receiving the form submission, the credentials will be verified against the database or some other data store. For the purposes of this example, we will assume they are valid and set $hasValidCredentials to true.

<code>{
    "alg": "HS256",
    "typ": "JWT"
}</code>
Copy after login
Copy after login
Copy after login

Next, we initialize a set of variables to generate JWT. Remember that since JWT can be checked on the client, don't include any sensitive information in it. Another thing worth pointing out is that $secretKey is not initialized like this. You might set it in your environment and extract it, use libraries like phpdotenv, or set it in a configuration file. In this case, I avoid doing this because I want to focus on the JWT code.

Don't leak it or store it under version control!

After preparing the payload data, we next use php-jwt's static encode method to create the JWT.
<code>{
    "iat": 1416929109,
    "jti": "aa7f8d0a95c",
    "scopes": [
        "repo",
        "public_repo"
    ]
}</code>
Copy after login
Copy after login
Copy after login

This method:

Convert array to JSON
  • Generate header
  • Sign the payload
  • Encoding final string
  • It accepts three parameters:

Payload information
  • Key
  • Algorithm for signing tokens
  • Return the generated token by calling echo on the function result:

Using JWT
<code>Authorization: Bearer ab0dde18155a43ee83edba4a4542b973</code>
Copy after login

Pictures

Now that the client has the token, you can store it using JavaScript or any mechanism you like. Here is an example of how to operate using native JavaScript. In index.html, after the form is successfully submitted, the received JWT will be stored in memory, the login form will be hidden, and a button requesting the timestamp will be displayed:

Using JWT
<?php
declare(strict_types=1);

use Firebase\JWT\JWT;

require_once('../vendor/autoload.php');
Copy after login

When you click the Get Current Timestamp button, a GET request is issued to resource.php, which sets the JWT you received after authentication in the Authorization header.

When we click the button, a request similar to the following will be issued:
<?php
// 从请求中提取凭据

if ($hasValidCredentials) {
Copy after login

Assuming that the JWT is valid, we will see the resource and the response will be written to the console after that.
$secretKey  = 'bGS6lzFqvvSQ8ALbOxatm7/Vk7mLQyzqaS34Q4oR1ew=';
$issuedAt   = new DateTimeImmutable();
$expire     = $issuedAt->modify('+6 minutes')->getTimestamp();      // 添加60秒
$serverName = "your.domain.name";
$username   = "username";                                           // 从过滤后的POST数据中检索

$data = [
    'iat'  => $issuedAt->getTimestamp(),         // 颁发时间:生成令牌的时间
    'iss'  => $serverName,                       // 颁发者
    'nbf'  => $issuedAt->getTimestamp(),         // 不早于
    'exp'  => $expire,                           // 过期
    'userName' => $username,                     // 用户名
];
Copy after login

Verify JWT

Finally, let's see how to verify the token in PHP. As always, we will include the Composer's autoloader. We can then choose to check if the correct request method is used. To keep focusing on JWT-specific code, I've skipped the code that does this:

The code will then try to extract the token from the Bearer header. I've done this using preg_match. If you are not familiar with the function, it will perform regular expression matching on the string.
<?php     // 将数组编码为JWT字符串。
    echo JWT::encode(
        $data,
        $secretKey,
        'HS512'
    );
}
Copy after login

The regex I'm using here will try to extract the token from the Bearer header and dump everything else. If not found, an HTTP 400 error request is returned:

Note that by default, Apache does not pass the HTTP_AUTHORIZATION header to PHP. The reason behind it is:
const store = {};
const loginButton = document.querySelector('#frmLogin');
const btnGetResource = document.querySelector('#btnGetResource');
const form = document.forms[0];

// 将jwt插入到store对象中
store.setJWT = function (data) {
  this.JWT = data;
};

loginButton.addEventListener('submit', async (e) => {
  e.preventDefault();

  const res = await fetch('/authenticate.php', {
    method: 'POST',
    headers: {
      'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'
    },
    body: JSON.stringify({
      username: form.inputEmail.value,
      password: form.inputPassword.value
    })
  });

  if (res.status >= 200 && res.status < 300) {
    const jwt = await res.text();
    store.setJWT(jwt);
    frmLogin.style.display = 'none';
    btnGetResource.style.display = 'block';
  } else {
    // 处理错误
    console.log(res.status, res.statusText);
  }
});
Copy after login

The basic authorization header is only secure when your connection is completed over HTTPS, because otherwise the credentials will be sent over the network in encoded plaintext (unencrypted), which is a huge security issue.

I fully understand the logic of this decision. However, to avoid a lot of confusion, add the following to your Apache configuration. The code will then work as expected. If you are using NGINX, the code should work as expected:

<code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MTY5MjkxMDksImp0aSI6ImFhN2Y4ZDBhOTVjIiwic2NvcGVzIjpbInJlcG8iLCJwdWJsaWNfcmVwbyJdfQ.XCEwpBGvOLma4TCoh36FU7XhUbcskygS81HE1uHLf0E</code>
Copy after login
Copy after login
Copy after login
Copy after login

Next, we try to extract the matching JWT, which will be in the second element of the $matches variable. If unavailable, no JWT is extracted and an HTTP 400 error request is returned:

<code>{
    "alg": "HS256",
    "typ": "JWT"
}</code>
Copy after login
Copy after login
Copy after login

If we reach this point, the JWT has been extracted, so we go to the decoding and verification phase. To do this, we need our key again, which will be extracted from the configuration of the environment or application. Then, we use php-jwt's static decode method to pass it to the JWT, the key and a set of algorithms used to decode the JWT. If it can be successfully decoded, we will try to verify it. My example here is very simple because it only uses issuer, no earlier than, and expired timestamps. In a real application, you may also use many other statements.

If the token is invalid, such as the token has expired, the user will receive the HTTP 401 unauthorized header and the script will exit.
<code>{
    "iat": 1416929109,
    "jti": "aa7f8d0a95c",
    "scopes": [
        "repo",
        "public_repo"
    ]
}</code>
Copy after login
Copy after login
Copy after login

If the decoding and verification process fails, it may be:

The number of segments provided does not match the standard three segments described above.
  • The header or payload is not a valid JSON string.
  • The signature is invalid, which means the data has been tampered with!
  • The nbf declaration is set in JWT, and its timestamp is smaller than the current timestamp.
  • The iat declaration is set in JWT, and its timestamp is smaller than the current timestamp.
  • An exp declaration is set in JWT, whose timestamp is greater than the current timestamp.
  • As you can see, JWT has a nice set of controls that you can mark it as invalid without manually revoking or checking against a list of valid tokens.

If the decoding and verification process is successful, the user will be allowed to issue a request and will receive a corresponding response.

Summary

This is a quick introduction to JSON Web Tokens (or JWT) and how to use them in PHP-based applications. From here you can try implementing JWT in the next API, maybe try some other signature algorithm that uses asymmetric keys like RS256, or integrate it into an existing OAUTH2 authentication server to use as API key .

If you have any comments or questions, please feel free to contact us via Twitter.

FAQs on using JWT for PHP authorization

Can we use JWT in PHP?

You can indeed use JWT in PHP to establish authentication and authorization mechanisms in your web application. To get started, you need to use Composer to install the PHP JWT library, such as "firebase/php-jwt" or "lcobucci/jwt". These libraries provide the necessary tools for creating, encoding, decoding, and validating JWTs. To create a JWT, you can use the library to build a token that contains statements such as issuer, audience, expiration time, and more. Once created, you can sign the token with the key. When receiving a JWT, you can use the library to decode and verify it to ensure its authenticity. If the token is valid and verified, you can access its declaration to determine user identity and permissions, allowing you to implement secure authentication and authorization in your PHP application. Protecting your keys and following security best practices when using JWT is critical to prevent unauthorized access to application resources.

What is JWT authentication in PHP?

JWT (JSON Web Token) authentication in PHP is a method widely used to implement user authentication and authorization in web applications. It is based on token authentication and enables secure and stateless user authentication. Here is how JWT authentication works in PHP: First, during user authentication or login, the server generates a JWT, a compact, self-contained token containing information (claims) related to the user, such as user ID, username, and role. These declarations are usually JSON data. The server then signs this token with a key to ensure its integrity and authenticity. Second, after successful authentication, the server sends the JWT back to the client, which is usually stored in a secure location such as HTTP cookies or local storage. This token serves as proof of authentication. Finally, for subsequent requests to protected resources on the server, the client appends a JWT to the request header, usually using the "Authorization" header with the "Bearer" scheme. After receiving the JWT, the server uses the same key used during the token creation to verify its signature. Additionally, it checks whether the token has not expired and contains a valid declaration. After successful verification, it extracts user information from the token declaration and implements authorization logic to ensure that the user has the permissions needed to access the requested resource. This approach allows secure, stateless authentication in PHP applications without server-side session storage. While JWT authentication in PHP provides many benefits such as scalability and statelessness, best practices for protecting keys and adopting token management are essential to maintaining the security of your application. Using established PHP JWT libraries can simplify token processing and enhance security.

What is the alternative to JWT in PHP?

The alternative to JWT (JSON Web Tokens) for authentication and authorization in PHP is session-based authentication. In session-based authentication, the server maintains one session for each authenticated user. When the user logs in, a unique session identifier is created (usually stored as a session cookie on the client browser). This identifier is used to associate the user with server-side session data, including information related to the user, such as user ID, user name, and permissions. Session-based authentication provides simplicity and ease of implementation, making it suitable for a variety of web applications, especially if you don't need the stateless and scalable capabilities of JWT. It is stateful by nature, which can be advantageous when you need to manage user-specific data (such as shopping cart content or user preferences) during a user session. However, there are a few things to consider when using session-based authentication. It may not be quite applicable for distributed or microservice-based architectures that require stateless authentication. Additionally, managing user sessions may increase server load, especially in applications with larger user bases. Ultimately, choosing JWT and session-based authentication in PHP should match the specific needs and design considerations of the application to ensure a secure and effective authentication mechanism best meets your needs.

How to protect PHP API using JWT?

Protecting the PHP API with JWT (JSON Web Tokens) involves a multi-step process that combines authentication and authorization. First, select the appropriate PHP JWT library (such as "firebase/php-jwt" or "lcobucci/jwt") to handle the token-related operations and use Composer to manage dependencies. For authentication, you need to implement a user authentication system in your PHP application. This system verifies user credentials against your database or authentication provider. After successful authentication, you will generate a JWT token containing user-related claims such as the user's ID, username, and role. Be sure to set the expiration time to control the validity of the token and then sign the token with the key. This signed token is sent back to the client as part of the authentication response. Clients securely store the received JWT, usually in HTTP cookies or local storage. For subsequent API requests, the client will include a JWT in the request header as the "Authorization" header with the "Bearer" scheme. In your PHP API, you can verify the incoming JWT by verifying its signature using the same key used when creating the token. Additionally, you check that the token has not expired and contains a valid declaration. After successful verification, you extract user information from the token declaration and implement authorization logic to ensure that the user has the permissions required to access the requested resource. Keeping the key secure is crucial because it is crucial to signing and verifying the token. Any leakage of this key can lead to a serious security vulnerability.

The above is the detailed content of PHP Authorization with JWT (JSON Web Tokens). For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template