Home >Backend Development >PHP Tutorial >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
JWT and Session
First of all, why is the conversation not that good? There are three main reasons:
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:
What does JWT look like?
This is a JWT example:
<code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MTY5MjkxMDksImp0aSI6ImFhN2Y4ZDBhOTVjIiwic2NvcGVzIjpbInJlcG8iLCJwdWJsaWNfcmVwbyJdfQ.XCEwpBGvOLma4TCoh36FU7XhUbcskygS81HE1uHLf0E</code>
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.
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
, 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.
JWT's signature
JWT's signature is a combination of three things:
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>
JWT's data
<code>{ "alg": "HS256", "typ": "JWT" }</code>
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>
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.
PrerequisitesIn 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
<code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MTY5MjkxMDksImp0aSI6ImFhN2Y4ZDBhOTVjIiwic2NvcGVzIjpbInJlcG8iLCJwdWJsaWNfcmVwbyJdfQ.XCEwpBGvOLma4TCoh36FU7XhUbcskygS81HE1uHLf0E</code>
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>
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>
This method:
Convert array to JSON
Payload information
Using JWT
<code>Authorization: Bearer ab0dde18155a43ee83edba4a4542b973</code>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
<code class="language-php"><?php declare(strict_types=1); use Firebase\JWT\JWT; require_once('../vendor/autoload.php');</code>
When we click the button, a request similar to the following will be issued:
<code class="language-php"><?php // 从请求中提取凭据 if ($hasValidCredentials) {</code>
Assuming that the JWT is valid, we will see the resource and the response will be written to the console after that.
<code class="language-php">$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, // 用户名 ];</code>
Verify JWT
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.
<code class="language-php"><?php // 将数组编码为JWT字符串。 echo JWT::encode( $data, $secretKey, 'HS512' ); }</code>
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:
<code class="language-javascript">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); } });</code>
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>
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>
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>
If the decoding and verification process fails, it may be:
The number of segments provided does not match the standard three segments described above.
If the decoding and verification process is successful, the user will be allowed to issue a request and will receive a corresponding response.
SummaryThis 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 authorizationYou 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. 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. 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. 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. Can we use JWT in PHP?
What is JWT authentication in PHP?
What is the alternative to JWT in PHP?
How to protect PHP API using JWT?
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!