ไม่ได้รับโทเค็นการรีเฟรชของ Google OAuth


270

ฉันต้องการรับโทเค็นการเข้าถึงจาก Google Google API บอกว่าจะได้รับโทเค็นการเข้าถึงส่งรหัสและพารามิเตอร์อื่น ๆ ไปยังหน้าการสร้างโทเค็นและการตอบสนองจะเป็นวัตถุ JSON เช่น:

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

อย่างไรก็ตามฉันไม่ได้รับโทเค็นการรีเฟรช การตอบสนองในกรณีของฉันคือ:

{
 "access_token" : "ya29.sddsdsdsdsds_h9v_nF0IR7XcwDK8XFB2EbvtxmgvB-4oZ8oU",
"token_type" : "Bearer",
"expires_in" : 3600
}

ฉันมีปัญหาที่คล้ายกัน ตรวจสอบคำตอบของฉันที่นี่
Arithran

คำตอบ:


675

refresh_tokenมีให้เฉพาะในการอนุมัติครั้งแรกจากผู้ใช้ การให้สิทธิ์ที่ตามมาเช่นชนิดที่คุณทำขณะทดสอบการรวม OAuth2 จะไม่ส่งคืนrefresh_tokenอีกครั้ง :)

  1. ไปที่หน้าแสดงปพลิเคชันที่มีการเข้าถึงบัญชีของคุณ: https://myaccount.google.com/u/0/permissions
  2. ใต้เมนูแอปของบุคคลที่สามเลือกแอปของคุณ
  3. คลิกลบการเข้าถึงจากนั้นคลิกตกลงเพื่อยืนยัน
  4. คำขอ OAuth2 ถัดไปที่คุณทำจะส่งคืนrefresh_token(โดยระบุว่ามีพารามิเตอร์การสืบค้น 'access_type = ออฟไลน์' ด้วย

หรือคุณสามารถเพิ่มพารามิเตอร์การสืบค้นprompt=consent&access_type=offlineลงในการเปลี่ยนเส้นทาง OAuth (ดูหน้าOAuth 2.0ของ Google สำหรับแอปพลิเคชันเว็บเซิร์ฟเวอร์ )

refresh_tokenซึ่งจะแจ้งให้ผู้ใช้ที่จะอนุญาตให้โปรแกรมประยุกต์อีกครั้งและมักจะกลับมาเป็น


20
สิ่งนี้ไม่ได้ผลสำหรับฉัน แต่การเพิ่มพารามิเตอร์ "access_type = ออฟไลน์" ดูเหมือนจะทำเคล็ดลับ: developers.google.com/accounts/docs/OAuth2WebServer#offline
Jesse

87
คุณจำเป็นต้องมีในทุกกรณีเมื่อคุณต้องการaccess_type=offline refresh_token
DanH

5
แต่ฉันจะรีเฟรชโทเค็นได้อย่างไรหลังจากหมดอายุในกรณีนี้
vivek_jonam

5
@vivek_jonam เก็บโทเค็นการรีเฟรชและวันหมดอายุ เมื่อหมดอายุคุณขอโทเค็นใหม่โดยใช้โทเค็นการรีเฟรช ดูที่นี่: developers.google.com/accounts/docs/OAuth2WebServer#refresh
gelviis

4
ฉันเข้าใจ$client->setAccessType('offline')แล้ว function setApprovalPrompt()ถูกส่งผ่านไปแล้วในforceตามค่าเริ่มต้น
moey

57

เพื่อให้ได้รับโทเค็นการรีเฟรชคุณต้องเพิ่มทั้งสองapproval_prompt=forceและaccess_type="offline" ถ้าคุณใช้จาวาไคลเอนต์จาก Google มันจะมีหน้าตาแบบนี้:

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

AuthorizationCodeRequestUrl authorizationUrl =
            flow.newAuthorizationUrl().setRedirectUri(callBackUrl)
                    .setApprovalPrompt("force")
                    .setAccessType("offline");

ในโหนด: var authUrl = oauth2Client.generateAuthUrl ({access_type: 'ออฟไลน์' ขอบเขต: SCOPES, Approval_prompt: 'แรง'});
Joris Mans

2
เป็นเรื่องที่น่ายินดีอย่างยิ่งที่ Google ไม่ได้ระบุสิ่งนี้ไว้ในเอกสารประกอบของพวกเขาหรืออย่างน้อยก็ไม่ได้อยู่ในเอกสาร php หรือ oath2 ที่ฉันได้จ้องมองมาเป็นเวลา 7 ชั่วโมง ทำไมในโลกนี้ไม่ได้เป็นตัวหนาขนาดใหญ่ในเอกสารของพวกเขา
Colin Rickels

ขอบคุณ! เอกสารที่นี่ ( github.com/googlesamples/apps-script-oauth2 ) ทำให้เข้าใจผิดมากเกี่ยวกับพารามิเตอร์นี้ เมื่อฉันเพิ่ม Approval_prompt = บังคับในที่สุดฉันก็ได้รับโทเค็นการรีเฟรช
Alex Zhevzhik

28

ฉันค้นหามาทั้งคืนและนี่เป็นการหลอกลวง:

แก้ไข user-example.php จาก admin-sdk

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

จากนั้นคุณจะได้รับรหัสที่ URL การเปลี่ยนเส้นทางและการตรวจสอบสิทธิ์ด้วยรหัสและรับโทเค็นการรีเฟรช

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

คุณควรเก็บมันตอนนี้;)

