mastra-ai/mastra · error

Google user is not in an allowed hosted domain

Error message

Google user is not in an allowed hosted domain

What it means

Google Workspace accounts carry an hd (hosted domain) claim. When the provider is configured with allowedDomains and/or hostedDomain, verifyIdToken enforces that the authenticated user's hosted domain is allowed via isHostedDomainAllowed. If the claim is absent or doesn't match the configured domains, the login is rejected — this is the library's Workspace domain restriction feature.

Source

Thrown at auth/google/src/auth-provider.ts:373

      issuer: GOOGLE_ISSUERS,
      audience: this.clientId,
    });

    if (nonce && payload.nonce !== nonce) {
      throw new Error('Invalid Google ID token nonce');
    }

    if (hasExpired(payload)) {
      throw new Error('Google ID token has expired');
    }

    const user = mapGoogleClaimsToUser(payload);
    if (!user.googleId) {
      throw new Error('Google ID token is missing subject');
    }

    if (!this.isHostedDomainAllowed(user.hostedDomain)) {
      throw new Error('Google user is not in an allowed hosted domain');
    }

    return user;
  }

  private isHostedDomainAllowed(hostedDomain: string | undefined): boolean {
    if (this.allowedDomains.length === 0) return true;
    const domain = normalizeDomain(hostedDomain);
    if (!domain) return false;
    return this.allowedDomains.includes(domain);
  }

  private extractBearerToken(request: Request): string | null {
    const authHeader = request.headers.get('Authorization');
    if (!authHeader) return null;
    const token = authHeader.replace(/^Bearer\s+/i, '').trim();
    return token || null;
  }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Log in with an account whose hd matches the configured allowedDomains/hostedDomain.
  2. Update GOOGLE_ALLOWED_DOMAINS or the hostedDomain option to include the correct domain(s) the org actually uses.
  3. If any Google account should be allowed, remove the allowedDomains/hostedDomain restriction.
  4. Remember the hd claim is only present for Workspace accounts; if you need to include such accounts, don't rely on hostedDomain matching alone.

Example fix

// before
GOOGLE_ALLOWED_DOMAINS=oldcompany.com

// after
GOOGLE_ALLOWED_DOMAINS=newcompany.com,oldcompany.com
Defensive patterns

Strategy: validation

Validate before calling

const { payload } = decodeJwt(token);
const hd = (payload as { hd?: string }).hd;
const allowed = ['yourcompany.com'];
if (allowed.length > 0 && (!hd || !allowed.includes(hd.toLowerCase()))) {
  // show an org-account-required message before calling verifyIdToken
}

Try / catch

try {
  const user = await provider.verifyIdToken(token, nonce);
} catch (err) {
  if (err instanceof Error && err.message === 'Google user is not in an allowed hosted domain') {
    return res.status(403).send('Please sign in with your organization Google Workspace account.');
  }
  throw err;
}

Prevention

When it happens

Trigger: verifyIdToken succeeds on signature/nonce/expiry/subject but the mapped user's hostedDomain is undefined or not in the allowedDomains/hostedDomain configured on the provider — e.g. a personal @gmail.com account, or an account from a different Workspace tenant.

Common situations: allowing only @yourcompany.com but a tester logs in with a personal Gmail account; hostedDomain configured too narrowly after a company rename/alias change; users whose Workspace account doesn't expose hd because the domain isn't a Workspace domain; mismatch between GOOGLE_ALLOWED_DOMAINS spelling and the actual hd claim (case/suffix).

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/ba8a187136fd42ce. Report an issue: GitHub.