Uwierzytelnić użytkownika za pomocą omniauth i Facebook dla rails API?
Buduję API Rails i z powodzeniem zbudowałem sposób uwierzytelniania użytkownika przy użyciu tożsamości Omniauth.
Po prostu wysyłamy do auth / identity / callback od klienta, przekazując auth_key i hasło.
Następnie serwer zwraca token doorkeeper, którego użytkownicy używają od tego czasu, aby uzyskać dostęp do aplikacji i zidentyfikować się.
Ten schemat ilustruje to:
Chcielibyśmy teraz zaimplementować Facebook login od klienta, ale są problemy z jego działaniem, zarówno teoretycznie, jak i praktycznie.
Na prostej aplikacji Rails z tożsamością Omniauth, po prostu wywołujesz auth / facebook, ale jeśli umieścimy link z tego w kliencie, wywoła on serwer, a następnie loguje Serwer:
INFO -- omniauth: (facebook) Request phase initiated.
Aplikacja jest poprawnie skonfigurowana w Facebook z identyfikatorem i sekretem, więc może monit logowania zostanie zwrócony na serwer?
[1]}zaczynam się mylić, choć łączenie uwierzytelniania. Każda pomoc z wdzięcznością doceniam to!3 answers
Najlepszy sposób znalazłem (po utknięciu na chwilę w tej sprawie ) jest zrobić omniauth2 (konkretnie w moim przypadku za pomocą satellizer angular plugin) ręcznie...
Omówię rozwiązanie dla Facebook, Jak to było w moim przypadku, ale wszystko może dotyczyć każdego innego dostawcy.
Najpierw musisz wiedzieć, jak działa omniauth2 (Jak udokumentowano dla ludzi tutaj )...
- Client: Otwórz wyskakujące okno dla użytkownika / align = "left" /
- Client: Zaloguj się (jeśli to konieczne), a następnie Autoryzuj aplikację.
-
Klient: po pomyślnej autoryzacji wyskakujące okienko jest przekierowywane z powrotem do aplikacji. z
code
(Kod autoryzacji) parametr ciągu zapytania
adres URL przekierowania musi odpowiadać adresowi URL aplikacji front-end, a nie adresowi URL back-end I musi być określony w konfiguracjach aplikacji facebook
-
Klient: The
code
parametr jest wysyłany z powrotem do okna nadrzędnego, które otworzyło wyskakujące okienko. -
Client: okno rodzica zamyka wyskakujące okienko i wysyła zapytanie
POST
dobackend/auth/facebook
z parametremcode
. -
Serwer:
code
(Kod autoryzacji ) jest wymieniany naaccess token
poniżej opisano szczegółowo, jak wymienić code
na access-token
od programistów facebook dokumentacja
Serwer: użyj
access-token
pobranego w kroku 6 aby pobrać informacje o użytkowniku. jak udokumentowane tutaj z ładnymi pomocami wizualnymi .VOILA masz sobie użytkownika, który możesz połączyć / utworzyć konto / połączyć z innymi dostawcami oauth / itp. ale pamiętaj, że użytkownik może odwołać niektóre uprawnienia (jak E-mail, facebook obsługuje cofanie niektórych uprawnień uprawnienia)...
(dość gadania, Pokaż mi jakiś kod)
Najpierw musisz dodać HTTParty gem do swojego Gemfile
gem 'httparty' # Makes http fun again (http client)
Dodałemten gist , który zawiera przepływ dla kroku (6, 7 i 8) są to najbardziej problematyczne kroki i nie są udokumentowane prawie nigdzie.
Gist eksportuje 2 główne metody:
Omniauth::Facebook.authenticate(authorization_code)
Który jest używany do uwierzytelniania użytkownika za pomocą facebook i zwraca user_info, long_live_access_token (valid przez 60 dni)
Omniauth::Facebook.deauthorize(access_token)
Który służy do dezautoryzacji / cofnięcia uprawnień access_token i aplikacji na facebook...
Jest to używane do specjalnych wymagań, które mam, gdy użytkownik odwołuje uprawnienia e-mail wymagane na Facebook login... cofamy wszystkie uprawnienia aplikacji... spowoduje to monit użytkownika przy następnym logowaniu, tak jakby był to jego pierwszy login (nie ma potrzeby przechodzenia do aplikacji facebook i ręcznego odwoływania aplikacji)...
Oto jak jest używany w controller
user_info, access_token = Omniauth::Facebook.authenticate(params['code'])
if user_info['email'].blank?
Omniauth::Facebook.deauthorize(access_token)
end
To jest to... teraz, jeśli jesteś zainteresowany w wewnętrznych realizacji... oto Kod, jak widać w gist. (dodano w celach informacyjnych) Możesz go rozwidlać, edytować i ulepszać.
require 'httparty'
module Omniauth
class Facebook
include HTTParty
# The base uri for facebook graph API
base_uri 'https://graph.facebook.com/v2.3'
# Used to authenticate app with facebook user
# Usage
# Omniauth::Facebook.authenticate('authorization_code')
# Flow
# Retrieve access_token from authorization_code
# Retrieve User_Info hash from access_token
def self.authenticate(code)
provider = self.new
access_token = provider.get_access_token(code)
user_info = provider.get_user_profile(access_token)
return user_info, access_token
end
# Used to revoke the application permissions and login if a user
# revoked some of the mandatory permissions required by the application
# like the email
# Usage
# Omniauth::Facebook.deauthorize(access_token)
# Flow
# Send DELETE /me/permissions?access_token=XXX
def self.deauthorize(access_token)
options = { query: { access_token: access_token } }
response = self.delete('/me/permissions', options)
# Something went wrong most propably beacuse of the connection.
unless response.success?
Rails.logger.error 'Omniauth::Facebook.deauthorize Failed'
fail Omniauth::ResponseError, 'errors.auth.facebook.deauthorization'
end
response.parsed_response
end
def get_access_token(code)
response = self.class.get('/oauth/access_token', query(code))
# Something went wrong either wrong configuration or connection
unless response.success?
Rails.logger.error 'Omniauth::Facebook.get_access_token Failed'
fail Omniauth::ResponseError, 'errors.auth.facebook.access_token'
end
response.parsed_response['access_token']
end
def get_user_profile(access_token)
options = { query: { access_token: access_token } }
response = self.class.get('/me', options)
# Something went wrong most propably beacuse of the connection.
unless response.success?
Rails.logger.error 'Omniauth::Facebook.get_user_profile Failed'
fail Omniauth::ResponseError, 'errors.auth.facebook.user_profile'
end
response.parsed_response
end
private
# access_token required params
# https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.3#confirm
def query(code)
{
query: {
# The authorization_code we want to exchange for the access_token
code: code,
# This must match the redirectUrl registerd in the facebook app.
# You can save it to ENV['WEB_APP_URL'] if you have multiple facebook apps for development and testing
# so you can support testing app on development and production app on production env.
redirect_uri: "http://localhost:9000/",
client_id: ENV['FB_APP_ID'], # Facebook appId
client_secret: ENV['FB_APP_SECRET'], # Facebook app secret (must not exist on front-end app for security)
}
}
end
end
end
Oto kolejny NodeJS tutorial implementujący oauth dla instagram który pomógł mi zrozumieć, jak działa oauth2 (dodany dla odniesienia)
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-05-06 15:12:48
Aby rozwiązać ten problem najlepszym zasobem, jaki znalazłem, jest przykładowa aplikacja rails w repo satellizer github: https://github.com/sahat/satellizer/tree/master/examples/server/ruby
Twój kod satelitarny wywołuje Kontroler AuthController.metoda authenticate . Ta metoda wykorzystuje klasy modelu oauth dla każdego dostawcy do konwersji otrzymanego kodu na token dostępu. Następnie w Klasa użytkownika możesz pobrać użytkownika, który pasuje do informacji, które otrzymałeś od dostawcy.
Na końcu metoda kontrolera zwraca klientowi token jwt.
W moim przypadku część kontrolera jest nieco inna, ponieważ używam również devise do uwierzytelniania poczty/hasła, ale kopiuję klasy oauth tak, jak jest i działa jak urok.
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-05-12 06:32:52
Do komunikacji z facebook api. Polecam użycie klejnotu 'omniauth-facebook' . Możesz sklonować ten przykład, aby zrozumieć więcej: https://github.com/ralphos/omniauth-facebook-example
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-03 21:10:15