Rails Google Client API-nie można wymienić tokena odświeżania na token dostępu
Po zmaganiu się z pewnymi problemami SSL na moim komputerze, nadal próbuję uzyskać dostęp do konta Bloggera Użytkownika za pośrednictwem interfejsu API klienta Google Ruby. Używam:
- Rails 3.2.3
- Ruby 1.9.3
- oauth2 (0.8.0)
- omniauth (1.1.1)
- omniauth-google-OAuth2 (0.1.13) [[19]} google-api-client (0.4.6)
Mogę skutecznie uwierzytelniać użytkowników i uzyskiwać dostęp do ich blogów za pośrednictwem Google API w tym czasie uwierzytelniania. Kiedy użytkownik się loguje, przechowuję access_token
i refresh_token
, które otrzymuję od Google. i wszystko działa świetnie, dopóki access_token
nie wygaśnie. Staram się zbudować funkcjonalność, która zamienia refresh_token
na nową access_token
, ale ciągle podskakuje na ściany. Korzystając z dokumentacji klienta jako przykład, jest to kod, którego używam:
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'})
Ten kod działa doskonale, gdy {[1] } jest poprawny. Jak tylko wygaśnie, widzę 2 problemy: {]}
- nawet chociaż wiem, że token wygasł (sprawdziłem
expires_at
wartość w bazie danych),client.authorization.expired?
zwracafalse
-- czy istnieje inny sposób, aby sprawdzić wygaśnięcie tokenu poza użyciem wartości w bazie danych? - kiedy wymuszam wykonanie
client.authorization.fetch_access_token!
dostajęinvalid_request
błąd.
Czy ktoś może mi powiedzieć, jak mogę wymienić {[2] } na Nowy access_token
za pomocą interfejsu API klienta? Nawet jeśli wiesz, jak to zrobić w innym języku, byłoby to bardzo pomocne, ponieważ mogę spróbować Ruby go. Dzięki!!
3 answers
Być może już to znalazłeś, ale możesz przeczytać cały proces tutaj w google: https://developers.google.com/accounts/docs/OAuth2WebServer
Strategia omniauth-google-OAuth2 już zajmuje się ustawianiem access_type i approval_prompt, więc uzyskanie tokena odświeżania jest tylko kwestią wysłania do https://accounts.google.com/o/oauth2/token with grant_type=request_token
Oto mniej więcej Kod, którego używam:
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
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
2012-09-24 23:37:56
Ponieważ używasz klienta Ruby Google API, dlaczego nie użyć go do wymiany tokena odświeżania? API Ruby robi prawie to samo wewnętrznie, co @brimil01 powiedział w swojej odpowiedzi.
W ten sposób używam API Ruby do wymiany tokenu odświeżania na nowy token dostępu.
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
I zgodnie z ten problem tutaj , zaleca się nie używać metody expired?
do sprawdzania, czy token dostępu wygasł.
Zasadniczo, nie nazywaj przeterminowane? metoda. Istnieje zasadniczo zero scenariusze, w których to dobry pomysł. Po prostu nie da ci niezawodności informacja o wygaśnięciu. To bardziej podpowiedź niż prawdziwe wydechy znacznik czasu, a serwer tokenu może zdecydować o uznaniu wygasłego tokenu tak czy inaczej, w pewnych teoretycznych, ale ważnych okolicznościach. Jeśli otrzymasz nieprawidłowy błąd przyznania, zawsze odśwież token dostępu i spróbuj jeszcze raz. Jeśli nadal masz błąd, podnieś błąd.
Oto to, co robię.
# 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
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-11-19 08:08:05
Naprawiłem go za pomocą prostego kodu poniżej.
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
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-12-12 08:50:46