Broken Authentication in Strapi with Mongodb
Broken Authentication in Strapi with Mongodb — how this specific combination creates or exposes the vulnerability
Broken Authentication in Strapi when using Mongodb as the datastore often arises from misconfigured identity providers, weak session handling, or overly permissive query filters. Strapi’s default authentication mechanisms rely on correctly set up policies, roles, and permissions; if these are not explicitly enforced, an unauthenticated or low-privilege actor may escalate access.
Mongodb’s flexible schema and rich query language can inadvertently contribute to the issue if field-level permissions are not enforced. For example, if a Strapi controller queries the user collection using an unchecked request parameter (such as userId) and passes it directly into a Mongodb filter, an attacker may manipulate that parameter to access or modify other users’ documents via NoSQL injection or BOLA/IDOR patterns.
Consider a Strapi service that retrieves a user profile by ID without validating ownership or applying strict role-based access control:
// Strapi controller action (vulnerable example)
async findOne(ctx) {
const { id } = ctx.params;
// Directly using request param in a Mongodb query without authorization checks
const user = await strapi.db.query('plugin::users-permissions.user').findOne({ where: { id } });
ctx.body = user;
}
If the controller does not verify that the requesting user matches id or that the requester has appropriate roles, this enables BOLA/IDOR. An attacker can iterate through numeric or ObjectId values to access other accounts. Mongodb’s support for complex queries means that unless the application enforces ownership at the filter level (e.g., ensuring _id matches the authenticated subject), the data is exposed.
Additionally, weak session token handling or improper JWT validation can compound the risk. If tokens are not securely stored, lack proper expiration, or are accepted without signature verification, an attacker can hijack sessions. Strapi’s admin panel and API tokens must be protected with strong transport security and scoped permissions to reduce the attack surface.
Compliance frameworks such as OWASP API Top 10 (2023) A07:2021 – Identification and Authentication Failures highlight these risks. Regular security scans using tools that test authentication and authorization paths, including BOLA/IDOR checks, help detect these issues early.
Mongodb-Specific Remediation in Strapi — concrete code fixes
To secure authentication when using Mongodb in Strapi, enforce strict ownership checks, parameterized queries, and role-based access controls. Avoid passing raw request parameters directly into database queries. Instead, build filters that explicitly tie data access to the authenticated subject.
Secure controller example that ensures users can only access their own profile:
// Strapi controller action (secure example)
async findOne(ctx) {
const authenticatedUser = ctx.state.user; // From JWT or session
const { id } = ctx.params;
// Ensure the authenticated user can only query their own record
if (authenticatedUser.id.toString() !== id) {
ctx.throw(403, 'Access denied: insufficient permissions');
}
const user = await strapi.db.query('plugin::users-permissions.user').findOne({
where: { id: id, _id: authenticatedUser._id },
});
if (!user) {
ctx.throw(404, 'User not found');
}
ctx.body = user;
}
When using Mongodb ObjectIds, ensure type-safe comparisons and avoid string coercion vulnerabilities. Use Mongodb’s driver methods to construct filters that include both the requested ID and the authenticated subject’s identifier:
// Using Mongodb query with multiple conditions to enforce ownership
const ObjectId = require('mongodb').ObjectId;
async findSecureProfile(ctx) {
const userId = new ObjectId(ctx.state.user._id);
const requestedId = new ObjectId(ctx.params.id);
const profile = await strapi.db.query('plugin::users-permissions.user').findOne({
where: {
_id: userId,
// Additional constraints such as role or tenant can be added here
},
});
if (!profile || requestedId.toString() !== profile._id.toString()) {
ctx.throw(403, 'Forbidden: you can only access your own data');
}
ctx.body = profile;
}
Leverage Strapi policies to centralize authorization logic. A policy can verify JWT signatures, extract user roles, and attach the user to ctx.state.user, which controllers then rely on. This reduces duplication and ensures consistent enforcement across endpoints.
For API tokens or OAuth flows, rotate secrets regularly and scope tokens to least privilege. In Mongodb, prefer using native ObjectId types for identifiers rather than exposing integer IDs, and always validate and sanitize inputs to prevent injection or type confusion attacks.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |