Enforcing Email Verification at the Middleware Layer (SOC2-14)
Enforcing Email Verification at the Middleware Layer (SOC2-14)
Release: v0.1.152
SOC 2 Control: SOC2-14
Affected file: src/middleware.ts
Background
The platform uses OAuth-only authentication, currently supporting Google and GitHub as identity providers. Both providers verify a user's email address as part of their own sign-in flow, which means email verification is implicitly handled upstream in the majority of cases.
However, a gap existed in the application's own middleware: access to the dashboard was granted to any request carrying a valid req.auth?.user session object. There was no programmatic assertion that session.user.emailVerified was non-null before the request was allowed through.
The Risk
Relying solely on OAuth provider behaviour creates a latent edge case:
- A custom or third-party OAuth provider added in future may not guarantee a verified email.
- Misconfigured provider settings could allow unverified accounts to receive a valid session token.
- The absence of an explicit guard means the application's security posture depends entirely on external provider contracts rather than its own enforced policy — which is inconsistent with SOC 2 access control requirements.
What Changed
An explicit email verification check has been added to src/middleware.ts. Before a request is allowed to proceed to any protected dashboard route, the middleware now asserts:
// src/middleware.ts (simplified)
if (!session?.user?.emailVerified) {
// Redirect to an appropriate error or sign-in page
return redirectToEmailVerificationRequired(req);
}
This check runs on every authenticated request, after the existing req.auth?.user existence check. Sessions where emailVerified is null or undefined are rejected and redirected before any application logic executes.
Behaviour for Existing Providers
| Provider | Email verified by provider? | Effect of new check |
|---|---|---|
| Yes — always | No change for end users | |
| GitHub | Yes — always | No change for end users |
| Custom | Not guaranteed | Unverified sessions blocked at middleware |
For users signing in through Google or GitHub, emailVerified is populated by NextAuth from the provider's token response. Those users will not notice any difference.
SOC 2 Alignment
This change directly addresses SOC2-14 under the SOC 2 framework, supporting the CC6.1 Logical and Physical Access Controls criterion. It ensures that access to the platform is restricted to identities whose email addresses have been positively verified, either by the OAuth provider or — as a safety net — confirmed absent and blocked by the application itself.
Recommendations for Operators
- If you integrate a custom OAuth provider, confirm that the provider returns an
email_verifiedclaim in its token or user-info response. NextAuth will map this tosession.user.emailVerified. - If your custom provider does not supply this claim, users will be blocked at the middleware. You will need to either configure the provider to include the claim or implement a custom email verification flow before session creation.
- Review your NextAuth provider configuration to ensure
emailVerifiedis correctly mapped from provider profile data.