{"record":{"id":"94070ee86c46f342","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-state","errorCode":"error-invalid-state","errorMessage":"Invalid state provided","messagePattern":"Invalid state provided","errorType":"error_code","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/cloud/finishOAuthAuthorization.ts","lineNumber":15,"sourceCode":"import { Users } from '@rocket.chat/models';\nimport { serverFetch as fetch } from '@rocket.chat/server-fetch';\nimport { Meteor } from 'meteor/meteor';\n\nimport { getRedirectUri } from './getRedirectUri';\nimport { userScopes } from './oauthScopes';\nimport { assertNotOfflineLicense } from './offlineLicense';\nimport { settings } from '../../settings';\nimport { SystemLogger } from '../logger/system';\n\nexport async function finishOAuthAuthorization(code: string, state: string) {\n\tassertNotOfflineLicense();\n\n\tif (settings.get<string>('Cloud_Workspace_Registration_State') !== state) {\n\t\tthrow new Meteor.Error('error-invalid-state', 'Invalid state provided', {\n\t\t\tmethod: 'cloud:finishOAuthAuthorization',\n\t\t});\n\t}\n\n\tconst clientId = settings.get<string>('Cloud_Workspace_Client_Id');\n\tconst clientSecret = settings.get<string>('Cloud_Workspace_Client_Secret');\n\n\tconst scope = userScopes.join(' ');\n\n\tlet payload;\n\ttry {\n\t\tconst cloudUrl = settings.get<string>('Cloud_Url');\n\t\tconst response = await fetch(`${cloudUrl}/api/oauth/token`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { 'Content-Type': 'application/x-www-form-urlencoded' },\n\t\t\tparams: new URLSearchParams({\n\t\t\t\tclient_id: clientId,\n\t\t\t\tclient_secret: clientSecret,","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/cloud/finishOAuthAuthorization.ts#L1-L33","documentation":"finishOAuthAuthorization is the last leg of the cloud OAuth flow. It compares the returned state parameter against the Cloud_Workspace_Registration_State setting stored when the flow started; a mismatch throws Meteor.Error 'error-invalid-state' — the standard OAuth CSRF state check failing for cloud registration.","triggerScenarios":"The cloud:finishOAuthAuthorization callback arrives with a state from an earlier or different registration flow: a second admin started a new flow (overwriting the setting), the callback URL was replayed, or the setting was reset mid-flow.","commonSituations":"Two people (or two tabs) running workspace registration simultaneously; a stale browser tab completing an old OAuth redirect; reusing an old callback link after a failed attempt.","solutions":["Restart the cloud registration from the Setup Wizard / Admin > Cloud so a fresh state is generated end-to-end.","Ensure only one registration flow runs at a time on the workspace.","Never bookmark or replay the OAuth callback URL."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await Meteor.callAsync('cloud:finishOAuthAuthorization', code, state);\n} catch (e) {\n  if (e instanceof Meteor.Error && e.error === 'error-invalid-state') {\n    // flow state stale/overwritten: restart registration from Admin > Cloud to mint a new state\n  }\n  throw e;\n}","preventionTips":["Run only one cloud registration flow at a time per workspace (lock the wizard while active).","Never reload or bookmark OAuth callback URLs.","On any registration failure, restart the whole flow rather than retrying the callback step."],"tags":["oauth","csrf-state","state-mismatch","cloud","rocket-chat"],"backgroundTag":"oauth-state-mismatch","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}