{"record":{"id":"ce7d808aa53d84fa","repo":"phacility/phabricator","slug":"unable-to-load-your-oauth1-token-secret-from-stora","errorCode":null,"errorMessage":"Unable to load your OAuth1 token secret from storage. It may have expired. Try authenticating again.","messagePattern":"Unable to load your OAuth1 token secret from storage\\. It may have expired\\. Try authenticating again\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/auth/provider/PhabricatorOAuth1AuthProvider.php","lineNumber":257,"sourceCode":"      ->setTokenExpires(time() + phutil_units('1 hour in seconds'))\n      ->setTokenCode($secret)\n      ->save();\n  }\n\n  private function loadHandshakeTokenSecret($client_code) {\n    $secret_type = PhabricatorOAuth1SecretTemporaryTokenType::TOKENTYPE;\n    $key = $this->getHandshakeTokenKeyFromClientCode($client_code);\n    $type = $this->getTemporaryTokenType($secret_type);\n\n    $token = id(new PhabricatorAuthTemporaryTokenQuery())\n      ->setViewer(PhabricatorUser::getOmnipotentUser())\n      ->withTokenResources(array($key))\n      ->withTokenTypes(array($type))\n      ->withExpired(false)\n      ->executeOne();\n\n    if (!$token) {\n      throw new Exception(\n        pht(\n          'Unable to load your OAuth1 token secret from storage. It may '.\n          'have expired. Try authenticating again.'));\n    }\n\n    return $token->getTokenCode();\n  }\n\n  private function getTemporaryTokenType($core_type) {\n    // Namespace the type so that multiple providers don't step on each\n    // others' toes if a user starts Mediawiki and Bitbucket auth at the\n    // same time.\n\n    // TODO: This isn't really a proper use of the table and should get\n    // cleaned up some day: the type should be constant.\n\n    return $core_type.':'.$this->getProviderConfig()->getID();\n  }","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/auth/provider/PhabricatorOAuth1AuthProvider.php#L239-L275","documentation":"During the OAuth1 callback, Phabricator loads the temporary token row in which it stored the request-token secret at handshake start (PhabricatorAuthTemporaryToken of type PhabricatorOAuth1SecretTemporaryTokenType, looked up with withTokenResources/withTokenTypes/withExpired(false) under the omnipotent user). If executeOne() returns nothing, the secret is gone and the handshake is unrecoverable, so Phabricator throws and tells the user to authenticate again.","triggerScenarios":"The temporary token expired between handshake start and provider callback (user sat on the provider's authorize page too long), the token was already consumed by a completed attempt, or the token row was purged/deleted before the callback arrived.","commonSituations":"A user leaves the authorization screen open for a long time before approving; the user completes login in a different browser or after clearing state; two parallel login attempts for the same provider racing each other.","solutions":["Go back to Phabricator and start authentication again - a fresh handshake stores a new token secret (this is the fix the message itself prescribes)","If it recurs constantly, check the auth temporary-token TTL and garbage collection settings for the install","Ensure only one login handshake per provider is open at a time (close extra tabs on the provider's authorize page)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  $adapter->setTokenSecret($this->loadHandshakeTokenSecret($client_code));\n} catch (Exception $ex) {\n  // Token secret expired: only sane recovery is a fresh handshake.\n  throw new PhutilAuthUserAbortedException(); // bounces user to login start\n}","preventionTips":["Complete the authorize step promptly after starting OAuth1 login - temporary tokens have a TTL","Keep one handshake window per provider; close stale authorize pages before starting again","Complete the callback in the same browser session the handshake started in"],"tags":["oauth1","phabricator","temporary-token","expired","authentication"],"backgroundTag":"oauth-token-expired","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}