@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add `bin/auth refresh` for debugging OAuth token refresh issues

Summary: Ref T2852. Provide a script for inspecting/debugging OAuth token refresh.

Test Plan: Ran `bin/auth refresh` with various arguments, saw token refreshes.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2852

Differential Revision: https://secure.phabricator.com/D6276

+161 -3
+1
scripts/setup/manage_auth.php
··· 16 16 17 17 $workflows = array( 18 18 new PhabricatorAuthManagementRecoverWorkflow(), 19 + new PhabricatorAuthManagementRefreshWorkflow(), 19 20 new PhabricatorAuthManagementLDAPWorkflow(), 20 21 new PhutilHelpArgumentWorkflow(), 21 22 );
+2
src/__phutil_library_map__.php
··· 836 836 'PhabricatorAuthLoginController' => 'applications/auth/controller/PhabricatorAuthLoginController.php', 837 837 'PhabricatorAuthManagementLDAPWorkflow' => 'applications/auth/management/PhabricatorAuthManagementLDAPWorkflow.php', 838 838 'PhabricatorAuthManagementRecoverWorkflow' => 'applications/auth/management/PhabricatorAuthManagementRecoverWorkflow.php', 839 + 'PhabricatorAuthManagementRefreshWorkflow' => 'applications/auth/management/PhabricatorAuthManagementRefreshWorkflow.php', 839 840 'PhabricatorAuthManagementWorkflow' => 'applications/auth/management/PhabricatorAuthManagementWorkflow.php', 840 841 'PhabricatorAuthNewController' => 'applications/auth/controller/config/PhabricatorAuthNewController.php', 841 842 'PhabricatorAuthOldOAuthRedirectController' => 'applications/auth/controller/PhabricatorAuthOldOAuthRedirectController.php', ··· 2712 2713 'PhabricatorAuthLoginController' => 'PhabricatorAuthController', 2713 2714 'PhabricatorAuthManagementLDAPWorkflow' => 'PhabricatorAuthManagementWorkflow', 2714 2715 'PhabricatorAuthManagementRecoverWorkflow' => 'PhabricatorAuthManagementWorkflow', 2716 + 'PhabricatorAuthManagementRefreshWorkflow' => 'PhabricatorAuthManagementWorkflow', 2715 2717 'PhabricatorAuthManagementWorkflow' => 'PhutilArgumentWorkflow', 2716 2718 'PhabricatorAuthNewController' => 'PhabricatorAuthProviderConfigController', 2717 2719 'PhabricatorAuthOldOAuthRedirectController' => 'PhabricatorAuthController',
+144
src/applications/auth/management/PhabricatorAuthManagementRefreshWorkflow.php
··· 1 + <?php 2 + 3 + final class PhabricatorAuthManagementRefreshWorkflow 4 + extends PhabricatorAuthManagementWorkflow { 5 + 6 + protected function didConstruct() { 7 + $this 8 + ->setName('refresh') 9 + ->setExamples('**refresh**') 10 + ->setSynopsis( 11 + pht( 12 + 'Refresh OAuth access tokens. This is primarily useful for '. 13 + 'development and debugging.')) 14 + ->setArguments( 15 + array( 16 + array( 17 + 'name' => 'user', 18 + 'param' => 'user', 19 + 'help' => 'Refresh tokens for a given user.', 20 + ), 21 + array( 22 + 'name' => 'type', 23 + 'param' => 'provider', 24 + 'help' => 'Refresh tokens for a given provider type.', 25 + ), 26 + array( 27 + 'name' => 'domain', 28 + 'param' => 'domain', 29 + 'help' => 'Refresh tokens for a given domain.', 30 + ), 31 + )); 32 + } 33 + 34 + public function execute(PhutilArgumentParser $args) { 35 + $console = PhutilConsole::getConsole(); 36 + $viewer = PhabricatorUser::getOmnipotentUser(); 37 + 38 + $query = id(new PhabricatorExternalAccountQuery()) 39 + ->setViewer($viewer); 40 + 41 + $username = $args->getArg('user'); 42 + if (strlen($username)) { 43 + $user = id(new PhabricatorPeopleQuery()) 44 + ->setViewer($viewer) 45 + ->withUsernames(array($username)) 46 + ->executeOne(); 47 + if ($user) { 48 + $query->withUserPHIDs(array($user->getPHID())); 49 + } else { 50 + throw new PhutilArgumentUsageException( 51 + pht('No such user "%s"!', $username)); 52 + } 53 + } 54 + 55 + 56 + $type = $args->getArg('type'); 57 + if (strlen($type)) { 58 + $query->withAccountTypes(array($type)); 59 + } 60 + 61 + $domain = $args->getArg('domain'); 62 + if (strlen($domain)) { 63 + $query->withAccountDomains(array($domain)); 64 + } 65 + 66 + $accounts = $query->execute(); 67 + 68 + if (!$accounts) { 69 + throw new PhutilArgumentUsageException( 70 + pht("No accounts match the arguments!")); 71 + } else { 72 + $console->writeOut( 73 + "%s\n", 74 + pht( 75 + "Found %s accounts to refresh.", 76 + new PhutilNumber(count($accounts)))); 77 + } 78 + 79 + $providers = PhabricatorAuthProvider::getAllEnabledProviders(); 80 + 81 + foreach ($accounts as $account) { 82 + $console->writeOut( 83 + "%s\n", 84 + pht( 85 + "Refreshing account #%d (%s/%s).", 86 + $account->getID(), 87 + $account->getAccountType(), 88 + $account->getAccountDomain())); 89 + 90 + $key = $account->getProviderKey(); 91 + if (empty($providers[$key])) { 92 + $console->writeOut( 93 + "> %s\n", 94 + pht("Skipping, provider is not enabled or does not exist.")); 95 + continue; 96 + } 97 + 98 + $provider = $providers[$key]; 99 + if (!($provider instanceof PhabricatorAuthProviderOAuth)) { 100 + $console->writeOut( 101 + "> %s\n", 102 + pht("Skipping, provider is not an OAuth provider.")); 103 + continue; 104 + } 105 + 106 + $adapter = $provider->getAdapter(); 107 + if (!$adapter->supportsTokenRefresh()) { 108 + $console->writeOut( 109 + "> %s\n", 110 + pht("Skipping, provider does not support token refresh.")); 111 + continue; 112 + } 113 + 114 + $refresh_token = $account->getProperty('oauth.token.refresh'); 115 + if (!$refresh_token) { 116 + $console->writeOut( 117 + "> %s\n", 118 + pht("Skipping, provider has no stored refresh token.")); 119 + continue; 120 + } 121 + 122 + $console->writeOut( 123 + "+ %s\n", 124 + pht( 125 + "Refreshing token, current token expires in %s seconds.", 126 + new PhutilNumber( 127 + $account->getProperty('oauth.token.access.expires') - time()))); 128 + 129 + $adapter->refreshAccessToken($refresh_token); 130 + 131 + $console->writeOut( 132 + "+ %s\n", 133 + pht( 134 + "Refreshed token, new token expires in %s seconds.", 135 + new PhutilNumber($adapter->getAccessTokenExpires() - time()))); 136 + 137 + } 138 + 139 + $console->writeOut("%s\n", pht("Done.")); 140 + 141 + return 0; 142 + } 143 + 144 + }
+13 -2
src/applications/auth/provider/PhabricatorAuthProviderOAuth.php
··· 284 284 protected function willSaveAccount(PhabricatorExternalAccount $account) { 285 285 parent::willSaveAccount($account); 286 286 287 - $oauth_token = $this->getAdapter()->getAccessToken(); 288 - $account->setProperty('oauth.token', $oauth_token); 287 + $adapter = $this->getAdapter(); 288 + 289 + $oauth_token = $adapter->getAccessToken(); 290 + $account->setProperty('oauth.token.access', $oauth_token); 291 + 292 + if ($adapter->supportsTokenRefresh()) { 293 + $refresh_token = $adapter->getRefreshToken(); 294 + $account->setProperty('oauth.token.refresh', $refresh_token); 295 + } else { 296 + $account->setProperty('oauth.token.refresh', null); 297 + } 289 298 299 + $expires = $adapter->getAccessTokenExpires(); 300 + $account->setProperty('oauth.token.access.expires', $expires); 290 301 } 291 302 292 303 }
+1 -1
src/applications/doorkeeper/bridge/DoorkeeperBridgeAsana.php
··· 35 35 // right now so this is currently moot. 36 36 $account = head($accounts); 37 37 38 - $token = $account->getProperty('oauth.token'); 38 + $token = $account->getProperty('oauth.token.access'); 39 39 if (!$token) { 40 40 return; 41 41 }