Nie otrzymujemy tokena odświeżającego Google OAuth

Chcę uzyskać token dostępu od Google. Google API mówi, że aby uzyskać token dostępu, wyślij kod i inne parametry do strony generującej token, a odpowiedzią będzie obiekt JSON w stylu:

{
"access_token" : "ya29.AHES6ZTtm7SuokEB-RGtbBty9IIlNiP9-eNMMQKtXdMP3sfjL1Fc",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "1/HKSmLFXzqP0leUihZp2xUt3-5wkU7Gmu2Os_eBnzw74"
}

Jednak nie otrzymuję tokena odświeżania. Odpowiedź w moim przypadku brzmi:

{
 "access_token" : "ya29.sddsdsdsdsds_h9v_nF0IR7XcwDK8XFB2EbvtxmgvB-4oZ8oU",
"token_type" : "Bearer",
"expires_in" : 3600
}
Author: m0meni, 2012-05-31

12 answers

refresh_token jest dostarczany tylko przy pierwszej autoryzacji od użytkownika. Kolejne autoryzacje, takie jak te, które wykonujesz podczas testowania integracji OAuth2, nie zwrócą ponownie refresh_token. :)

  1. przejdź do strony pokazującej aplikacje z dostępem do Twojego konta: https://myaccount.google.com/u/0/permissions .
  2. w menu aplikacje innych firm wybierz swoją aplikację.
  3. kliknij Usuń dostęp, a następnie kliknij Ok, aby potwierdzić
  4. Następna Prośba OAuth2 zwróci refresh_token.

Alternatywnie możesz dodać parametr zapytania prompt=consent do przekierowania OAuth (zobacz stronę Google OAuth 2.0 Dla aplikacji serwerowych).

Spowoduje to poproszenie użytkownika o ponowne autoryzowanie aplikacji i zawsze zwróci refresh_token.

 536
Author: Rich Sutton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-27 00:52:51

Aby otrzymać odświeżacz należy dodać zarówno approval_prompt=force jak i access_type="offline" Jeśli korzystasz z klienta java dostarczonego przez Google, będzie on wyglądał tak:

GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
            HTTP_TRANSPORT, JSON_FACTORY, getClientSecrets(), scopes)
            .build();

AuthorizationCodeRequestUrl authorizationUrl =
            flow.newAuthorizationUrl().setRedirectUri(callBackUrl)
                    .setApprovalPrompt("force")
                    .setAccessType("offline");
 50
Author: Gal Morad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-01 08:44:40

Szukałem długiej nocy i to robi sztuczkę:

Zmodyfikowany przykład użytkownika.php from admin-sdk

$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$authUrl = $client->createAuthUrl();
echo "<a class='login' href='" . $authUrl . "'>Connect Me!</a>";

Następnie otrzymasz kod na adres URL przekierowania i uwierzytelnianie z kodem i uzyskanie tokena odświeżania

$client()->authenticate($_GET['code']);
echo $client()->getRefreshToken();

Powinieneś go teraz przechowywać;)

When your accesskey times out just do

$client->refreshToken($theRefreshTokenYouHadStored);
 24
Author: Norbert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-06 13:03:08

To sprawiło mi pewne zamieszanie, więc pomyślałem, że podzielę się tym, czego nauczyłem się na własnej skórze:

Gdy żądasz dostępu za pomocą parametrów access_type=offline i approval_prompt=force powinieneś otrzymać zarówno token access , jak i token refresh . Token access wygasa wkrótce po jego otrzymaniu i będziesz musiał go odświeżyć.

Poprawnie złożyłeś żądanie uzyskania nowego tokena access i otrzymałeś odpowiedź, która ma Twój nowy token access . I był również zdezorientowany faktem, że nie dostałem nowego odświeżania tokena. Jednak tak ma być, ponieważ możesz używać tego samego tokena refresh w kółko.

Myślę, że niektóre z innych odpowiedzi zakładają, że z jakiegoś powodu chciałeś zdobyć nowy odśwież token i sugerujesz, że ponownie autoryzujesz użytkownika, ale w rzeczywistości nie musisz, ponieważ token odśwież będzie działał do odwołania przez użytkownika.

 12
Author: jeteon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-15 13:12:39

Odpowiedź Rich Suttona w końcu zadziałała dla mnie, po tym jak zdałem sobie sprawę, że dodanie access_type=offline odbywa się na Front end żądania klienta o kod autoryzacyjny, nie żądanie back end, które wymienia ten kod na access_token. Dodałem komentarz do jego odpowiedzi i ten link w Google aby uzyskać więcej informacji na temat odświeżania tokenów.

P. S. Jeśli używasz Satellizera, Oto jak dodać tę opcję do $authProvider.google w AngularJS .

 4
Author: Zack Morris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:54

Ustawienie tego spowoduje, że token odświeżania będzie wysyłany za każdym razem:

$client->setApprovalPrompt('force');

Przykład jest podany poniżej (php):

$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
$client->addScope("email");
$client->addScope("profile"); 
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
 2
Author: apadana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-06 22:00:43

