Secure Your Data with MongoDB’s Client-Side Field Level Encryption in Spring Boot

Abhishek Ranjan
Javarevisited
Published in
4 min readJul 17, 2023
Photo by Markus Spiske on Unsplash

Howdy, developers! Let’s talk about protecting sensitive data in our applications. Today, we’re shining the spotlight on MongoDB’s Client-Side Field Level Encryption (CSFLE). It’s a handy feature for encrypting specific fields in your documents right on the client side, so you’re sending over encrypted data to your MongoDB server. This is a great way to ensure sensitive data is only readable at the application level.

In this tutorial, we’re going to build a simple Spring Boot application and use CSFLE to encrypt selected fields in our documents. Specifically, we’ll have a User document with a mix of Personally Identifiable Information (PII) and non-PII data, and we’ll make sure that only the PII gets encrypted. Sound exciting? Let’s dive in!

Setting Up the Environment

First off, you need a MongoDB instance. You can go with a local installation or MongoDB Atlas for a cloud-based solution. Next, we need to create a new Spring Boot project.

You can create a new project using the Spring Boot CLI:

$ spring init --dependencies=web,data-mongodb csfle-demo

This command will create a new project with Web and Spring Data MongoDB dependencies. Head into the project’s directory:

$ cd csfle-demo

Next, add the following dependencies to your pom.xml:

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.2.3</version>
</dependency>
</dependencies>

The mongodb-driver-sync dependency will enable us to perform client-side encryption.

Implementing Client-Side Field Level Encryption

First, we’ll define our User document:

public class User {
private ObjectId id;
private String firstName; // Non-PII
private String lastName; // Non-PII
private String email; // PII
private String ssn; // PII
// ...
}

Next, let’s configure our MongoDB client for CSFLE. We’ll have MongoDB automatically encrypt and decrypt fields in our User documents.

@Configuration
public class MongoConfig {
@Value("${spring.data.mongodb.uri}")
private String connectionString;
public MongoClient mongoClient() {
// Define the master key
String localMasterKeyHex = "C410F849F2213312EE0DF85FBB3772EE"; // This should be securely generated
byte[] localMasterKey = new byte[96];
new Random().nextBytes(localMasterKey);
String kmsProviders = "local";
Map<String, Map<String, Object>> kmsProvidersMap = new HashMap<>();
Map<String, Object> providerDetailsMap = new HashMap<>();
providerDetailsMap.put(kmsProviders, localMasterKeyHex.getBytes(StandardCharsets.UTF_8));
kmsProvidersMap.put("local", providerDetailsMap);
// Define the JSON Schema for automatic encryption
String schema = "{ " +
"\"bsonType\": \"object\", " +
"\"properties\": { " +
"\"email\": { " +
"\"encrypt\": { " +
"\"keyId\": [\"/keyAltName\"], " +
"\"bsonType\": \"string\", " +
"\"algorithm\": \"AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic\" " +
"} " +
"}, " +
"\"ssn\": { " +
"\"encrypt\": { " +
"\"keyId\": [\"/keyAltName\"], " +
"\"bsonType\": \"string\", " +
"\"algorithm\": \"AEAD_AES_256_CBC_HMAC_SHA_512-Random\" " +
"} " +
"} " +
"} " +
"}";
// Create the ClientEncryptionSettings
ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder()
.keyVaultMongoClientSettings(MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.build())
.keyVaultNamespace("encryption.__keyVault")
.kmsProviders(kmsProvidersMap)
.build();
// Create the ClientEncryption
ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings);
// Create the MongoClientSettings
MongoClientSettings clientSettings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.autoEncryptionSettings(AutoEncryptionSettings.builder()
.keyVaultNamespace("encryption.__keyVault")
.kmsProviders(kmsProvidersMap)
.schemaMap(new HashMap<String, BsonDocument>().put("myDatabase.myCollection", BsonDocument.parse(schema)))
.build())
.build();
return MongoClients.create(clientSettings);
}
}

The JSON Schema in the schema string specifies which fields should be encrypted and the type of encryption to use. In our case, email and ssn will be automatically encrypted with different algorithms for variety.

Now, let’s create a simple REST API to handle our User documents. We'll have two endpoints: one to insert a new User and another to retrieve a User by their ID.

@RestController
public class UserController {
@Autowired
private MongoClient mongoClient;
@PostMapping("/user")
public String insertUser(@RequestBody User user) {
// Get the users collection (or create it if it doesn't exist)
MongoCollection<Document> collection = mongoClient.getDatabase("myDatabase").getCollection("myCollection");
// Insert the new user
Document doc = new Document()
.append("firstName", user.getFirstName())
.append("lastName", user.getLastName())
.append("email", user.getEmail()) // This will be automatically encrypted
.append("ssn", user.getSsn()); // This will be automatically encrypted
collection.insertOne(doc);
return "User inserted with ID: " + doc.get("_id");
}
@GetMapping("/user/{id}")
public Document getUser(@PathVariable String id) {
// Get the users collection
MongoCollection<Document> collection = mongoClient.getDatabase("myDatabase").getCollection("myCollection");
// Retrieve the user
Document doc = collection.find(new Document("_id", new ObjectId(id))).first();
return doc;
}
}

And there you have it! We now have a simple Spring Boot application that uses MongoDB’s CSFLE to secure sensitive user data. Fields such as email and ssn are automatically encrypted before being stored in MongoDB and are decrypted when retrieved.

Please keep in mind that this is a simplified example, and real-world applications would require secure key generation and management.

Conclusion

MongoDB’s CSFLE is a fantastic tool for bolstering the security of sensitive data in your applications. It can help you meet regulatory requirements for data privacy and gives you fine-grained control over what data gets encrypted. When combined with Spring Boot, you can build secure, robust applications that are ready to handle sensitive data right out of the box. Keep experimenting, and remember to keep your data (and keys) safe!

🔗 Connect with me on LinkedIn!

I hope you found this article helpful! If you’re interested in learning more and staying up-to-date with my latest insights and articles, don’t hesitate to connect with me on LinkedIn.

Let’s grow our networks, engage in meaningful discussions, and share our experiences in the world of software development and beyond. Looking forward to connecting with you! 😊

Follow me on LinkedIn ➡️

--

--