15

के लिए रीफ्रेश टोकन का आदान-प्रदान करने में असमर्थ मेरी मशीन पर कुछ SSL issues के साथ संघर्ष करने के बाद, मैं अभी भी Google रूबी क्लाइंट एपीआई के माध्यम से किसी उपयोगकर्ता के ब्लॉगर खाते तक पहुंचने का प्रयास कर रहा हूं।रेल Google क्लाइंट एपीआई - एक्सेस टोकन

  • रेल 3.2.3
  • रूबी 1.9.3
  • OAuth2 (0.8.0)
  • omniauth (1.1.1)
  • omniauth-google-OAuth2: मैं निम्नलिखित का उपयोग कर रहा (0.1.13)
  • गूगल-api-ग्राहक (0.4.6)

मैं सफलतापूर्वक उपयोगकर्ताओं को प्रमाणित और गूगल एक के माध्यम से अपने ब्लॉग का उपयोग कर सकते प्रमाणीकरण के समय पीआई। जब कोई उपयोगकर्ता लॉग इन करता है, तो मैं Google से प्राप्त access_token और refresh_token स्टोर करता हूं। और access_token समाप्त होने तक सब कुछ बढ़िया काम करता है। मैं एक नई access_token के लिए refresh_token का आदान-प्रदान करने वाली कार्यक्षमता बनाने की कोशिश कर रहा हूं, लेकिन दीवारों के खिलाफ आ रहा हूं।

client = Google::APIClient.new 
    token_pair = auth.oauth_token # access_token and refresh_token received during authentication 

    # Load the access token if it's available 
    if token_pair 
    client.authorization.update_token!(token_pair.to_hash) 
    end    

    # Update access token if expired 
    if client.authorization.refresh_token && client.authorization.expired? 
    client.authorization.fetch_access_token! 
    end 

    blogger = client.discovered_api('blogger', 'v3') 
    result = client.execute(
     api_method: blogger.blogs.list_by_user, 
     parameters: {'userId' => "self", 'fields' => 'items(description,id,name,url)'}, 
     headers: {'Content-Type' => 'application/json'}) 

इस कोड को पूरी तरह से काम करता है, जबकि access_token मान्य है: एक उदाहरण के रूप client documentation का उपयोग करना, इस कोड को मैं उपयोग कर रहा हूँ है। जैसे ही यह समाप्त हो रहा है, हालांकि के रूप में, मैं 2 समस्याओं दिखाई दे रही है:

  1. हालांकि मैं जानता हूँ कि टोकन समाप्त हो रहा है (मैं डेटाबेस में expires_at मूल्य देख लिया है), client.authorization.expired? रिटर्न false - वहाँ एक अलग तरीका है मैं डेटाबेस में मान का उपयोग करने के अलावा टोकन की समाप्ति की जांच कर सकता हूं?
  2. जब मैं client.authorization.fetch_access_token! के निष्पादन को मजबूर करता हूं तो मुझे invalid_request त्रुटि मिलती है।

कोई मुझे पता है कि मैं ग्राहक एपीआई का उपयोग कर एक नया access_token के लिए एक refresh_token विनिमय कर सकते हैं तो कृपया कर सकते हैं? यहां तक ​​कि यदि आप जानते हैं कि इसे किसी अन्य भाषा में कैसे करना है, तो यह एक बड़ी मदद होगी क्योंकि मैं इसे रूबीफी की कोशिश कर सकता हूं। धन्यवाद!!

उत्तर

25

आप हो सकता है पहले से ही इस पाया है, लेकिन आप गूगल पर यहाँ पूरी प्रक्रिया के माध्यम पढ़ सकते हैं: https://developers.google.com/accounts/docs/OAuth2WebServer

omniauth-google-OAuth2 रणनीति पहले से ही access_type स्थापित करने का ख्याल रखता है और हो रही एक ताज़ा टोकन है तो approval_prompt बस grant_type साथ https://accounts.google.com/o/oauth2/token पर पोस्ट करने की बात = request_token

यहाँ मोटे तौर पर कोड मैं का उपयोग किया जाता है:

def refresh_token 
    data = { 
    :client_id => GOOGLE_KEY, 
    :client_secret => GOOGLE_SECRET, 
    :refresh_token => REFRESH_TOKEN, 
    :grant_type => "refresh_token" 
    } 
    @response = ActiveSupport::JSON.decode(RestClient.post "https://accounts.google.com/o/oauth2/token", data) 
    if @response["access_token"].present? 
    # Save your token 
    else 
    # No Token 
    end 
rescue RestClient::BadRequest => e 
    # Bad request 
rescue 
    # Something else bad happened 
end 
+0

brimil01, आप आदमी हैं !! मुझे यह भी नहीं पता कि यह क्यों काम करता है और HTTP कॉल करने के मेरे अन्य प्रयास क्यों नहीं थे, लेकिन मैं इसे 12 घंटों तक देख रहा हूं, इसलिए मैं कल इसे समझूंगा। आपका कोड पूरी तरह से काम करता है और आपने मुझे बड़े पैमाने पर सिर-बैंगिंग से बचा लिया है, बहुत सराहना की। – cerrina

+0

धन्यवाद। थोड़ी देर के लिए यह पता लगाने की कोशिश कर रहा था। –

+0

