Tutorial do Rails 4: Login com o Soundcloud

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 Soundcloudclasse 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 IDClient Secretenvyableenv.yml.gitignorearquivo 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:3000http://localhost:3000/soundcloud/oauth-callbackroutes.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 certifiedjoia, 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_soundcloudsendo 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_uservariá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.erbLogged Out<h1>Logged In</h1>_logged_in.html.erbhome.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.