Authenticators RESTHeart
Authenticators verify credentials passed by the client and build the Account.
An Authentication Mechanism can delegate the verification of credentials to an Authenticator. For example, the default configuration enables the basicAuthMechanism that uses by default the mongoRealmAuthenticator.
RESTHeart provides two implementations of Authenticator:
-
FileRealmAuthenticator that handle credentials in a configuration file
-
MongoRealmAuthenticator that handle credentials on a MongoDB collection.
Implementations
The Authenticator class must implement the org.restheart.plugins.security.Authenticator interface.
public interface Authenticator extends IdentityManager {
@Override
public Account verify(Account account);
@Override
public Account verify(String id, Credential credential);
@Override
public Account verify(Credential credential);
}
Registering
The Authenticator class must be annotated with @RegisterPlugin:
@RegisterPlugin(name="myAuthenticator",
description = "my custom authenticator")
public class MyAuthenticator implements Authenticator {
}
Configuration
The Authenticator can receive parameters from the configuration file using the @Inject("config") annotation:
@Inject("config")
private Map<String, Object> config;
@OnInit
public void init() throws ConfigurationException {
// get configuration arguments
int number = argValue(this.config, "number");
String string = argValue(this.config, "string");
}
The parameters are defined in the configuration using the name of the authenticator as defined by the @RegisterPlugins annotation:
myAuthenticator:
number: 10
string: a string
Attached Request Parameters (v9)
RESTHeart v9 enhances the MongoRealmAuthenticator to automatically transfer specified request parameters to account properties after successful authentication.
Problem and Solution
Interceptors running at BEFORE_AUTH can attach parameters to a request using request.attachParam(key, value). However, these parameters were not automatically carried over to the authenticated account properties, requiring manual handling.
The new attached-props configuration option solves this by automatically copying specified attached parameters to the account properties after successful authentication.
Configuration
Add the attached-props array to your mongoRealmAuthenticator configuration:
mongoRealmAuthenticator:
enabled: true
users-db: restheart
users-collection: users
attached-props:
- tenantId
- organizationId
- host
Behaviors
-
Only parameters listed in
attached-propsare copied to account properties -
Missing parameters are silently skipped (no errors)
-
Parameters are transferred after successful authentication
-
Fully backward compatible - existing configurations work without changes
Use Cases
1. Custom Attributes
Attach organizational metadata or user-specific data that should be accessible throughout the request lifecycle:
@RegisterPlugin(
name = "tenantExtractor",
description = "Extracts tenant ID from request",
interceptPoint = InterceptPoint.REQUEST_BEFORE_AUTH)
public class TenantExtractorInterceptor implements WildcardInterceptor {
@Override
public void handle(Request<?> request, Response<?> response) {
// Extract tenant from subdomain, header, or path
var tenantId = extractTenantId(request);
request.attachParam("tenantId", tenantId);
}
@Override
public boolean resolve(Request<?> request, Response<?> response) {
return true;
}
}
2. Dynamic Authorization
Use account properties in security predicates without additional database lookups:
permissions:
- role: user
predicate: equals(@user.tenantId, @request.tenantId)
mongo:
readFilter: |
{ "tenantId": "@user.tenantId" }
This ensures users can only access data from their own tenant.
3. Multi-Tenant Applications
Implement tenant isolation by attaching tenant identifiers:
// Interceptor extracts tenant from subdomain
var host = request.getHeader("Host");
var tenantId = host.split("\\.")[0]; // Extract subdomain
request.attachParam("tenantId", tenantId);
Configuration:
mongoRealmAuthenticator:
attached-props:
- tenantId
permissions:
- role: user
predicate: path-prefix('/data')
mongo:
readFilter: '{ "tenant": "@user.tenantId" }'
writeFilter: '{ "tenant": "@user.tenantId" }'
mergeRequest:
tenant: "@user.tenantId"
This automatically: - Filters queries to include only the user’s tenant data - Prevents writing to other tenants' data - Adds the tenant ID to all new documents
Complete Example
A complete multi-tenant setup:
Step 1: Interceptor attaches tenant ID
@RegisterPlugin(
name = "tenantExtractor",
interceptPoint = InterceptPoint.REQUEST_BEFORE_AUTH)
public class TenantExtractorInterceptor implements WildcardInterceptor {
@Override
public void handle(Request<?> request, Response<?> response) {
var subdomain = extractSubdomain(request.getHeader("Host"));
request.attachParam("tenantId", subdomain);
request.attachParam("organizationId", lookupOrgId(subdomain));
}
}
Step 2: Configuration transfers parameters
mongoRealmAuthenticator:
enabled: true
users-db: restheart
users-collection: users
attached-props:
- tenantId
- organizationId
Step 3: Authorization uses account properties
permissions:
- role: user
predicate: path-prefix('/api/data')
mongo:
readFilter: '{ "tenantId": "@user.tenantId" }'
writeFilter: '{ "tenantId": "@user.tenantId" }'
mergeRequest:
tenantId: "@user.tenantId"
organizationId: "@user.organizationId"
Now every authenticated request automatically: 1. Extracts tenant/organization from the request 2. Transfers them to the user’s account properties 3. Enforces tenant isolation in all MongoDB operations