
JSON Web Encryption (JWE): A Comprehensive Guide
Introduction
Understanding JSON Web Encryption (JWE)
JSON Web Encryption (JWE) is a standard for the secure transmission of data in a compact and URL-secure format. It ensures confidentiality by encrypting sensitive information so that it cannot be read without the correct decryption key. JWE is part of the broader JOSE (JavaScript Object Signing and Encryption) framework, which also includes JSON Web Tokens (JWT) and JSON Web Signatures (JWS).
The importance of securing sensitive data
Data security is an important issue for modern applications, especially when personal, financial or authentication-related information is transmitted over networks. Encrypting data with JWE offers several advantages:
Protection of sensitive information
JWE ensures that only authorized parties can access the encrypted data, preventing unauthorized access even if the token is intercepted.
Compliance with security regulations
Many industries, such as healthcare (HIPAA) and finance (PCI DSS), require encryption to protect customer data. JWE helps to comply with these regulations.
Increased API security
APIs often exchange sensitive data between customers and servers. Using JWE to encrypt API responses and requests ensures that the content of a token remains confidential even if it is disclosed.
The difference between JWE and JWT
JSON Web Encryption (JWE) and JSON Web Tokens (JWT) are both part of the JOSE framework, but they serve different purposes:
JWT (JSON Web Token)
- Is generally used for authentication and authorization
- Consists of three parts: Header, payload and signature
- The user data is not encrypted — it is only base64-encoded and signed
- Used when the integrity and authenticity of the data is paramount
JWE (JSON Web Encryption)
- Focuses on confidentiality by encrypting the user data
- Consists of five parts: Header, encrypted key, IV, ciphertext and authentication tag
- Prevents unauthorized persons from reading the data even if they receive the token
- Used when data confidentiality is a priority
When should you use JWE?
JWE is useful in scenarios where the protection of sensitive information is critical:
Securing user data in transit
If you are transferring personal or financial data over an insecure network, JWE ensures that the information remains private.
Store encrypted data in databases
Some applications store JWTs in databases for authentication or session management. Encrypting these tokens prevents sensitive information from being disclosed through leaks in the database.
Protection of multi-tenant applications
In cloud-based applications that serve multiple customers, encrypting data with JWE ensures that tenant-specific information remains confidential.
What is JSON Web Encryption (JWE)
Overview of JWE
JSON Web Encryption (JWE) is a standard for the secure transmission of data through encryption. In contrast to JSON Web Tokens (JWT), which are primarily concerned with integrity and authenticity, JWE ensures confidentiality by encrypting the user data in such a way that only authorized recipients can read it.
JWE is defined in the RFC 7516 specification and is part of the broader JOSE (JavaScript Object Signing and Encryption) Framework, which also includes JSON Web Signature (JWS) and JSON Web Key (JWK).
The most important components of a JWE token
A JWE token consists of five parts, each of which has a specific function in encryption and decryption:
JWE header
- Contains metadata about the encryption algorithm used
- Specifies how the encryption key is managed
- Example (Base64URL-encoded JSON):
{
"alg": "RSA-OAEP",
"enc": "A256GCM"
}
In this example:
"alg": "RSA-OAEP"
indicates that the key is encrypted with RSA-OAEP"enc": "A256GCM"
indicates that AES-GCM-256 is used to encrypt the content
Encrypted key
- Stores the encrypted version of the Content Encryption Key (CEK)
- The key is encrypted with the algorithm specified in the header (
"alg"
) - Only the intended recipient with the correct private key can decrypt this section
Initialization vector (IV)
- A random value used to increase encryption security
- Prevents attackers from recognizing patterns in encrypted data
- Essential for block ciphers such as AES-GCM and AES-CBC
Ciphertext
- The actual encrypted payload (data)
- Ensures that the content remains unreadable even if the token is intercepted
Authentication tag
- Verifies that the encrypted data has not been tampered with
- Ensures the integrity and authenticity of the encrypted message
How does JWE differ from JWS?
JSON Web Encryption (JWE) and JSON Web Signature (JWS) are often confused because they both deal with securing JSON-based data. However, their main goals are different:
JSON Web Signature (JWS)
- Ensures data integrity and authenticity
- Uses a digital signature to verify that the data has not been altered
- User data remains visible but is protected from tampering
- Often used for authentication tokens (JWTs)
JSON Web Encryption (JWE)
- Ensures the confidentiality of the data by encrypting the user data
- The content remains hidden for unauthorized persons
- Used when sensitive data needs to be kept private
- Suitable for secure data exchange via public networks
Advantages of JWE
The use of JWE offers several security advantages for applications that handle sensitive data:
End-to-end data protection
JWE encrypts the user data and ensures that only the intended recipient can decrypt and access the information.
Secure API communication
JWE is often used in APIs to encrypt responses and requests and thus protect sensitive information from attackers.
Compliance with security standards
Industries such as finance, healthcare and e-commerce require encryption to meet regulatory requirements such as GDPR, HIPAA and PCI DSS. JWE helps achieve these security goals.
Mitigation against data leaks
If an attacker intercepts a JWE token, they cannot read its contents without the corresponding decryption key, reducing the risk of data exposure.
Structure of a JWE token
Understanding the JWE format
A JSON Web Encryption (JWE) token consists of five different parts, each of which has a specific task in encrypting and securing the data. These parts are separated by dots (.
), which makes JWE similar to JSON Web Tokens (JWT). However, unlike JWT, the JWE payload is fully encrypted and cannot be read without the correct decryption key.
A JWE token has the following structure:
BASE64URL(Protected header) .
BASE64URL(Encrypted key) .
BASE64URL(Initialization vector) .
BASE64URL(Ciphertext) .
BASE64URL(Authentication tag)
Each of these components is encrypted with Base64URL to ensure that they can be transmitted securely over networks.
Breakdown of the JWE components
JWE header
- A Base64URL-encoded JSON object that contains metadata about the encryption method used.
- It specifies:
- The algorithm used to encrypt the key (
"alg"
) - The encryption method that was applied to the payload (
"enc"
) - Additional headers for the key agreement or integrity check
- The algorithm used to encrypt the key (
Example header:
{
"alg": "RSA-OAEP",
"enc": "A256GCM"
}
"alg": "RSA-OAEP"
→ RSA-OAEP is used to encrypt the key."enc": "A256GCM"
→ AES-GCM-256 is used to encrypt the content.
Encrypted key
- Contains the Encrypted Content Encryption Key (CEK).
- The CEK is used to encrypt the actual payload (ciphertext).
- Only the recipient who has the corresponding private key can decrypt this section and retrieve the CEK.
Example (Base64URL-encrypted):
nZJvY3lQ3x8Qg... (shortened for better readability)
Initialization vector (IV)
- A random value used during encryption to ensure that the output is different even if the same data is encrypted multiple times.
- This prevents attackers from recognizing patterns in encrypted data.
- Required for certain encryption algorithms such as AES-GCM and AES-CBC.
Example (Base64URL-encrypted):
h3CC9eWfW8fU... (shortened for better readability)
Ciphertext
- The actual encrypted payload (data).
- This section contains the original data in encrypted form.
- Without the correct key, this data is unreadable.
Example (Base64URL-encrypted):
4fsd9LsGJWpY... (shortened for readability)
Authentication tag
- A checksum that ensures that the encrypted data has not been tampered with.
- Used in authenticated encryption algorithms such as AES-GCM.
- If any part of the token is altered, decryption will fail due to an invalid authentication tag.
Example (Base64URL encrypted):
JYHgZJ3KjWf0... (shortened for readability)
Example of a complete JWE token
A complete JWE token looks like this:
eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.
XtjS7wXH6T5_wz...
YVnQ8j34uMC6yf...
qRTzt4wF9Hc_jg...
hW77jT3uN0fKbO...
Each section represents a Base64URL-encoded part of the JWE structure.
How JWE ensures data security
- Confidentiality: The user data is fully encrypted so that unauthorized persons cannot read its content.
- Integrity: The authentication tag prevents manipulation of the encrypted data.
- Key management: The encrypted key ensures that only authorized recipients can decrypt the user data.
By using this structured format, JWE provides a robust mechanism for the secure exchange of sensitive information over networks.
Encryption algorithms in JWE
Overview of JWE encryption
JSON Web Encryption (JWE) uses several encryption techniques to secure data. The encryption process in JWE is divided into two main parts:
- Key Encryption: The Content Encryption Key (CEK) is encrypted using an asymmetric or symmetric algorithm.
- Content Encryption: The actual payload is encrypted using the CEK with a symmetric encryption algorithm.
Each of these encryption levels requires a different algorithm to ensure both confidentiality and secure key exchange.
Types of encryption algorithms in JWE
Key encryption algorithms
Key encryption algorithms are used to encrypt the Content Encryption Key (CEK). These algorithms can be either asymmetric (public-key-based) or symmetric (shared-secret-based).
Asymmetric key encryption (public-key cryptography)
These algorithms use a pair of public and private keys, whereby the sender encrypts the CEK with the recipient’s public key and only the recipient can decrypt it with their private key.
Common asymmetric key encryption algorithms in JWE:
- RSA-OAEP (Rivest-Shamir-Adleman Optimal Asymmetric Encryption Padding)
- More secure than RSA1_5 due to padding improvements.
- Example of a use case: Encryption of CEK for secure transmission.
"alg": "RSA-OAEP"
- ECDH-ES (Elliptic Curve Diffie-Hellman Ephemeral Static)
- Uses elliptic curve cryptography for key agreement.
- For modern applications it is more efficient than RSA.
"alg": "ECDH-ES"
Symmetric key encryption (shared secret)
For cases where both parties have a shared secret key, symmetric key encryption can be used.
Common symmetric key encryption algorithms in JWE:
- A128KW, A192KW, A256KW (AES Key Wrap)
- Uses AES (Advanced Encryption Standard) to wrap the CEK securely.
"alg": "A256KW"
- PBES2-HS256+A128KW (Password-Based Encryption Scheme 2)
- Derives an encryption key from a password with PBKDF2.
- Useful for cases where passwords are involved in key management.
"alg": "PBES2-HS256+A128KW"
Content encryption algorithms
After the CEK has been decrypted, it is used to encrypt the actual payload. These algorithms ensure the confidentiality of the data.
AES-GCM (Advanced Encryption Standard – Galois/Counter Mode)
- Highly secure and widely recommended due to its built-in authentication.
- Provides both encryption and integrity checking.
"enc": "A256GCM"
for AES-256-GCM.
AES-CBC-HMAC-SHA2 (Cipher Block Chaining Mode + HMAC for integrity)
- Uses AES in CBC mode for encryption and HMAC-SHA2 for integrity checking.
"enc": "A128CBC-HS256"
for AES-128-CBC with HMAC-SHA256."enc": "A256CBC-HS512"
for AES-256-CBC with HMAC-SHA512.
How does encryption work in JWE?
The encryption process in JWE follows these steps:
Generation of the Content Encryption Key (CEK)
- A random CEK is generated for the encryption of the user data.
Encrypting the CEK
- The CEK is encrypted with the selected key encryption algorithm (e.g. RSA-OAEP or AES Key Wrap).
Encrypting the user data
- The actual JSON payload is encrypted with the Content Encryption Algorithm (e.g. AES-GCM).
Creating the authentication tag
- When using AES-GCM or AES-CBC-HMAC-SHA2, an authentication tag is generated for the integrity check.
Creating the JWE token
- The JWE token is created by assembling the header, the encrypted CEK, the IV, the ciphertext and the authentication tag, all Base64URL encoded.
Choosing the right encryption algorithm
The choice of the right encryption algorithm depends on the respective application:
- For secure API communication: Use AES-GCM with RSA-OAEP key encryption.
- For performance sensitive applications: ECDH-ES is a lightweight alternative to RSA.
- For password-based encryption: PBES2-HS256+A128KW is suitable for protecting user-generated secrets.
By using these encryption algorithms effectively, JWE provides a robust mechanism for securing sensitive information in web applications and APIs.
How JWE works: step-by-step process
Overview of the JWE process
JSON Web Encryption (JWE) secures sensitive data by encrypting it and ensuring that only authorized recipients can decrypt and access it. The process includes key encryption, content encryption and token generation.
JWE encryption follows these steps:
- Generate a Content Encryption Key (CEK).
- Encrypt the CEK with a Key Encryption Algorithm.
- Encrypt the Payload using the CEK with a Content Encryption Algorithm.
- Create an Authentication Tag to ensure data integrity.
- Create the JWE token by combining the encrypted components.
Creating a JWE token
Step 1: Creating the JWE header
The JWE header contains metadata about the encryption process, such as
- The algorithm for key encryption (
alg
). - The algorithm for encrypting the content (
enc
). - Optional parameters such as
kid
(key ID).
Example JWE header
{
"alg": "RSA-OAEP",
"enc": "A256GCM"
}
"alg": "RSA-OAEP"
→ The CEK is encrypted with RSA-OAEP."enc": "A256GCM"
→ The payload is encrypted with AES-256-GCM.
This header is Base64URL-encrypted before it is included in the JWE token.
Step 2: Generating and encrypting the Content Encryption Key (CEK)
- A random CEK is generated.
- The CEK is encrypted using the algorithm specified in
"alg"
.
For example, if "alg": "RSA-OAEP"
is used, the CEK is encrypted with the RSA Public Key of the recipient.
Base64URL-encoded encrypted key Example
XtjS7wXH6T5_wz...
Step 3: Encrypting the user data
- The actual data (user data) is encrypted using the CEK and the
"enc"
algorithm (e.g. AES-256-GCM). - An initialization vector (IV) is generated to ensure unique encryption results.
- The encrypted data is called ciphertext.
Example of encrypted user data (Base64URL-encrypted)
qRTzt4wF9Hc_jg...
Step 4: Creating an authentication tag
If an authenticated encryption algorithm (such as AES-GCM) is used, an authentication tag is generated. This tag is used to check that the encrypted data has not been changed.
Example of an authentication tag (Base64URL-encoded)
JYHgZJ3KjWf0...
Step 5: Constructing the JWE token
The final JWE token is created by concatenating the Base64URL encoded components:
BASE64URL(Protected header) .
BASE64URL(Encrypted key) .
BASE64URL(Initialization vector) .
BASE64URL(Ciphertext) .
BASE64URL(Authentication tag)
Example JWE Token
eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.
XtjS7wXH6T5_wz...
YVnQ8j34uMC6yf...
qRTzt4wF9Hc_jg...
hW77jT3uN0fKbO...
Decrypting and restoring the original data
Step 1: Parsing the JWE token
The receiver extracts the five components from the JWE token.
Step 2: Decrypting the Content Encryption Key (CEK)
- The recipient decrypts the CEK with his private key (if asymmetric encryption was used).
- If a symmetric algorithm was used (e.g. AES key wrap), the shared secret is used to decrypt the CEK.
Step 3: Decrypting the payload
- The decrypted CEK is used to decrypt the ciphertext with the algorithm specified in the
"enc"
field. - The initialization vector (IV) is used in the decryption process.
Step 4: Check the authentication tag
- If an authenticated encryption method (such as AES-GCM) was used, the receiver checks the authentication tag.
- If the tag does not match, the data has been corrupted and decryption will fail.
Step 5: Access to the original user data
If all decryption steps were successful, the original plain text user data is retrieved. The recipient can now use the decrypted data securely.
Example of a JWE decryption process (Python)
Using the Python libraries PyCryptodome and PyJWT (jose), a JWE decryption process could look like this:
from jose import jwe from Crypto.PublicKey import RSA
#Load the recipient’s private key private_key = RSA.import_key(open("private.pem").read())
#Encrypted JWE token (example)
jwe_token = "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ..."
#Decrypt the JWE token decrypted_data = jwe.decrypt(jwe_token, private_key)
print(decrypted_data.decode("utf-8"))
This script:
- Loads the private RSA key.
- Decrypts the JWE token.
- Prints the original JSON payload.
Through this structured encryption and decryption process, JWE ensures that sensitive data remains protected and can only be accessed by authorized recipients.
Implementing JWE in different languages
Overview of the JWE implementation
JSON Web Encryption (JWE) can be implemented with different cryptographic libraries in different programming languages. The implementation process includes the following:
- Creating a JWE token by encrypting the payload.
- Decrypting a JWE token to extract the original data.
Various libraries support JWE, such as:
- Python:
PyJWT
,cryptography
,jose
- Node.js:
jose
,jsonwebtoken
- Java:
Nimbus JOSE+JWT
- Go:
golang.org/x/crypto
- C#:
Microsoft.IdentityModel.Tokens
Implement JWE in Python
Installation of the required libraries
pip install pyjwt cryptography
Encrypt data with JWE in Python
from jose import jwe from Crypto.PublicKey import RSA
#Load the public key for the encryption public_key = RSA.import_key(open("public.pem").read())
#Data to be encrypted payload = b'{"message": "Confidential data"}'
#Encrypt the data jwe_token = jwe.encrypt(payload, public_key, algorithm="RSA-OAEP", encryption="A256GCM")
print(jwe_token)
- The function
jwe.encrypt()
encrypts the payload with the public key of the recipient. - the CEK is encrypted with “RSA-OAEP”
and the actual payload is encrypted with "A256GCM"
.
Decrypt JWE in Python
#Load the private key for decryption private_key = RSA.import_key(open("private.pem").read())
#Decrypt JWE token decrypted_data = jwe.decrypt(jwe_token, private_key)
print(decrypted_data.decode("utf-8"))
- The function
jwe.decrypt()
decrypts the token with the private key of the recipient. - The original JSON payload is restored.
Implementing JWE in Node.js
Installation of the required libraries
npm install jose
Encrypt data with JWE in Node.js
import { compactEncrypt } from 'jose';
// Load public key const publicKey = await importSPKI(PUBLIC_KEY_PEM, 'RSA-OAEP');
// Encrypt the user data const jweToken = await new compactEncrypt(
new TextEncoder().encode(JSON.stringify({ message: "Confidential data" })))
)
.setProtectedHeader({ alg: "RSA-OAEP", enc: "A256GCM" })
.encrypt(publicKey);
console.log(jweToken);
- Uses the
jose
library to create a JWE token. - The user data is encrypted with
"A256GCM"
and the CEK is encrypted with"RSA-OAEP"
.
Decrypt JWE in Node.js
import { compactDecrypt } from 'jose';
// Load private key const privateKey = await importPKCS8(PRIVATE_KEY_PEM, 'RSA-OAEP');
// Decrypt the JWE token const { plaintext } = await compactDecrypt(jweToken, privateKey);
console.log(new TextDecoder().decode(plaintext));
- The
compactDecrypt()
function decrypts the JWE token and restores the original payload.
Implementing JWE in Java
Adding dependencies (Maven)
<dependency>
com.nimbusds
<artifactId>nimbus-jose-jwt</artifactId>
9.23
</dependency>
Encrypting data with JWE in Java
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.*;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.*;
import java.security.interfaces.RSAPublicKey;
public class JWEExample {
public static void main(String[] args) throws Exception {
// Load public key
RSAKey rsaKey = RSAKey.parse(PUBLIC_KEY_JSON);
RSAPublicKey publicKey = rsaKey.toRSAPublicKey();
// Create the payload
Payload payload = new Payload("{\"Message\": \"Confidential data\"}");
// Encrypt with JWE
JWEObject jweObject = new JWEObject(
new JWEHeader.Builder(JWEAlgorithm.RSA_OAEP, EncryptionMethod.A256GCM).build(),
payload
);
jweObject.encrypt(new RSAEncrypter(publicKey));
String jweToken = jweObject.serialize();
System.out.println(jweToken);
}
}
- Uses Nimbus JOSE+JWT to encrypt the user data with AES-GCM and RSA-OAEP.
Decrypt JWE in Java
import com.nimbusds.jose.crypto.*;
import com.nimbusds.jose.*;
import java.security.interfaces.RSAPrivateKey;
public class JWEDecrypt {
public static void main(String[] args) throws Exception {
// Load private key
RSAKey rsaKey = RSAKey.parse(PRIVATE_KEY_JSON);
RSAPrivateKey privateKey = rsaKey.toRSAPrivateKey();
// Parse and decrypt the JWE token
JWEObject jweObject = JWEObject.parse(jweToken);
jweObject.decrypt(new RSADecrypter(privateKey));
System.out.println(jweObject.getPayload().toString());
}
}
- The function
JWEObject.decrypt()
decrypts the JWE token and retrieves the plain text of the user data.
Implementing JWE in Go
Installation of the required package
go get github.com/square/go-jose/v3
Encrypt data with JWE in Go
package main
import (
"encoding/json"
"fmt"
"github.com/square/go-jose/v3"
"crypto/rand"
"crypto/rsa"
)
func main() {
// Generate an RSA key
privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
publicKey := &privateKey.PublicKey
// Create JWE encryption program
encrypter, _ := jose.NewEncrypter(jose.A256GCM, jose.Recipient{Algorithm: jose.RSA_OAEP, Key: publicKey}, nil)
// Encrypt data
plaintext, _ := json.Marshal(map[string]string{"message": "Confidential data"})
encrypted, _ := encrypter.Encrypt(plaintext)
jweToken, _ := encrypted.CompactSerialize()
fmt.Println(jweToken)
}
- Uses
square/go-jose
to encrypt JSON payloads with AES-GCM.
Decrypting JWE in Go
package main
import (
"fmt"
"github.com/square/go-jose/v3"
)
func main() {
// Parse JWE token
encrypted, _ := jose.ParseEncrypted(jweToken)
// Decrypt JWE
decrypted, _ := encrypted.decrypt(privateKey)
fmt.Println(string(decrypted))
}
- The original data is restored with the function
ParseEncrypted().Decrypt()
.
Selecting the correct library for JWE
The choice of library depends on the programming language and the use case:
- Python:
jose
(Simple implementation, good for API security). - Node.js:
jose
(Recommended for JavaScript-based applications). - Java: nimbus JOSE+JWT` (enterprise level security).
- Go:
square/go-jose
(Good for cloud and microservices). - C#: microsoft.IdentityModel.Tokens” (best for .NET applications).
If you implement JWE correctly, applications can securely transfer encrypted data across different platforms while ensuring confidentiality.
JWE use cases and applications
Overview of the JWE applications
JSON Web Encryption (JWE) is often used in applications that require secure data transmission, confidentiality and protection against unauthorized access. By encrypting sensitive data, JWE ensures that the content of a token remains unreadable even if it is intercepted.
JWE is often used in:
- secure API communication
- Data protection in web applications
- Secure storage of tokens and credentials
- Multi-tenant cloud applications
Secure API communication
Encrypt API responses
APIs that transmit sensitive information (such as personal data, payment details or authentication tokens) can use JWE to encrypt responses.
Example scenario
- A bank API sends account data in a JWE token instead of plain JSON.
- Only the authorized customer with the private key can decrypt and access the account data.
Example JWE response
{
"access_token": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ..."
}
- Instead of sending sensitive data as plain text, the server encrypts it with JWE.
Securing API authentication tokens
Traditional JWTs (JSON Web Tokens) are signed but not encrypted, i.e. their content is visible if intercepted.
- Using JWE for authentication tokens ensures that the content of a token remains unreadable even if it is intercepted.
- Prevents the disclosure of sensitive data such as user roles, authorizations and session data.
Example of a use case:
- OAuth 2.0 Access tokens encrypted with JWE provide an additional layer of security compared to JWTs.
Protection of sensitive data in web applications
Encryption of user data during transmission
Web applications often process user data, including:
- Personal data (name, email, phone number)
- Financial information (credit card details, bank accounts)
- Medical data (health reports, prescriptions)
By using JWE, applications can encrypt user data before it is sent over an insecure network to ensure that
- The data is not visible to intermediaries.
- Only the intended recipient can decrypt and access the data.
Application example: Secure messaging app
- A messaging app encrypts private messages with JWE before they are sent.
- Only the recipient can decrypt the message.
- Even if a hacker intercepts the data, they cannot read it.
Encryption of form transmissions
- Online forms that collect sensitive data (e.g. tax forms, job applications or insurance applications) can use JWE to encrypt the input.
- The backend decrypts the JWE token on receipt, ensuring secure transmission.
Secure storage of tokens and credentials
Encryption of refresh tokens in databases
- Many applications store refresh tokens to keep users logged in.
- In the event of a database breach, attackers could steal plain text refresh tokens and gain unauthorized access.
- Storing encrypted refresh tokens with JWE prevents this risk.
Example: Encrypting tokens before storing them
Instead of storing:
{
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9".."
}
Save:
{
"refresh_token": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ..."
}
- The JWE token ensures that only the application with the decryption key can access the refresh token.
Secure storage of API keys
Many applications require API keys to access third-party services.
- If API keys are stored in plain text, they can be stolen and misused.
- Encrypting API keys with JWE ensures that they remain confidential.
Multi-tenant cloud applications
Isolate tenant data in cloud services
Cloud applications that serve multiple customers (multi-tenant environments) must ensure that one tenant’s data is not accessible to others.
- Encrypting tenant data with separate encryption keys using JWE ensures data isolation.
- Even if one tenant’s data is compromised, the other tenants remain secure.
Example: SaaS CRM application
- A Customer Relationship Management (CRM) system stores customer data.
- Each tenant’s data is encrypted with a unique key that uses JWE.
- Even if a competitor gains access to the database, they cannot decrypt another company’s data.
Ensuring compliance with security standards
Compliance with GDPR and HIPAA encryption requirements
Many regulations require encryption of sensitive data to protect user privacy.
- The GDPR (General Data Protection Regulation) requires the encryption of personal data.
- HIPAA (Health Insurance Portability and Accountability Act) requires the encryption of medical data.
- PCI DSS (Payment Card Industry Data Security Standard) requires the encryption of credit card data.
The use of JWE ensures compliance with these regulations by encrypting it:
- User data
- Payment transactions
- Medical data and prescriptions
Prevention of data breaches and fines
- Data breaches can result in hefty fines and legal action.
- Encrypting sensitive data with JWE reduces liability and increases security.
Protecting IoT and edge computing data
Encryption of sensor data in IoT devices
- IoT (Internet of Things) devices collect and transmit sensitive data.
- Encrypting IoT messages with JWE ensures secure communication.
Example: Smart home security
- A Smart Lock encrypts access logs with JWE before sending them to the cloud.
- Even if hackers intercept the data, they cannot read when the doors were opened or closed.
Securing edge computing networks
- Edge computing devices process data outside central cloud servers.
- Encrypting edge data with JWE ensures that it remains secure even if the devices are compromised.
Prevent man-in-the-middle (MITM) attacks
Encryption of sensitive data during transmission
- When data is sent over HTTP, WebSockets or mobile networks, attackers can intercept the communication.
- Encrypting the data with JWE ensures that even if it is intercepted, it cannot be read.
Example: Mobile banking app
- A banking app encrypts the transaction data with JWE before it is sent to the bank’s servers.
- Even if an attacker intercepts the request, the transaction data remains unreadable.
By implementing JWE in various use cases, companies can increase security, protect user privacy and meet legal and regulatory requirements.
JWE vs. JWS: When should you use both?
Understanding the difference between JWE and JWS
JSON Web Encryption (JWE) and JSON Web Signature (JWS) are both part of the JOSE (JavaScript Object Signing and Encryption) framework, but they serve different security purposes:
- JWS (JSON Web Signature) ensures integrity and authenticity by digitally signing the payload, but the content remains visible.
- JWE (JSON Web Encryption) ensures confidentiality by encrypting the payload so that it cannot be read without decryption.
The most important differences between JWE and JWS
Feature | JWE (JSON Web Encryption) | JWS (JSON Web Signature) |
---|---|---|
Purpose | Encrypts data for confidentiality | Signs data for integrity and authenticity |
Visibility of user data | Encrypted and unreadable | Plain text and readable |
Protection against manipulation | Yes (via encryption algorithms) | Yes (via digital signature) |
Purpose of use | Secure data transmission, storage of sensitive information | API authentication, verification of data integrity |
Token Structure | Five parts (header, encrypted key, IV, ciphertext, authentication tag) | Three parts (header, payload, signature) |
When is JWE used?
Protection of sensitive information
JWE should be used if the payload contains confidential data that must not be disclosed to unauthorized persons.
Example: Encrypting financial data
A financial service provider transfers customer data with JWE:
{
"account_number": "123456789",
"balance": "₹50,000"
}
- The encryption of this data ensures that only the authorized recipient can access it.
Securing data in public channels
JWE is useful when data is transmitted over public or untrusted networks and confidentiality is important.
Example: Secure communication via APIs
A Healthcare API transmits patient data with JWE to prevent data leakage.
Compliance with data protection regulations
If an application needs to comply with GDPR, HIPAA or PCI DSS, JWE helps to fulfill the encryption requirements.
When should you use JWS?
Ensuring data integrity
JWS is best suited for cases where data needs to be verifiable and tamper-proof but not hidden.
Example: API authentication
OAuth 2.0 access tokens use JWS to sign authentication data.
Example JWS token:
{
"alg": "RS256",
"type": "JWT"
}
.
{
"sub": "user123",
"exp": 1712600000
}
.
{ "signature".)
- Even if it is intercepted, the payload is visible, but cannot be modified without invalidating the signature.
Verification of the sender’s identity
When verifying the sender of a message, JWS can be used to confirm the authenticity of the data.
Example: Signed webhooks
- A webhook provider signs event payloads with JWS.
- The recipient verifies the signature before processing the event.
When should JWE and JWS be combined?
Encrypting and signing data for maximum security
Some applications require both encryption (JWE) and signing (JWS) to ensure
- Confidentiality (data is hidden).
- Integrity and authenticity (data is not falsified).
Example: Secure data exchange between authorities
A government agency transmits classified data with a nested JWE+JWS structure:
- Data is signed with JWS to verify its authenticity.
- The signed data is then encrypted with JWE to ensure confidentiality.
This ensures that:
- Unauthorized users cannot read the data (JWE encryption).
- recipients can verify that the data has not been tampered with (JWS signature).
The choice between JWE and JWS
scenario | use JWE | use JWS | use both (JWE + JWS) |
---|---|---|---|
Encrypt sensitive user data | Yes | No | Yes |
Securing API authentication tokens | No | Yes | Yes |
Protection of medical records | Yes | No | Yes |
Verify the identity of API calls No | Yes | Yes | Yes |
Transmission of financial transactions | Yes | No | Yes |
Knowing when to use JWE, JWS or both will help you ensure secure, efficient and compliant data processing in your applications.
Implementing JWE in applications
Selecting a JWE library
To implement JWE in an application, choosing the right encryption library is crucial. Popular libraries support JWE in different programming languages:
Python
- PyJWT
- jose (Python JOSE)
JavaScript (Node.js)
- jsonwebtoken
- node-jose
Java
- Nimbus JOSE+JWT
.NET (C#)
- Microsoft.IdentityModel.Tokens
The choice of a library depends on:
- Compatibility with your framework.
- Support of encryption algorithms (AES, RSA, ECDH-ES, etc.).
- Easy integration into existing authentication systems.
Generation of a JWE token
Steps for creating a JWE token
- Prepare the user data – The data to be encrypted.
- Choose an encryption algorithm – AES, RSA or ECDH-ES.
- Generate encryption keys – Public/private key pairs or shared secrets.
- Encrypt the payload – convert it into a JWE token.
Example: Generate JWE in Python
from jose import jwe import json
#Payload (data to be encrypted)
payload = json.dumps({"user_id": "12345", "email": "user@example.com"})
#Encryption key key = b "my_secret_key_32_bytes_long"
#Encrypt with AES_GCM encrypted_jwe = jwe.encrypt(payload, key, algorithm="A256GCM")
print(encrypted_jwe)
- The output is a JWE compact token containing the encrypted payload.
Decrypting a JWE token
Steps to decrypt JWE
- Retrieve the JWE token from the request or database.
- Use the correct decryption key to decrypt the payload.
- Extract the original data after decryption.
Example: Decrypting JWE in Python
decrypted_payload = jwe.decrypt(encrypted_jwe, key)
print(decrypted_payload)
- The output shows the original JSON data.
Use JWE for API authentication
Encryption of authentication tokens
- OAuth 2.0 access tokens can be encrypted with JWE for confidentiality.
- This prevents the disclosure of sensitive data such as user roles and authorizations.
Example: OAuth 2.0 with JWE
- The user logs in and the server issues an encrypted JWE access token.
- The client inserts the JWE token into API requests.
- The server decrypts the token to extract the authentication data.
Protection of refresh tokens
- Refresh tokens are often stored in databases or cookies.
- Encrypting them with JWE ensures that they cannot be stolen and reused.
Secure storage of JWE
Best practices for key management
- Use a secure key storage (e.g. AWS KMS, Azure Key Vault).
- Change encryption keys regularly to increase security.
- **Never write encryption keys in the source code.
Secure token storage
- Store short-lived JWE tokens in memory.
- Store long-lived JWE tokens in encrypted databases.
By following these implementation steps, applications can securely encrypt, transmit and store sensitive data with JWE.
Conclusion
JSON Web Encryption (JWE) provides a robust mechanism for securing sensitive data by ensuring confidentiality, integrity and protection against unauthorized access. By choosing the right encryption algorithms, implementing sound key management and enforcing strict security controls, developers can effectively protect their applications from potential threats.
While JWE is powerful on its own, it can be combined with JSON Web Signature (JWS) when both confidentiality and authenticity are required. Proper token expiration, secure transmission over HTTPS and continuous monitoring further enhance security.
As data privacy regulations become more stringent, proper implementation of JWE is essential for compliance with standards such as GDPR, HIPAA and PCI DSS. By adhering to best practices, organizations can ensure that their encrypted tokens remain secure, scalable and efficient in modern web applications.