Dla mnie próbowałem CalendarSampleServlet dostarczone przez Google. Po 1 godzinie kończy się access_key i pojawia się przekierowanie na stronę 401. Próbowałem wszystkich powyższych opcji, ale nie działały. W końcu po sprawdzeniu kodu źródłowego 'AbstractAuthorizationCodeServlet' , zauważyłem, że przekierowanie byłoby wyłączone, jeśli poświadczenia są obecne, ale najlepiej byłoby sprawdzić dla refresh token!=null. Dodałem poniższy kod do CalendarSampleServlet i zadziałało później. Wielka ulga po tylu godzinach frustracja . Dzięki Bogu.

if (credential.getRefreshToken() == null) {
    AuthorizationCodeRequestUrl authorizationUrl = authFlow.newAuthorizationUrl();
    authorizationUrl.setRedirectUri(getRedirectUri(req));
    onAuthorization(req, resp, authorizationUrl);
    credential = null;
}
 1
Author: Anoop Isaac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-11 16:23:38

Aby uzyskać refresh_token Musisz podać access_type=offline w adresie URL żądania OAuth. Kiedy użytkownik uwierzytelni się po raz pierwszy, otrzymasz z powrotem niezerowe refresh_token oraz access_token, które wygasa.

Jeśli masz sytuację, w której użytkownik może ponownie uwierzytelnić konto, dla którego masz już token uwierzytelniania (jak wspomina @SsjCosty powyżej), musisz odzyskać informacje z Google, na którym koncie jest token. Aby to zrobić, dodaj profile do swoich zakresów. Korzystanie z OAuth2 Ruby gem, Twoje ostatnie życzenie może wyglądać mniej więcej tak:

client = OAuth2::Client.new(
  ENV["GOOGLE_CLIENT_ID"],
  ENV["GOOGLE_CLIENT_SECRET"],
  authorize_url: "https://accounts.google.com/o/oauth2/auth",
  token_url: "https://accounts.google.com/o/oauth2/token"
)

# Configure authorization url
client.authorize_url(
  scope: "https://www.googleapis.com/auth/analytics.readonly profile",
  redirect_uri: callback_url,
  access_type: "offline",
  prompt: "select_account"
)

Uwaga zakres ma dwa wpisy rozdzielane spacjami, jeden dla dostępu tylko do odczytu do Google Analytics, a drugi jest po prostu profile, który jest standardem OpenID Connect.

Spowoduje to udostępnienie przez Google dodatkowego atrybutu o nazwie id_token w odpowiedzi get_token. Aby uzyskać informacje z id_token, sprawdź tę stronę w Dokumentach Google. Istnieje garść bibliotek udostępnionych przez Google, które poprawi i "odkoduje" to dla Ciebie(użyłem Ruby Google-id-token gem ). Po przetworzeniu parametr sub jest faktycznie unikalnym identyfikatorem konta Google.

Warto zauważyć, że jeśli zmienisz zakres, otrzymasz ponownie token odświeżania dla użytkowników, którzy już uwierzytelnili się z oryginalnym zakresem. Jest to przydatne, jeśli, powiedzmy, masz już kilku użytkowników i nie chcesz, aby wszyscy nieautoryzowali aplikacji w Google.

Oh, I jeszcze jeden finał uwaga: nie potrzebujesz prompt=select_account, ale jest to przydatne, jeśli masz sytuację, w której użytkownicy mogą chcieć uwierzytelnić się za pomocą więcej niż jednego konta Google (np. nie używasz tego do logowania / uwierzytelniania).

 1
Author: coreyward,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-21 16:52:52