เมื่อ accesskey ของคุณหมดเวลาให้ทำ

$client->refreshToken($theRefreshTokenYouHadStored);

Perfect @Norbert นี่คือสิ่งที่ฉันต้องการ
Emmanuel

ขอบคุณ! คำตอบที่ถูกต้องสำหรับคำถามของฉัน @Norbert
varun teja-MVT

16

สิ่งนี้ทำให้ฉันสับสนดังนั้นฉันคิดว่าฉันจะแบ่งปันสิ่งที่ฉันได้เรียนรู้วิธีการที่ยาก:

เมื่อคุณร้องขอการเข้าถึงการใช้access_type=offlineและapproval_prompt=forceพารามิเตอร์ที่คุณควรจะได้รับทั้งการเข้าถึงโทเค็นและรีเฟรชโทเค็น เข้าถึงโทเค็นจะหมดอายุในเร็ว ๆ นี้หลังจากที่คุณได้รับมันและคุณจะต้องรีเฟรชมัน

คุณทำการร้องขอให้รับโทเค็นการเข้าถึงใหม่อย่างถูกต้องและได้รับการตอบสนองที่มีโทเค็นการเข้าถึงใหม่ของคุณ ฉันสับสนด้วยความจริงที่ว่าฉันไม่ได้รับโทเค็นการรีเฟรชใหม่ อย่างไรก็ตามนี่เป็นวิธีที่มีความหมายเนื่องจากคุณสามารถใช้โทเค็นการรีเฟรชเดียวกันซ้ำแล้วซ้ำอีก

ฉันคิดว่าคำตอบอื่น ๆ คิดว่าคุณต้องการรับโทเค็นการรีเฟรชใหม่ด้วยตัวเองด้วยเหตุผลบางอย่างและเป็นอย่างยิ่งว่าคุณอนุญาตผู้ใช้อีกครั้ง แต่ในความเป็นจริงคุณไม่จำเป็นต้องทำเพราะโทเค็นการรีเฟรชที่คุณมี ถูกเพิกถอนโดยผู้ใช้


1
ฉันมี CMS ที่ผู้ใช้หลายคนใช้บัญชี Google ที่แตกต่างกันเพื่อเชื่อมต่อกับ API การวิเคราะห์ อย่างไรก็ตามบางครั้งผู้ใช้หลายคนสามารถเชื่อมต่อโดยใช้บัญชี google ของ บริษัท เดียวกัน แต่แต่ละคนต้องการเข้าถึงบัญชี Analytics ที่แตกต่างกัน มีเพียงคนแรกเท่านั้นที่ได้รับโทเค็นการรีเฟรชในขณะที่คนอื่น ๆ ทั้งหมดไม่ต้องเชื่อมต่อใหม่ทุกชั่วโมง ไม่มีวิธีที่จะได้รับโทเค็นการรีเฟรช SAME สำหรับการตรวจสอบสิทธิ์ในภายหลังแทนที่จะเป็นแค่ access_token ที่หมดอายุภายในหนึ่งชั่วโมง?
SsjCosty

1
API ดูเหมือนจะสร้างโทเค็นการรีเฟรชเพียงครั้งเดียว โทเค็น "การแบ่งปัน" ใด ๆ จะต้องเกิดขึ้นในรหัสของคุณ คุณจะต้องระวังไม่ให้สิทธิ์การเข้าถึงใหม่แก่ผู้ใช้โดยไม่ได้ตั้งใจ วิธีง่ายๆในการทำเช่นนี้คือให้แอปพลิเคชันติดตาม โทเค็นการรีเฟรชและบัญชีที่เกี่ยวข้องในที่จัดเก็บข้อมูลของตนเอง (แยกต่างหาก 'ตาราง' ใน SQLese) จากนั้นเมื่อคุณต้องการได้รับโทเค็นการเข้าถึงใหม่คุณจะตรวจสอบและใช้โทเค็นทั่วไปที่อาจเกิดขึ้นจากที่นั่น ใช้วิธีการบางอย่างรหัสของคุณไม่จำเป็นต้องรู้ว่าใครได้รับโทเค็น
jeteon

