Edit Page

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:

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-props are 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