gitroomhq/postiz-app · error · HttpException

insufficient_scope

insufficient_scope

Error message

{
  error: 'insufficient_scope',
  error_description:
    'This OAuth client is not authorized to access email claims',
}

What it means

Returned as HTTP 403 insufficient_scope from getUserInfo when the token's associated OAuth app clientId is not the configured OpenAI OAuth client id. Email claims on this endpoint are restricted to the specific whitelisted integration client.

Source

Thrown at libraries/nestjs-libraries/src/database/prisma/oauth/oauth.service.ts:370

    const token = extractBearerToken(authorization);
    if (!token) {
      throw new HttpException(
        { error: 'invalid_token', error_description: 'Bearer token required' },
        HttpStatus.UNAUTHORIZED
      );
    }

    const authorizationRecord = await this.getOrgByOAuthToken(token);
    if (!authorizationRecord) {
      throw new HttpException(
        { error: 'invalid_token', error_description: 'Token is invalid or revoked' },
        HttpStatus.UNAUTHORIZED
      );
    }

    if (authorizationRecord.oauthApp.clientId !== openAiOAuthClientId()) {
      throw new HttpException(
        {
          error: 'insufficient_scope',
          error_description:
            'This OAuth client is not authorized to access email claims',
        },
        HttpStatus.FORBIDDEN
      );
    }

    const { user } = authorizationRecord;
    return {
      sub: user.id,
      email: user.email,
      email_verified: user.activated,
    };
  }

  async getApprovedApps(userId: string) {

View on GitHub (pinned to 0f1647f749)

Solutions

  1. Only call userinfo for email claims with the designated OpenAI OAuth client's tokens
  2. Verify OPENAI_OAUTH_CLIENT_ID matches the clientId of the app that issued the token
  3. For other clients, obtain user identity through the normal Postiz API/organization endpoints instead
Defensive patterns

Strategy: validation

Validate before calling

if (app.clientId !== configuredOpenAiClientId) {
  throw new Error('email claims unavailable for this client');
}

Type guard

const clientAllowedForEmailClaims = (clientId: string, allowed: string): boolean => clientId === allowed;

Try / catch

try { return await getUserInfo(auth); } catch (e) { if (e?.response?.data?.error === 'insufficient_scope') return null; throw e; }

Prevention

When it happens

Trigger: Exchanging tokens with your own registered OAuth client and then calling userinfo expecting email claims; OPENAI_OAUTH_CLIENT_ID env changed so a previously valid client no longer matches; using a dynamically registered client other than the designated one.

Common situations: Building a custom OAuth integration and assuming /userinfo email access; misconfigured env var pointing at the wrong client id on a self-hosted deployment.

Related errors


AI-assisted analysis of gitroomhq/postiz-app@0f1647f749 (2026-08-27). Data as JSON: /api/errors/3c0267a47e9e5f9e. Report an issue: GitHub.