1
ฉันไม่ทราบว่าฉันสามารถระบุโทเค็นการรีเฟรชใดที่ฉันควรเชื่อมโยงกับโทเค็นการเข้าถึงใหม่ที่ฉันเพิ่งได้รับ มีผู้ใช้หลายคนที่ทำการล็อกอินและสิ่งเดียวที่พวกเขามีเหมือนกันคือพวกเขาใช้บัญชี Google (อีเมล) เดียวกันเพื่อเชื่อมต่อกับ API แต่ Google ไม่ได้ส่ง ID ของบัญชีหรืออีเมลกลับมามันแค่ส่งโทเค็นกลับมา ดังนั้นผมจึงไม่ทราบวิธีการที่จะเชื่อมโยงผู้ใช้ CMS ที่แตกต่างกัน 2 ...
SsjCosty

ฉันได้อธิบายปัญหาของฉันอย่างครบถ้วนแล้วที่นี่: stackoverflow.com/questions/30217524/…
SsjCosty

oAuth2 refresh_token ของ Youtube แสดงเฉพาะเมื่อมีการบังคับใช้
Dmitry Polushkin

7

ในที่สุดคำตอบของ Rich Suttonก็ใช้งานได้สำหรับฉันหลังจากที่ฉันรู้ว่าการเพิ่มaccess_type=offlineจะทำในคำขอของลูกค้าส่วนหน้าสำหรับรหัสการอนุญาตไม่ใช่คำขอ back end ที่แลกเปลี่ยนรหัสนั้นสำหรับ access_token ฉันได้เพิ่มความคิดเห็นในคำตอบของเขาและลิงก์นี้ที่ Googleสำหรับข้อมูลเพิ่มเติมเกี่ยวกับโทเค็นการรีเฟรช

PS ถ้าคุณกำลังใช้ Satellizer, นี่คือวิธีการเพิ่มตัวเลือกนั้นไปยัง $ authProvider.google ใน AngularJS


รายละเอียดเล็ก ๆ น้อย ๆ แต่สำคัญมาก ช่วยฉันด้วย! ขอบคุณ :)
เด็กซ์เตอร์

@ZackMorris ดังนั้น .. คุณหมายความว่าฉันไม่สามารถรับ refresh_token จากแบ็กเอนด์โดยใช้โทเค็นการเข้าถึงหรือไม่
อีกแล้ว

@Nevermore คุณไม่สามารถรับ refresh_token จาก access_token ได้ หากคุณต้องการให้เซิร์ฟเวอร์ของคุณจัดการการรีเฟรชคุณจะต้องเก็บ refresh_token ในฐานข้อมูลของคุณเป็นครั้งแรก นอกจากนี้หากคุณกำลังทำโฟลว์ OAuth ของลูกค้าที่ส่วนหน้าผู้ใช้จะต้องส่ง refresh_token ไปที่แบ็คเอนด์หากพวกเขาต้องการให้เซิร์ฟเวอร์รีเฟรช
Zack Morris

4

เพื่อให้ได้สิ่งที่refresh_tokenคุณต้องการรวมaccess_type=offlineไว้ใน URL คำขอ OAuth เมื่อผู้ใช้รับรองความถูกต้องเป็นครั้งแรกคุณจะได้รับข้อมูลที่ไม่ใช่ศูนย์refresh_tokenรวมถึงการaccess_tokenหมดอายุ

หากคุณมีสถานการณ์ที่ผู้ใช้อาจตรวจสอบสิทธิ์บัญชีที่คุณมีโทเค็นการรับรองความถูกต้องอีกครั้งสำหรับ (เช่น @SsjCosty กล่าวถึงข้างต้น) คุณต้องรับข้อมูลกลับจาก Google ซึ่งเป็นชื่อโทเค็น เมื่อต้องการทำเช่นนั้นเพิ่มprofileในขอบเขตของคุณ การใช้อัญมณี OAuth2 Ruby คำขอสุดท้ายของคุณอาจมีลักษณะเช่นนี้:

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"
)

