{"record":{"id":"3c0267a47e9e5f9e","repo":"gitroomhq/postiz-app","slug":"insufficient-scope","errorCode":"insufficient_scope","errorMessage":"{\n  error: 'insufficient_scope',\n  error_description:\n    'This OAuth client is not authorized to access email claims',\n}","messagePattern":"\\{\n  error: 'insufficient_scope',\n  error_description:\n    'This OAuth client is not authorized to access email claims',\n\\}","errorType":"http","errorClass":"HttpException","httpStatus":403,"severity":"error","filePath":"libraries/nestjs-libraries/src/database/prisma/oauth/oauth.service.ts","lineNumber":370,"sourceCode":"\n    const token = extractBearerToken(authorization);\n    if (!token) {\n      throw new HttpException(\n        { error: 'invalid_token', error_description: 'Bearer token required' },\n        HttpStatus.UNAUTHORIZED\n      );\n    }\n\n    const authorizationRecord = await this.getOrgByOAuthToken(token);\n    if (!authorizationRecord) {\n      throw new HttpException(\n        { error: 'invalid_token', error_description: 'Token is invalid or revoked' },\n        HttpStatus.UNAUTHORIZED\n      );\n    }\n\n    if (authorizationRecord.oauthApp.clientId !== openAiOAuthClientId()) {\n      throw new HttpException(\n        {\n          error: 'insufficient_scope',\n          error_description:\n            'This OAuth client is not authorized to access email claims',\n        },\n        HttpStatus.FORBIDDEN\n      );\n    }\n\n    const { user } = authorizationRecord;\n    return {\n      sub: user.id,\n      email: user.email,\n      email_verified: user.activated,\n    };\n  }\n\n  async getApprovedApps(userId: string) {","sourceCodeStart":352,"sourceCodeEnd":388,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/libraries/nestjs-libraries/src/database/prisma/oauth/oauth.service.ts#L352-L388","documentation":"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.","triggerScenarios":"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.","commonSituations":"Building a custom OAuth integration and assuming /userinfo email access; misconfigured env var pointing at the wrong client id on a self-hosted deployment.","solutions":["Only call userinfo for email claims with the designated OpenAI OAuth client's tokens","Verify OPENAI_OAUTH_CLIENT_ID matches the clientId of the app that issued the token","For other clients, obtain user identity through the normal Postiz API/organization endpoints instead"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (app.clientId !== configuredOpenAiClientId) {\n  throw new Error('email claims unavailable for this client');\n}","typeGuard":"const clientAllowedForEmailClaims = (clientId: string, allowed: string): boolean => clientId === allowed;","tryCatchPattern":"try { return await getUserInfo(auth); } catch (e) { if (e?.response?.data?.error === 'insufficient_scope') return null; throw e; }","preventionTips":["Only the designated integration client should call userinfo for email claims","Keep OPENAI_OAUTH_CLIENT_ID env in sync with the issuing app"],"tags":["oidc","insufficient-scope","userinfo","authorization"],"backgroundTag":"oauth-insufficient-scope","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}