Já existem alguns excelentes tutoriais por aí mostrando como usar estratégias oauth e omniauth para fazer login usando várias plataformas online, como o login railscasts com screencast do Twitter. Usando um método semelhante hoje, vamos fazer o login usando a API do Soundcloud.
Primeiro, precisamos criar um novo aplicativo Rails 4. Usarei o postgreSQL como meu banco de dados e também ignorarei o conjunto de testes por enquanto.
$rails new login-with-soundcloud-demo-app -T -d postgresql
Agora que temos o aplicativo criado e pronto para funcionar, precisamos de uma página de login e de uma página de login. Primeiro entramos no diretório do aplicativo e, em seguida, geramos um controlador estático com a ação inicial que definimos como nossa raiz.
$cd login-with-soundcloud-demo-app
$rails g controller static home
E, em nosso arquivo config / routes.rb, inserimos o seguinte:
root 'static#home'
Depois de fazer isso, podemos criar o banco de dados.
$rake db:create
Agora, se ligarmos o servidor, devemos obter uma página em branco com algum texto de espaço reservado gerado automaticamente.
Em seguida, chegamos à parte interessante. Para interagir com a api soundcloud, podemos usar o wrapper ruby, que pode ser encontrado aqui https://github.com/soundcloud/soundcloud-ruby . Para fazer isso, colocamos as seguintes linhas em nosso gemfile e executamos o bundle install no terminal.
#Soundcloud API wrapper
gem 'soundcloud'
–
$bundle install
Agora que temos os ossos do nosso aplicativo definido, precisamos criar um aplicativo Soundcloud para nos permitir interagir com sua API. Para fazer isso, vamos para http://soundcloud.com/you/apps/new , digite o nome do seu aplicativo e clique em ‘Registrar’. Na próxima página, precisamos preencher a url do site do nosso aplicativo e também o URI de redirecionamento. Estaremos usando como nosso URI por enquanto e um url inventado para o campo de url do nosso site. Eles podem (e precisam ser) alterados posteriormente, então não se preocupe com eles agora. Por fim, marque a caixa de seleção referente às políticas do desenvolvedor e clique em ‘Salvar aplicativo’.http://localhost:3000/
De volta ao nosso aplicativo Rails, agora precisamos configurar algum tipo de fluxo de usuário que envia o usuário ao Soundcloud, permite que ele faça o login (se ainda não estiver conectado), confirme se deseja fazer o login com o soundcloud e, em seguida, será redirecionado de volta para nosso aplicativo.
A primeira coisa que precisamos é de um modelo de usuário. Neste modelo, precisamos armazenar o token de acesso do soundcloud dos usuários e também para acelerar nosso aplicativo, é provavelmente uma boa ideia adicionar um índice a esta coluna. Fazemos isso no terminal com o seguinte comando:
rails g model User soundcloud_user_id:integer:index soundcloud_access_token:string:index
e então confirmamos as alterações no banco de dados com:
rake db:migrate
Assim que a migração for executada, podemos começar a configurar como iremos interagir com a API. Precisamos de um controlador para rotear tudo e é uma boa ideia chamar o controlador de soundcloud para sabermos exatamente com o que ele lida conforme nosso aplicativo cresce. No controlador de soundcloud, precisamos de 3 ações, conectar, conectar e destruir. Portanto, vamos em frente e criar o controlador, mas também vamos nos certificar de que nenhuma visualização seja criada, pois não precisamos delas.
$rails g controller Soundcloud connect connected destroy --skip-template-engine
Assim que o controlador for gerado, navegue até ele e insira o seguinte código na conexão:
def connect
# create client object with app credentials
client = Soundcloud.new(:client_id => ENV["SOUNDCLOUD_CLIENT_ID"],
:client_secret => ENV["SOUNDCLOUD_CLIENT_SECRET"],
:redirect_uri => "http://localhost:3000/soundcloud/oauth-callback",
:response_type => 'code')
# redirect user to authorize URL
redirect_to client.authorize_url(:grant_type => 'authorization_code', :scope => 'non-expiring', :display => 'popup')
end
Ok, há um monte de coisas importantes acontecendo aqui, então vamos dar uma olhada. Criamos uma nova instância da Soundcloud
classe e atribuímos a ela alguns valores, mas de onde obtemos esses valores? Se navegarmos de volta à página do Soundcloud do aplicativo que acabamos de gerar, encontraremos nosso e . Como somos super cuidadosos com a segurança, ocultamos seus valores nas variáveis de ambiente. Para fazer isso no Mac OSX, estou usando a gema. Você pode aprender como usá-lo aqui: https://github.com/philnash/envyable . Basicamente, criei um arquivo YAML (chamado no meu caso, mas você pode chamá-lo do que quiser) que, em seguida, adicionei ao meuClient ID
Client Secret
envyable
env.yml
.gitignore
arquivo para garantir que não seja publicado em nenhum repositório público. Dessa forma, meus segredos nunca serão expostos. Vamos em frente e adicionar a joia invejável ao nosso gemfile:
#Envirnoment variable manager
$gem 'envyable'
e execute a instalação do pacote:
$bundle install
Em seguida, precisamos criar nosso arquivo YAML no diretório de configuração e inserir nossos segredos do Soundcloud nele (seus segredos, é claro, serão diferentes daqueles que inserir aqui).
#env.yml
SOUNDCLOUD_CLIENT_ID: a892399b90a5099247b564e0bba71205
SOUNDCLOUD_CLIENT_SECRET: 4f87403b17abb32670ba3cd43f515046
Depois de fazer isso, precisamos reiniciar nosso servidor Rails para que as alterações tenham efeito e, em seguida, temos que adicionar as seguintes linhas a .gitignore (adicionar secrets.yml também é uma boa ideia, então devemos fazer isso agora).
/config/secrets.yml
/config/env.yml
Agora que configuramos nossas variáveis de ambiente, vamos voltar e examinar o código em nossa ação de conexão do Soundcloud. Podemos ver que o link de redirecionamento é um pouco diferente do que inserimos no painel de configurações do aplicativo soundcloud, então vamos atualizar rapidamente (substitua o URI de redirecionamento por . Depois de clicar em salvar no painel de configurações do aplicativo soundcloud, podemos ir para nosso e crie as rotas necessárias para que tudo funcione. Agora, nosso routes.rb deve ficar assim:http://localhost:3000
http://localhost:3000/soundcloud/oauth-callback
routes.rb
root 'static#home'
get '/soundcloud/connect', :to => 'soundcloud#connect'
get 'soundcloud/oauth-callback', to: 'soundcloud#connected'
get 'logout', to: 'soundcloud#destroy', as: 'logout'
De volta à ação de conexão no controlador Soundcloud, temos um último pedaço de código para revisar, ou seja, o redirecionamento para chamar `redirect to client.authorize url (: grant type => ‘ authority_code ‘ ,: scope => ‘non-expiring’ ,: display => ‘popup’) `. Este é um método integrado à classe Soundcloud e solicitamos um código de autorização que não expira, então não precisamos nos preocupar em atualizar os tokens posteriormente. Finalmente, queremos passar a opção pop-up, mas você pode deixá-la desativada se desejar.
Em seguida, precisamos criar um botão em nossa página inicial com um link para a ação souncloud # connect para que o usuário tenha algo em que clicar para fazer o login. Peguei uma imagem ‘Connect with Soundcloud’ do site deles e coloquei na pasta. No arquivo de visualização da página inicial Static # (nossa raiz), coloquei o código a seguir, que deve enviar nosso usuário ao Soundcloud para fazer o login./app/assets/images
<%= link_to image_tag("soundcloud_connect.png"), soundcloud_connect_path %>
Agora podemos clicar no botão e seremos redirecionados para o loop de autorização do Soundcloud. Clique em conectar na página soundlcoud e você será enviado de volta ao seu site com os dados necessários a reboque.
* Neste ponto, você pode encontrar um erro relacionado aos certificados SSL. É mais ou menos assim:
OpenSSL::SSL::SSLError in SoundcloudController#connected
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
Isso ocorre quando seus certificados SSL estão desatualizados. Se você tiver esse problema, há uma solução fácil. Usando a certified
joia, podemos garantir que nossos certificados estejam sempre atualizados. Simplesmente adicione esta linha ao seu gemfile e execute o bundle install.
#Keep SSL certs up to date
gem 'certified'
Em seguida, no Terminal:
$bundle install
Se você precisar instalar a gem certificada, reinicie o servidor para que as alterações tenham efeito.
Se você tiver chegado até aqui com sucesso, encontrará um erro informando que não há um modelo de visualização para a ação soundcloud # connected porque nós propositadamente deixamos isso de fora. Em vez disso, usaremos a ação soundcloud # connected para construir um token de troca a partir do token de acesso que o soundcloud nos deu, adicionar o usuário ao banco de dados (se for a primeira vez que usa nosso aplicativo) e, em seguida, conectar o usuário (criando uma sessão para eles). Finalmente, iremos redirecioná-los para a página inicial com um aviso informando que eles estão logados. O código para fazer isso é semelhante a este:
def connected
# create client object with app credentials
client = Soundcloud.new(:client_id => ENV["SOUNDCLOUD_CLIENT_ID"],
:client_secret => ENV["SOUNDCLOUD_CLIENT_SECRET"],
:redirect_uri => "http://localhost:3000/soundcloud/oauth-callback")
# exchange authorization code for access token
access_token = client.exchange_token(:code => params[:code])
client = Soundcloud.new(:access_token => access_token["access_token"])
# make an authenticated call
soundcloud_user = client.get('/me')
unless User.where(:soundcloud_user_id => soundcloud_user["id"]).present?
User.create_from_soundcloud(soundcloud_user, access_token)
end
sign_in_user = User.where(:soundcloud_user_id => soundcloud_user["id"])
#create user sessions
session[:user_id] = sign_in_user.first.id
redirect_to root_url, notice: "Signed in!"
end
Você deve ter notado que existe um método indefinido chamado create_from_soundcloud
sendo chamado no modelo de usuário. Precisamos criar esse método no modelo de usuário. É o que gravará o registro do usuário no banco de dados. No arquivo, adicione o seguinte:/app/models/user.rb
def self.create_from_soundcloud(access_token)
create! do |user|
user.soundcloud_user_id = soundcloud_user["id"]
user.soundcloud_access_token = access_token["access_token"]
end
end
Ainda não configuramos uma maneira de renderizar os avisos, então vamos adicionar rapidamente o seguinte código ao arquivo de visualização diretamente entre a tag de abertura do corpo e a chamada de rendimento.application.html.erb
<% if notice %>
<p class="alert alert-success"><%= notice %></p>
<% end %>
<% if alert %>
<p class="alert alert-danger"><%= alert %></p>
<% end %>
Também precisamos de uma maneira de persistir a sessão com uma current_user
variável que podemos fazer no arquivo. Todo o código de todo o arquivo deve ter a seguinte aparência:application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
private
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
end
Finalmente, seria bom renderizar uma visão diferente dependendo se o usuário está logado com sucesso ou não. Para fazer isso, criaremos 2 parciais na pasta chamada e respectivamente. Cortaremos e colaremos o conteúdo da # visualização inicial estática atual no parcial, substituindo a tag H1 pelo texto e, em seguida, simplesmente adicionaremos a linha ao parcial. Finalmente, iremos substituir o código estático para renderizar um parcial se não houver nenhum usuário conectado e o outro se o usuário estiver conectado. O código para isso se parece com este:/views/static
_logged_in.html.erb
_logged_out.html.erb
_logged_out.html.erb
Logged Out
<h1>Logged In</h1>
_logged_in.html.erb
home.html.erb
<% if current_user %>
<%= render :partial => 'logged_in' %>
<% else %>
<%= render :partial => 'logged_out' %>
<% end %>
OK, então vamos tentar nosso novo fluxo de login. Vá para o URL raiz e clique no botão de conexão do soundcloud. Sim, funciona!
E se quisermos permitir que o usuário faça logout? Vamos adicionar o código para logout à ação soundcloud # destroy (se tivéssemos mais opções de login, provavelmente faria mais sentido colocá-lo em um controlador de sessões, mas isso funcionará por enquanto).
def destroy
session[:user_id] = nil
redirect_to root_url, notice: "Logged out!"
end
Também precisamos adicionar uma linha ao parcial para permitir que o usuário saia:_logged_in.html.erb
<p><%= link_to "Logout", logout_path %></p>
Agora, se formos para nosso root_url e clicarmos no link, seremos levados de volta à tela de login. É isso aí. O Soundcloud Connect está funcionando e pronto para o resto do seu aplicativo. Eu recomendo fortemente verificar os exemplos de ruby na documentação da API do Soundcloud para ver como você pode interagir com ele e também a documentação para a gem do Soundcloud que tem alguns bons exemplos também.