โปรดทราบว่าขอบเขตมีรายการที่คั่นด้วยช่องว่างสองรายการหนึ่งรายการสำหรับการเข้าถึง Google Analytics แบบอ่านอย่างเดียวและอีกรายการหนึ่งเป็นเพียงprofileมาตรฐานการเชื่อมต่อ OpenID

ซึ่งจะส่งผลให้ Google ให้แอตทริบิวต์เพิ่มเติมที่เรียกว่าid_tokenในการget_tokenตอบกลับ หากต้องการรับข้อมูลจาก id_token โปรดดูหน้านี้ใน Google เอกสาร มีห้องสมุดที่ Google จัดเตรียมไว้ให้จำนวนหนึ่งที่จะตรวจสอบและ“ ถอดรหัส” สิ่งนี้ให้คุณ (ฉันใช้ Ruby google-id-token gem ) เมื่อคุณแยกวิเคราะห์แล้วsubพารามิเตอร์จะเป็นรหัสบัญชี Google ที่ไม่ซ้ำใคร

ถ้าคุณเปลี่ยนขอบเขตคุณจะได้รับโทเค็นการรีเฟรชอีกครั้งสำหรับผู้ใช้ที่ได้รับการรับรองความถูกต้องกับขอบเขตดั้งเดิมแล้ว สิ่งนี้มีประโยชน์ถ้าพูดว่าคุณมีกลุ่มผู้ใช้อยู่แล้วและไม่ต้องการทำให้พวกเขาทั้งหมดยกเลิกการตรวจสอบแอปใน Google

โอ้และอีกหนึ่งโน้ตสุดท้าย: คุณทำไม่ได้ จำเป็น prompt=select_accountแต่มีประโยชน์ถ้าคุณมีสถานการณ์ที่ผู้ใช้ของคุณอาจต้องการตรวจสอบสิทธิ์ด้วยบัญชี Google มากกว่าหนึ่งบัญชี (เช่นคุณไม่ได้ใช้สิ่งนี้ในการลงชื่อเข้าใช้ / รับรองความถูกต้อง) .


ฉันคิดว่าส่วนเกี่ยวกับการระบุผู้ใช้โดยไม่ต้องจัดเก็บข้อมูลส่วนบุคคลใด ๆ เป็นกุญแจสำคัญ ขอบคุณที่ชี้ให้เห็นว่าฉันไม่เห็นการอ้างอิงใด ๆ ใน Google เอกสารเกี่ยวกับเรื่องนี้
Danielo515

3

1.วิธีรับ 'refresh_token'

การแก้ไข:ควรใช้ตัวเลือก access_type = 'ออฟไลน์' เมื่อสร้าง authURL แหล่งที่มา: การใช้ OAuth 2.0 สำหรับเว็บเซิร์ฟเวอร์แอปพลิเคชัน

2.แต่ถึงแม้จะมี 'access_type = ออฟไลน์' ฉันไม่ได้รับ 'refresh_token' ใช่ไหม

วิธีแก้ไข:โปรดทราบว่าคุณจะได้รับเฉพาะในคำขอแรกเท่านั้นดังนั้นหากคุณจัดเก็บไว้ที่ใดที่หนึ่งและมีข้อกำหนดที่จะเขียนทับสิ่งนี้ในรหัสของคุณเมื่อรับ access_token ใหม่หลังจากหมดอายุก่อนหน้านี้อย่าลืมเขียนทับค่านี้

จาก Google Auth Doc: (ค่านี้ = access_type)

ค่านี้สั่งให้เซิร์ฟเวอร์การอนุญาตของ Google ส่งคืนโทเค็นการรีเฟรชและโทเค็นการเข้าถึงในครั้งแรกที่แอปพลิเคชันของคุณแลกเปลี่ยนรหัสการอนุญาตสำหรับโทเค็น

ถ้าคุณต้องการ 'refresh_token' อีกครั้งแล้วคุณจะต้องลบการเข้าถึงสำหรับแอปของคุณโดยทำตามขั้นตอนที่เขียนในคำตอบที่อุดมไปด้วยของซัตตัน


2

การตั้งค่านี้จะทำให้โทเค็นการรีเฟรชถูกส่งทุกครั้ง:

$client->setApprovalPrompt('force');

