Consents Management
RESTHeartOverview
The Accounts plugin does not persist user consents (terms & conditions, privacy policy acceptance) out of the box.
If your application requires consent tracking — for example to comply with GDPR or local transparency requirements — you have two options:
-
With a JSON Schema configured on the users collection (recommended): additional body properties sent to
POST /auth/registerare carried into the user document before validation. Includeconsentsin the registration body and declare its format in the schema. No interceptor is needed. -
Without a JSON Schema: use a response interceptor (the
consentsSaverpattern below) to persist consents after registration.
See User Registration — JSON Schema validation for how to configure the schema.
|
Note
|
The OAuth flow does transport a |
|
Note
|
|
Implementing consent persistence (without schema)
When no JSON Schema is configured on the users collection, unmapped body fields are dropped by POST /auth/register. Use a response interceptor to persist consents after registration:
-
Intercepts successful
POST /auth/registerresponses (status201). -
Reads the
consentsobject from the request body. -
Persists it on the user document.
@RegisterPlugin(name = "consentsSaver",
description = "Persists user consents on registration",
interceptPoint = InterceptPoint.RESPONSE)
public class ConsentsSaver implements JsonInterceptor {
@Inject("mclient")
private MongoClient mclient;
@Override
public void handle(JsonRequest request, JsonResponse response) {
if (!"/auth/register".equals(request.getPath())
|| response.getStatusCode() != 201) {
return;
}
var consents = request.getContent().get("consents");
if (consents == null || !consents.isJsonObject()) {
return;
}
var email = request.getContent().get("email").getAsString();
var users = mclient.getDatabase("restheart")
.getCollection("users");
users.updateOne(
Filters.eq("email", email),
Updates.set("consents", Document.parse(
consents.toString())));
}
}
|
Note
|
The same pattern applies to |
Consent schema
There is no enforced schema for the consents field. A common approach:
{
"consents": {
"terms": { "accepted": true, "version": "1.0", "at": "2024-01-15T10:30:00Z", "ip": "203.0.113.42" },
"privacy": { "accepted": true, "version": "1.0", "at": "2024-01-15T10:30:00Z", "ip": "203.0.113.42" }
}
}
OAuth flow
When a user authenticates via OAuth, the frontend can signal that the user accepted consents before the redirect by passing consentsAccepted=true as a query parameter to GET /auth/oauth/authorize/{provider}.
This flag is stored in the OAuth state token and retrieved on callback. The default MembershipProvider implementation ignores it, but a custom implementation can use it to persist consents.
See Membership Providers for the activateViaOAuth(userId, consents) SPI contract and OAuth Social Login for the full flow.
Validating consent versions
If you need to enforce that users accept the latest version of your terms, implement a request interceptor that:
-
Runs before authentication on
PATCH /auth/activate. -
Reads the submitted consent versions from the request body.
-
Compares them against your configured policy versions.
-
Returns
409 Conflictif the versions are outdated.