Há uma grande joia para autenticação com o nome do Linked: omniauth-linkedin-oauth2
Havia um problema com a gema original, então eu bifurquei e ajustei, então fique à vontade para fazer um fork ou usar a minha.
Criar aplicativo Linkedin
Em primeiro lugar, acesse https://www.linkedin.com/developer/apps e crie um aplicativo para autenticação.
Observação importante sobre a configuração do URL:
Você deve configurar urls de retorno de chamada para cada ambiente no aplicativo Linkedin para que os retornos de chamada funcionem corretamente.
Para desenvolvimento:
http://appname.dev/auth/linkedin/callback
Para produção:
https://appname.com/auth/linkedin/callback
1. Comece adicionando a gema
gem 'omniauth-linkedin-oauth2', git: 'https://github.com/Devato/omniauth-linkedin-oauth2.git'
2. Em seguida, configure o inicializador:
#config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :linkedin, ENV['LINKEDIN_CLIENT_ID'], ENV['LINKEDIN_CLIENT_SECRET'], secure_image_url: true
end
Agora vamos retornar ao URL de retorno de chamada. Este é o URL para onde um usuário será redirecionado dentro do aplicativo após a autenticação bem-sucedida e a autorização aprovada (a solicitação também conterá os dados e o token do usuário). Todas as estratégias OmniAuth esperam que o URL de retorno de chamada seja igual a “/ auth /: provedor / retorno de chamada”. : o provedor obtém o nome da estratégia (“twitter”, “facebook”, “linkedin”, etc.) conforme listado no inicializador.
3. Adicione as rotas
#config/routes.rb
get '/auth/:provider/callback', to: 'oauth#callback', as: 'oauth_callback'
get '/auth/failure', to: 'oauth#failure', as: 'oauth_failure'
4. Um link para enviar a solicitação ao Linkedin (obviamente ainda não funcionará).
= link_to 'Register with Linkedin', '/auth/linkedin'
5. Prepare-se para armazenar os dados
Você pode configurar o armazenamento de dados da maneira que desejar. Criei um modelo separado para guardar tudo. Esta é a migração:
class CreateOauthAccounts < ActiveRecord::Migration
def change
create_table :oauth_accounts do |t|
t.belongs_to :user, index: true, foreign_key: true
t.string :provider
t.string :uid
t.string :image_url
t.string :profile_url
t.string :access_token
t.text :raw_data
t.timestamps null: false
end
end
end
6. Processe o retorno de chamada.
Eu gerei um Oauth
controlador para manter as coisas separadas:
#app/controllers/oauth_controller.rb
class OauthController < ApplicationController
def callback
begin
oauth = OauthService.new(request.env['omniauth.auth'])
if oauth_account = oauth.create_oauth_account!
...
redirect_to Config.provider_login_path
end
rescue => e
flash[:alert] = "There was an error while trying to authenticate your account."
redirect_to register_path
end
end
def failure
flash[:alert] = "There was an error while trying to authenticate your account."
redirect_to register_path
end
end
Você notará que existem dois métodos para lidar com a resposta do LinkedIn. callback
e failure
. O retorno de chamada está processando os dados e criando os registros conforme necessário. é um serviço personalizado usado para realmente processar os dados.request.env['omniauth.auth']
OauthService
7. O serviço que processa dados de retorno de chamada
Passei esse processamento para uma classe de serviço para manter tudo organizado:
#app/services/oauth_service.rb
class OauthService
attr_reader :auth_hash
def initialize(auth_hash)
@auth_hash = auth_hash
end
def create_oauth_account!
unless oauth_account = OauthAccount.where(uid: @auth_hash[:uid]).first
oauth_account = OauthAccount.create!(oauth_account_params)
end
oauth_account
end
private
def oauth_account_params
{ uid: @auth_hash[:uid],
provider: @auth_hash[:provider],
image_url: @auth_hash[:info][:image],
profile_url: @auth_hash[:info][:urls][:public_profile],
raw_data: @auth_hash[:extra][:raw_info].to_json }
end
end
Existem muitas maneiras diferentes de fazer isso, mas parecia certo e era bastante simples de testar.
ADICIONE COBERTURA DE TESTE DE RSPEC
Existem algumas nuances de teste desse processo, e aqui está o que funcionou na configuração do mocking:
1. Configurar macro para simular a resposta
#spec/support/omniauth_macros.rb
module OmniauthMacros
def mock_auth_hash
# The mock_auth configuration allows you to set per-provider (or default)
# authentication hashes to return during integration testing.
OmniAuth.config.mock_auth[:linkedin] = OmniAuth::AuthHash.new({
'provider' => 'linkedin',
'uid' => '123545',
'info' => {
'name' => 'mockuser',
'image' => 'mock_user_thumbnail_url',
'first_name' => 'john',
'last_name' => 'doe',
'email' => 'john@doe.com',
'urls' => {
'public_profile' => 'http://test.test/public_profile'
}
},
'credentials' => {
'token' => 'mock_token',
'secret' => 'mock_secret'
},
'extra' => {
'raw_info' => '{"json":"data"}'
}
})
end
end
2. Inclua esta macro em sua configuração RSpec:
#spec/rails_helper.rb
RSpec.configure do |config|
config.include(OmniauthMacros)
end
Então, abaixo do bloco de configuração, defina OmniAuth para o modo de teste:
OmniAuth.config.test_mode = true
3. Adicionar especificação de solicitação:
#spec/requests/registration_spec.rb
require "rails_helper"
describe "home#register as a provider", :type => :request do
it "redirects to oauth#callback" do
get '/auth/linkedin'
expect(response).to redirect_to(oauth_callback_path(:linkedin))
end
end
Como OmniAuth
está em modo de teste, ele deve redirecionar para retorno de chamada.
4. Especificação do OauthController:
#spec/controllers/oauth_controller_spec.rb
require 'rails_helper'
describe OauthController, type: :controller do
before(:each) do
mock_auth_hash
request.env['omniauth.auth'] = OmniAuth.config.mock_auth[:linkedin]
end
after(:each) do
OmniAuth.config.mock_auth[:linkedin] = nil
end
describe 'GET #callback' do
it 'expects omniauth.auth to be be_truthy' do
get :callback, provider: :linkedin
expect(request.env['omniauth.auth']).to be_truthy
end
it 'completes the registration process successfully' do
get :callback, provider: :linkedin
expect(page).to redirect_to Config.provider_login_path
end
it 'creates an oauth_account record' do
expect{
get :callback, provider: :linkedin
}.to change { OauthAccount.count }.by(1)
end
end
end
Você notará a chamada mock_auth_hash
e a configuração de prepara os dados de simulação para teste.request.env['omniauth.auth']
Esses testes básicos garantem que o mock esteja funcionando corretamente, que sejamos redirecionados para a rota adequada e que o OauthAccount
registro tenha sido criado corretamente.
Existem muitas maneiras diferentes de alcançar os mesmos resultados, mas foi isso que funcionou bem para nós e, esperançosamente, é uma boa referência para qualquer pessoa necessária para realizar as mesmas coisas.