ตัวอย่างได้รับด้านล่าง (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');

1

สำหรับฉันฉันได้ลองจากCalendarSampleServletGoogle หลังจาก 1 ชั่วโมงaccess_keyหมดเวลาและมีการเปลี่ยนเส้นทางไปยังหน้า 401 ฉันลองตัวเลือกทั้งหมดข้างต้น แต่ไม่ได้ผล ในที่สุดเมื่อตรวจสอบซอร์สโค้ดสำหรับ'AbstractAuthorizationCodeServlet'ฉันจะเห็นว่าการเปลี่ยนเส้นทางจะถูกปิดใช้งานหากมีข้อมูลรับรอง แต่ควรมีการตรวจสอบrefresh token!=nullอย่างสมบูรณ์ ฉันเพิ่มโค้ดด้านล่างลงไปCalendarSampleServletและมันทำงานหลังจากนั้น ความโล่งใจที่ยอดเยี่ยมหลังจากหลายชั่วโมงของความยุ่งยาก ขอบคุณพระเจ้า.

if (credential.getRefreshToken() == null) {
    AuthorizationCodeRequestUrl authorizationUrl = authFlow.newAuthorizationUrl();
    authorizationUrl.setRedirectUri(getRedirectUri(req));
    onAuthorization(req, resp, authorizationUrl);
    credential = null;
}

0

ตอนนี้ google ปฏิเสธพารามิเตอร์เหล่านั้นในคำขอของฉัน (access_type, prompt) ... :( และไม่มีปุ่ม "เพิกถอนการเข้าถึง" เลยฉันหงุดหงิดเพราะได้รับ refresh_token lol กลับมาแล้ว

อัปเดต: ฉันพบคำตอบที่นี่: D คุณสามารถรับโทเค็นการรีเฟรชโดยการร้องขอ https://developers.google.com/identity/protocols/OAuth2WebServer

curl -H "ประเภทเนื้อหา: แอปพลิเคชัน / x-www-form-urlencoded" \ https://accounts.google.com/o/oauth2/revoke?token= {token}

โทเค็นสามารถเป็นโทเค็นการเข้าถึงหรือโทเค็นการรีเฟรช หากโทเค็นเป็นโทเค็นการเข้าถึงและมีโทเค็นการรีเฟรชที่สอดคล้องกันโทเค็นการรีเฟรชจะถูกเพิกถอน

หากการเพิกถอนได้รับการประมวลผลเรียบร้อยแล้วรหัสสถานะของการตอบสนองคือ 200 สำหรับเงื่อนไขข้อผิดพลาดรหัสสถานะ 400 จะถูกส่งกลับพร้อมกับรหัสข้อผิดพลาด


0
    #!/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

การใช้การเข้าถึงและการแจ้งเตือนออฟไลน์: ความยินยอมทำงานได้ดีกับฉัน:

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

   auth2.grantOfflineAccess({prompt:'consent'}).then(signInCallback); 

0

ทางออกของฉันแปลกไปหน่อยฉันลองทุกวิธีที่ฉันพบบนอินเทอร์เน็ตและไม่มีอะไรเลย สิ่งนี้ทำงานได้อย่างน่าประหลาดใจ: ลบข้อมูลรับรอง json, รีเฟรช, vinculate แอปของคุณในบัญชีของคุณอีกครั้ง ไฟล์หนังสือรับรองใหม่ json จะมีโทเค็นการรีเฟรช สำรองไฟล์นี้ไว้ที่ใดที่หนึ่ง จากนั้นใช้แอปของคุณต่อไปจนกว่าข้อผิดพลาดโทเค็นการรีเฟรชจะกลับมาอีกครั้ง ลบไฟล์ crendetials.json ที่ตอนนี้มีเพียงข้อความแสดงข้อผิดพลาด (สิ่งนี้เกิดขึ้นในกรณีของฉัน) จากนั้นวางไฟล์ข้อมูลรับรองเก่าแก่คุณลงในโฟลเดอร์เสร็จแล้ว! เป็นเวลา 1 สัปดาห์แล้วที่ ive ทำสิ่งนี้และไม่มีปัญหาอีกต่อไป


0

ในการรับ refresh_token ใหม่ทุกครั้งในการตรวจสอบสิทธิ์ประเภทของข้อมูลรับรอง OAuth 2.0 ที่สร้างในแดชบอร์ดควรเป็น "อื่น ๆ " ควรใช้ตัวเลือก access_type = 'ออฟไลน์' เมื่อสร้าง authURL

เมื่อใช้ข้อมูลประจำตัวที่มีประเภท "เว็บแอปพลิเคชัน" จะไม่มีการรวมกันของตัวแปร prompt / Approval_prompt ที่ใช้งานได้ - คุณจะยังได้รับ refresh_token เฉพาะในคำขอแรกเท่านั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.