Broken Authentication in Nestjs with Bearer Tokens
Broken Authentication in Nestjs with Bearer Tokens — how this combination creates or exposes the vulnerability
Broken Authentication in a NestJS application using Bearer Tokens typically arises when token issuance, validation, or storage is implemented without adequate security controls. Because Bearer Tokens are transmitted in the Authorization header and accepted based on presence and signature validity, any weakness in how tokens are created, verified, or scoped can lead to authentication bypass or token compromise. Common implementation gaps include missing token revocation, weak signing keys, overly permissive CORS, and improper handling of token lifetimes.
NestJS does not enforce a specific authentication mechanism out of the box; developers integrate strategies via packages such as passport-jwt. If the JWT strategy is configured with a weak secret, accepts unsigned tokens in development, or does not validate token binding to a specific audience or issuer, an attacker can craft or reuse tokens to escalate privileges or impersonate other users. For example, a route guarded by an unverified JWT strategy may inadvertently allow unauthenticated access if the guard is misconfigured or omitted, enabling unauthenticated attackers to reach endpoints that should require a valid Bearer Token.
Another vector specific to Bearer Tokens in NestJS is insecure transport or storage on the client side. If tokens are stored in localStorage and the application lacks strict Content Security Policy and Secure, HttpOnly cookie alternatives, they become susceptible to cross-site scripting (XSS) theft. Even with HTTPS, missing strict transport security headers and lack of token binding can expose tokens to interception or replay. Additionally, if token expiration and refresh logic are not enforced, stolen tokens remain valid for extended periods, amplifying the impact of a compromised credential.
Authorization issues often coexist with authentication flaws. A token may be valid and accepted, but the authorization layer may fail to verify scope or resource ownership per request. For instance, an endpoint that retrieves user profiles might only check the presence of a token and the user ID in the payload, without confirming that the requesting user is allowed to view that specific profile. This can enable horizontal privilege escalation when an attacker modifies the subject (sub) claim in a otherwise valid token to access other users’ data.
Operational practices also contribute to risk. Using the same signing key across multiple environments, failing to rotate keys, and exposing token introspection endpoints without authentication can undermine an otherwise secure implementation. Inadequate logging and missing monitoring for repeated authentication failures reduce the ability to detect brute-force or credential-stuffing attacks early. Since middleBrick scans unauthenticated attack surfaces, it can identify endpoints that accept Bearer Tokens without proper authentication enforcement and highlight missing controls such as token binding, audience validation, and revocation support.
Real-world attack patterns align with these implementation concerns. For example, CVE-2022-23539-type issues involve JWT libraries accepting unsigned tokens when algorithm validation is misconfigured, allowing attackers to bypass signature verification. Similarly, missing rate limiting on token exchange endpoints can facilitate brute-force or credential stuffing attacks. By scanning your API endpoints, middleBrick can surface misconfigurations in how Bearer Tokens are accepted and validated, providing findings mapped to OWASP API Top 10 and related compliance frameworks to guide remediation.
Bearer Tokens-Specific Remediation in Nestjs — concrete code fixes
Remediation focuses on secure token generation, strict validation, proper audience and issuer checks, token binding where feasible, and defense-in-depth measures such as transport security and short lifetimes. The following examples illustrate a hardened approach using passport-jwt in NestJS.
1. Secure JWT Strategy Configuration
Configure the JWT strategy to reject unsigned tokens, enforce strong algorithms, and validate standard claims. Avoid accepting tokens with none algorithm and explicitly set audience and issuer.
// auth/jwt.strategy.ts
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { jwtConstants } from './jwt.constants';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: jwtConstants.secretOrPrivateKey,
algorithms: ['RS256'],
audience: 'https://api.yourdomain.com',
issuer: 'https://auth.yourdomain.com',
});
}
async validate(payload: any) {
// Ensure token is bound to a specific scope/role
if (!payload.scope || !payload.scope.includes('read:profile')) {
throw new UnauthorizedException('Insufficient scope');
}
return { userId: payload.sub, scope: payload.scope };
}
}
2. Strong Token Constants and Key Management
Use environment-managed keys and prefer asymmetric algorithms. Do not hardcode secrets and avoid debug endpoints that accept unsigned tokens.
// auth/jwt.constants.ts
export const jwtConstants = {
secretOrPrivateKey: process.env.JWT_PRIVATE_KEY || '',
publicKey: process.env.JWT_PUBLIC_KEY || '',
};
3. Enforce HTTPS and Security Headers
Ensure tokens are only transmitted over HTTPS and protected by transport security headers. Avoid storing tokens in localStorage in production; prefer short-lived access tokens with secure, HttpOnly cookies for web clients when applicable.
// main.ts
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors({
origin: 'https://app.yourdomain.com',
credentials: true,
});
app.useGlobalPipes(new ValidationPipe());
// Ensure production environment enforces secure headers at the infrastructure level
await app.listen(3000);
}
bootstrap();
4. Token Revocation and Short Lifetimes
Implement short access token lifetimes and a revocation mechanism, such as a denylist stored in a fast store. Use refresh tokens with strict rotation and binding to mitigate token replay.
// auth/auth.service.ts
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class AuthService {
constructor(private readonly jwtService: JwtService) {}
async generateTokens(payload: any) {
return {
accessToken: this.jwtService.sign(payload, {
secret: process.env.JWT_PRIVATE_KEY,
expiresIn: '15m',
algorithm: 'RS256',
}),
refreshToken: this.jwtService.sign(payload, {
secret: process.env.JWT_PRIVATE_KEY,
expiresIn: '7d',
algorithm: 'RS256',
}),
};
}
}
5. Rate Limiting and Monitoring
Apply rate limiting on token exchange and authentication endpoints. Monitor for repeated failures and anomalous token usage patterns to detect brute-force or credential-stuffing attacks.
// auth/auth.guard.ts example combining strategy and scope checks
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const requiredScope = this.reflector.get('scope', context.getHandler());
const request = context.switchToHttp().getRequest();
const user = request.user;
if (!user) return false;
if (requiredScope && !requiredScope.every(s => user.scope.includes(s))) {
return false;
}
return true;
}
}
By combining strict JWT validation, short lifetimes, proper audience/issuer checks, and infrastructure-level protections, you reduce the risk of Broken Authentication when using Bearer Tokens in NestJS. middleBrick can help identify endpoints where Bearer Token handling lacks required controls, offering findings aligned with OWASP API Top 10 and providing remediation guidance to strengthen your authentication posture.
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 |