{"record":{"id":"ffaa35be2a36f363","repo":"medusajs/medusa","slug":"the-identity-provider-did-not-return-an-id-token","errorCode":null,"errorMessage":"The identity provider did not return an ID token; ensure the 'openid' scope is requested","messagePattern":"The identity provider did not return an ID token; ensure the 'openid' scope is requested","errorType":"exception","errorClass":"MedusaError","httpStatus":401,"severity":"error","filePath":"packages/modules/providers/auth-oidc/src/engine/engine.ts","lineNumber":178,"sourceCode":"      // Forward every authorization-response parameter so\n      // openid-client can enforce all applicable checks. The `checks` argument\n      // carries the values we stored ourselves (PKCE verifier, nonce, state).\n      tokenSet = await client.callback(redirectUri, params, {\n        code_verifier: input.codeVerifier,\n        nonce: input.nonce,\n        state: input.state,\n      })\n    } catch (error) {\n      throw new MedusaError(\n        MedusaError.Types.UNAUTHORIZED,\n        `Could not validate the identity provider's response: ${error.message}`\n      )\n    }\n\n    // Without the `openid` scope, the token endpoint returns no ID token and\n    // `tokenSet.claims()` would throw an unhelpful TypeError.\n    if (!tokenSet.id_token) {\n      throw new MedusaError(\n        MedusaError.Types.UNAUTHORIZED,\n        \"The identity provider did not return an ID token; ensure the 'openid' scope is requested\"\n      )\n    }\n\n    const claims = tokenSet.claims()\n\n    return {\n      claims: { ...claims },\n      tokens: {\n        id_token: tokenSet.id_token,\n        access_token: tokenSet.access_token,\n        refresh_token: tokenSet.refresh_token,\n        expires_at: tokenSet.expires_at,\n        token_type: tokenSet.token_type,\n        scope: tokenSet.scope,\n      },\n    }","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/modules/providers/auth-oidc/src/engine/engine.ts#L160-L196","documentation":"After a successful token exchange, the engine requires an ID token (tokenSet.id_token) to extract claims. Without the openid scope the provider returns only access/refresh tokens and claims() would throw an unhelpful TypeError, so the engine fails fast with UNAUTHORIZED and an explicit hint.","triggerScenarios":"The provider was configured with a scope list that omits 'openid' (e.g. only 'email profile'), or the IdP app registration does not expose the openid scope, so the token endpoint returns no id_token.","commonSituations":"A custom scope string like \"profile email\" in medusa-config.js; using a non-OIDC OAuth2 provider (plain OAuth has no ID tokens); the IdP admin toggled off OpenID Connect for the client.","solutions":["Add 'openid' to the authentication scope configuration for the provider (e.g. scope: \"openid email profile\").","Verify in the IdP console that the client is allowed to request the openid scope.","If the provider is plain OAuth2 (no ID tokens), it cannot be used with this OIDC engine — use a dedicated OAuth2 strategy."],"exampleFix":"// before\noptions: { issuer: \"...\", client_id: \"...\", callback_url: \"...\", scope: \"email profile\" }\n// after\noptions: { issuer: \"...\", client_id: \"...\", callback_url: \"...\", scope: \"openid email profile\" }","handlingStrategy":"validation","validationCode":"const scopes = (options.scope ?? \"openid\").split(\" \")\nif (!scopes.includes(\"openid\")) {\n  throw new Error(\"OIDC scope must include 'openid' to receive an ID token\")\n}","typeGuard":"const requestsOpenidScope = (scope?: string): boolean =>\n  (scope ?? \"openid\").split(/\\s+/).includes(\"openid\")","tryCatchPattern":"try { await engine.exchangeCode(input) } catch (e) { if (e instanceof MedusaError && /'openid' scope/.test(e.message)) { /* fix scope config, then restart flow */ } throw e }","preventionTips":["Default scope strings should always start with 'openid'.","Only use OIDC-capable providers with this engine.","Add a startup assertion on the configured scope."],"tags":["oidc","openid-scope","id-token","configuration"],"backgroundTag":"oidc-missing-id-token","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}