मुझे यह पोस्ट करने पर प्रतीत होता है: # "invalid_request"}, @response = # <नेट :: HTTPBadRequest 400 खराब अनुरोध readbody = true> , @headers = {"कैश-कंट्रोल" => ["नो-कैश, नो-स्टोर, अधिकतम आयु = 0, अवश्य-पुनरीक्षित"], "प्रगामा" => ["नो-कैश"], "समाप्त हो जाती है" => ["शुक्र, 01 जनवरी 1 99 0 00:00:00 जीएमटी"], "तिथि" => ["बुध, 27 मार्च 2013 08:50:48 जीएमटी"], "सामग्री-प्रकार" => ["आवेदन/जेसन "]," एक्स-कंटेंट-टाइप-ऑप्शन "=> [" नोस्निफ "]," एक्स-फ्रेम-विकल्प "=> [" सैमोरिजिन "]," एक्स-एक्सएसएस-प्रोटेक्शन "=> [" 1; मोड = ब्लॉक "]," सर्वर "=> [" जीएसई "]," कनेक्शन "=> [" करीबी "]}> ... –

16

चूंकि आप रूबी Google API क्लाइंट का उपयोग कर रहे हैं, इसलिए रीफ्रेश टोकन का आदान-प्रदान करने के लिए इसका उपयोग क्यों न करें? रुबी एपीआई आंतरिक रूप से वही चीज़ करता है, जो @ brimil01 ने अपने जवाब में कहा है।

इस प्रकार मैं एक नया एक्सेस टोकन के लिए अपने रीफ्रेश टोकन का आदान-प्रदान करने के लिए रूबी एपीआई का उपयोग करता हूं।

def self.exchange_refresh_token(refresh_token) 
    client = Google::APIClient.new 
    client.authorization.client_id = CLIENT_ID 
    client.authorization.client_secret = CLIENT_SECRET 
    client.authorization.grant_type = 'refresh_token' 
    client.authorization.refresh_token = refresh_token 

    client.authorization.fetch_access_token! 
    client.authorization 
end 

और this issue here के अनुसार, यह अगर पहुंच टोकन समाप्त हो गया है की जाँच करने के expired? विधि का उपयोग करने के लिए नहीं की सिफारिश की है।

असल में, समाप्त होने पर कॉल न करें? तरीका। अनिवार्य रूप से शून्य परिदृश्य हैं जहां यह एक अच्छा विचार है। यह आपको विश्वसनीय समाप्ति जानकारी नहीं देगा। यह वास्तविक समाप्ति टाइमस्टैंप की तुलना में अधिक संकेत है, और टोकन सर्वर कुछ समय-समय पर सैद्धांतिक, लेकिन महत्वपूर्ण, परिस्थितियों में किसी भी समय समाप्त होने वाले टोकन का सम्मान करने का निर्णय ले सकता है। यदि आपको अमान्य अनुदान त्रुटि मिलती है, तो हमेशा अपने एक्सेस टोकन को रीफ्रेश करें और एक बार फिर से प्रयास करें। अगर आपको अभी भी कोई त्रुटि मिल रही है, तो त्रुटि बढ़ाएं।

यहां मैं यही करता हूं।

# Retrieved stored credentials for the provided user email address. 
# 
# @param [String] email_address 
# User's email address. 
# @return [Signet::OAuth2::Client] 
# Stored OAuth 2.0 credentials if found, nil otherwise. 
def self.get_stored_credentials(email_address) 
    hash = Thread.current['google_access_token'] 
    return nil if hash.blank? 

    hash[email_address] 
end 

## 
# Store OAuth 2.0 credentials in the application's database. 
# 
# @param [String] user_id 
# User's ID. 
# @param [Signet::OAuth2::Client] credentials 
# OAuth 2.0 credentials to store. 
def self.store_credentials(email_address, credentials) 
    Thread.current['google_access_token'] ||= {} 
    Thread.current['google_access_token'][email_address] = credentials 
end 


def self.credentials_expired?(credentials) 
    client = Google::APIClient.new 
    client.authorization = credentials 
    oauth2 = client.discovered_api('oauth2', 'v2') 
    result = client.execute!(:api_method => oauth2.userinfo.get) 

    (result.status != 200) 
end 


# @return [Signet::OAuth2::Client] 
# OAuth 2.0 credentials containing an access and refresh token. 
def self.get_credentials 
    email_address = '' 

    # Check if a valid access_token is already available. 
    credentials = get_stored_credentials(email_address) 
    # If not available, exchange the refresh_token to obtain a new access_token. 

    if credentials.blank? 
    credentials = exchange_refresh_token(REFRESH_TOKEN) 
    store_credentials(email_address, credentials) 
    else 
    are_credentials_expired = credentials_expired?(credentials) 

    if are_credentials_expired 
     credentials = exchange_refresh_token(REFRESH_TOKEN) 
     store_credentials(email_address, credentials) 
    end 
    end 

    credentials 
end 
+1

' credentials_expired? 'में, ग्राहक को कॉल करें। निष्पादित करें 'को' execute! 'फ़ॉर्म का उपयोग नहीं करना चाहिए, क्योंकि यह अनधिकृत स्थिति के साथ' परिणाम 'को पॉप्युलेट करने की बजाय क्रेडेंशियल समाप्त होने पर अपवाद उठाएगा। – pauljm

0

मैंने इसे नीचे सरल कोड के साथ तय किया।

def refesh_auth_tooken(refresh_token) 
     client = Google::APIClient.new 
     puts "REFESH TOOKEN" 
     client.authorization = client_secrets 
     client.authorization.refresh_token = refresh_token 

     #puts YAML::dump(client.authorization) 

     client.authorization.fetch_access_token! 
     return client.authorization 

    end 
संबंधित मुद्दे