Teraz google odrzucił te parametry w moim żądaniu(access_type, prompt)... : (i w ogóle nie ma przycisku "Odwołaj dostęp". Jestem frustrujący, ponieważ odzyskałem odświeżanie_token lol

UPDATE: Znalazłem tu odpowiedź: D można odzyskać token odświeżania za pomocą prośby https://developers.google.com/identity/protocols/OAuth2WebServer

Curl-H " Content-type:application / x-www-form-urlencoded" \ https://accounts.google.com/o/oauth2/revoke?token= {token}

Token może być tokenem dostępu lub tokenem odświeżania. Jeśli token jest tokenem dostępu i posiada odpowiedni token odświeżania, token odświeżania również zostanie odwołany.

Jeśli odwołanie zostało pomyślnie przetworzone, kod statusu odpowiedzi wynosi 200. W przypadku warunków błędu zwracany jest kod stanu 400 wraz z kodem błędu.

 0
Author: Tran Tien Duc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-08 04:47:25
    #!/usr/bin/env perl

    use strict;
    use warnings;
    use 5.010_000;
    use utf8;
    binmode STDOUT, ":encoding(utf8)";

    use Text::CSV_XS;
    use FindBin;
    use lib $FindBin::Bin . '/../lib';
    use Net::Google::Spreadsheets::V4;

    use Net::Google::DataAPI::Auth::OAuth2;

    use lib 'lib';
    use Term::Prompt;
    use Net::Google::DataAPI::Auth::OAuth2;
    use Net::Google::Spreadsheets;
    use Data::Printer ;


    my $oauth2 = Net::Google::DataAPI::Auth::OAuth2->new(
         client_id => $ENV{CLIENT_ID},
         client_secret => $ENV{CLIENT_SECRET},
         scope => ['https://www.googleapis.com/auth/spreadsheets'],
    );
    my $url = $oauth2->authorize_url();
    # system("open '$url'");
    print "go to the following url with your browser \n" ;
    print "$url\n" ;
    my $code = prompt('x', 'paste code: ', '', '');
    my $objToken = $oauth2->get_access_token($code);

    my $refresh_token = $objToken->refresh_token() ;

    print "my refresh token is : \n" ;
    # debug p($refresh_token ) ;
    p ( $objToken ) ;


    my $gs = Net::Google::Spreadsheets::V4->new(
            client_id      => $ENV{CLIENT_ID}
         , client_secret  => $ENV{CLIENT_SECRET}
         , refresh_token  => $refresh_token
         , spreadsheet_id => '1hGNULaWpYwtnMDDPPkZT73zLGDUgv5blwJtK7hAiVIU'
    );

    my($content, $res);

    my $title = 'My foobar sheet';

    my $sheet = $gs->get_sheet(title => $title);

    # create a sheet if does not exit
    unless ($sheet) {
         ($content, $res) = $gs->request(
              POST => ':batchUpdate',
              {
                    requests => [
                         {
                              addSheet => {
                                    properties => {
                                         title => $title,
                                         index => 0,
                                    },
                              },
                         },
                    ],
              },
         );

         $sheet = $content->{replies}[0]{addSheet};
    }

    my $sheet_prop = $sheet->{properties};

    # clear all cells
    $gs->clear_sheet(sheet_id => $sheet_prop->{sheetId});

    # import data
    my @requests = ();
    my $idx = 0;

    my @rows = (
         [qw(name age favorite)], # header
         [qw(tarou 31 curry)],
         [qw(jirou 18 gyoza)],
         [qw(saburou 27 ramen)],
    );

    for my $row (@rows) {
         push @requests, {
              pasteData => {
                    coordinate => {
                         sheetId     => $sheet_prop->{sheetId},
                         rowIndex    => $idx++,
                         columnIndex => 0,
                    },
                    data => $gs->to_csv(@$row),
                    type => 'PASTE_NORMAL',
                    delimiter => ',',
              },
         };
    }

    # format a header row
    push @requests, {
         repeatCell => {
              range => {
                    sheetId       => $sheet_prop->{sheetId},
                    startRowIndex => 0,
                    endRowIndex   => 1,
              },
              cell => {
                    userEnteredFormat => {
                         backgroundColor => {
                              red   => 0.0,
                              green => 0.0,
                              blue  => 0.0,
                         },
                         horizontalAlignment => 'CENTER',
                         textFormat => {
                              foregroundColor => {
                                    red   => 1.0,
                                    green => 1.0,
                                    blue  => 1.0
                              },
                              bold => \1,
                         },
                    },
              },
              fields => 'userEnteredFormat(backgroundColor,textFormat,horizontalAlignment)',
         },
    };

    ($content, $res) = $gs->request(
         POST => ':batchUpdate',
         {
              requests => \@requests,
         },
    );

    exit;

    #Google Sheets API, v4

    # Scopes
    # https://www.googleapis.com/auth/drive   View and manage the files in your Google D# # i# rive
    # https://www.googleapis.com/auth/drive.file View and manage Google Drive files and folders that you have opened or created with this app
    # https://www.googleapis.com/auth/drive.readonly   View the files in your Google Drive
    # https://www.googleapis.com/auth/spreadsheets  View and manage your spreadsheets in Google Drive
    # https://www.googleapis.com/auth/spreadsheets.readonly  View your Google Spreadsheets
 0
Author: Yordan Georgiev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-08 15:06:15

Korzystanie z dostępu offline i prompt: consent zadziałało dobrze dla mnie:

   auth2 = gapi.auth2.init({
                    client_id: '{cliend_id}' 
   });

   auth2.grantOfflineAccess({prompt:'consent'}).then(signInCallback); 
 0
Author: Carlos Eduardo Ki Lee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-18 13:55:10

Moje rozwiązanie było trochę dziwne..próbowałem wszystkich rozwiązań, które znalazłem w Internecie i nic. Zaskakująco to działało: usunąć poświadczenia.json, odśwież, ponownie podłącz aplikację do konta. Nowe referencje.plik json będzie miał token odświeżania. Zrób kopię zapasową tego pliku. Następnie używaj aplikacji do czasu ponownego wystąpienia błędu odświeżania tokena. Usunąćplik json, który teraz jest tylko z Komunikatem o błędzie (Ten hapenned w moim przypadku), a następnie wklej ci stary plik poświadczeń w folder, gotowe! To był 1 tydzień od ive zrobił to i nie miał więcej problemów.

 0
Author: Guilherme Canoa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-04 16:13:21