ruby on rails - developers - ¿Autentica el usuario usando omniauth y Facebook para una API de rieles?
facebook developers login (3)
La mejor manera que encontré (después de haber estado estancado durante un tiempo sobre este tema) es hacer tu omniauth2 (específicamente en mi caso usando el plugin satellizer angular) manualmente ...
Discutiré la solución para Facebook como era mi caso, pero todo podría aplicarse a cualquier otro proveedor.
primero tienes que saber cómo funciona omniauth2 ( como se documenta para los humanos aquí ) ...
- Cliente: abra una ventana emergente para que el usuario se autentique.
- Cliente: inicie sesión (si es necesario) y luego autorice la aplicación.
- Cliente: después de la autorización exitosa, la ventana emergente se redirige a su aplicación. con el parámetro de cadena de consulta del
code
(code
autorización)
la dirección URL de redireccionamiento debe coincidir con la URL de la aplicación front-end, no con la url de la parte posterior, y debe especificarse en la configuración de la aplicación de Facebook.
- Cliente: el parámetro de
code
se envía de vuelta a la ventana principal que abrió el menú emergente. - Cliente: la ventana principal cierra la ventana emergente y envía una solicitud
POST
abackend/auth/facebook
con el parámetro decode
. - Servidor: el
code
(code
autorización ) se intercambia poraccess token
aquí se describe en detalle cómo intercambiar el code
de un access-token
de access-token
de la documentación de desarrolladores de Facebook
Servidor: use el
access-token
recuperado en el paso 6 para recuperar la información del Usuario. como se documenta aquí con buenas ayudas visuales .VOILA usted tiene un usuario que puede fusionar / crear cuenta / vincular con otros proveedores de oauth / etc. pero sin olvidar que el usuario puede revocar algunos de los permisos (como el correo electrónico , Facebook admite la revocación de algunos de los permisos) ...
(Hablando suficiente, muéstrame un código)
Primero debes agregar la gema HTTParty a tu Gemfile
gem ''httparty'' # Makes http fun again (http client)
He agregado esta idea que contiene el flujo para el paso (6, 7 y 8). Estos son los pasos más problemáticos y no están documentados en casi ninguna parte.
la esencia exporta 2 métodos principales:
Omniauth::Facebook.authenticate(authorization_code)
que se usa para autenticar al usuario con Facebook y devolver el user_info, long_live_access_token (válido por 60 días)
Omniauth::Facebook.deauthorize(access_token)
que se usa para desautorizar / revocar el access_token y los permisos de la aplicación en Facebook ...
Esto se utiliza para un requisito especial que tengo, cuando el usuario revoca el permiso de correo electrónico solicitado en el inicio de sesión de Facebook ... revocamos todos los permisos de la aplicación ... esto solicitará al usuario el siguiente inicio de sesión como si fuera su primer inicio de sesión (no es necesario) ir a aplicaciones de Facebook y revocar manualmente la aplicación) ...
aquí es cómo se usa en el controlador
user_info, access_token = Omniauth::Facebook.authenticate(params[''code''])
if user_info[''email''].blank?
Omniauth::Facebook.deauthorize(access_token)
end
Eso es todo ... ahora si está interesado en las partes internas de la implementación ... aquí está el código como se ve en la esencia. (Agregado para referencia) Siéntase libre de bifurcarlo, editarlo, ayudar a hacerlo mejor.
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
Aquí hay otro tutorial de nodejs que implementa oauth para instagram que me ayudó a entender cómo está funcionando oauth2 (se agregó como referencia)
Estoy construyendo una API de Rails y he creado una forma para que un usuario se autentique usando Omniauth Identity.
Simplemente publicamos en auth / identity / callback desde el cliente, pasando una auth_key y una contraseña.
Luego, el servidor devuelve una ficha de guardián que los usuarios utilizan a partir de ese momento para acceder a la aplicación e identificarse.
Este diagrama ilustra esto:
Ahora nos gustaría implementar un inicio de sesión de Facebook desde el cliente, pero estamos teniendo problemas para hacerlo funcionar, tanto teórica como prácticamente.
En una sencilla aplicación de Rails con Omniauth Identity, simplemente llame a auth / facebook, pero si ponemos un enlace desde este en el cliente, llama al servidor y el servidor y luego inicia sesión:
INFO -- omniauth: (facebook) Request phase initiated.
La aplicación está configurada correctamente en Facebook con una identificación y secreto, por lo que tal vez el prompt de inicio de sesión se devuelva al servidor.
Me estoy confundiendo, aunque encadenando la autenticación. Cualquier ayuda apreciada con gratitud!
Para la comunicación con facebook api. Recomiendo usar github.com/mkdynamic/omniauth-facebook . Puede clonar este ejemplo para comprender más: https://github.com/ralphos/omniauth-facebook-example
Para resolver este problema, el mejor recurso que encontré es la aplicación de ejemplo Rails en el repositorio github satellizer: https://github.com/sahat/satellizer/tree/master/examples/server/ruby
El código de su satelizador llama al método AuthController.authenticate . Este método utiliza las clases de modelo Oauth para cada proveedor para convertir el código que recibe en un token de acceso. Luego, en su clase de usuario puede recuperar al usuario que coincida con la información que recibió del proveedor.
Al final, el método del controlador devuelve el token jwt al cliente.
En mi caso, la parte del controlador es un poco diferente porque también uso el diseño para la autenticación de correo / contraseña, pero copio las clases como son y funciona como un amuleto.