Guia completo para configurar OAuth em um app Ruby on Rails API com Devise Auth Token

Com o crescente interesse em aplicativos web e móveis, garantir a segurança e a facilidade de acesso dos usuários é fundamental para proporcionar uma experiência positiva. Nesse contexto, o OAuth (Open Authorization) se destaca como uma solução poderosa para autenticação e autorização seguras entre aplicativos.

Ao desenvolver aplicativos Ruby on Rails, integrar o OAuth com a autenticação do usuário é um desafio comum. No entanto, com o uso da biblioteca “Devise Auth Token” e OmniAuth, é possível simplificar e otimizar esse processo.

Neste guia completo, vamos explorar o passo a passo para configurar o OAuth em um aplicativo Ruby on Rails, utilizando a eficiente biblioteca “Devise Auth Token”. Ao seguir este tutorial, você estará apto a implementar uma solução robusta de autenticação por token em seu aplicativo, oferecendo aos usuários a opção de login por meio de provedores de terceiros, como Google, Facebook, GitHub entre outros, proporcionando segurança aos dados e uma experiência de usuário mais fluída.

Vamos mergulhar nas etapas para configurar com sucesso o OAuth em um app Ruby on Rails API. Siga os passos e transforme a autenticação do seu aplicativo em uma experiência segura e otimizada.

Por que utilizar autenticação de terceiros?

Utilizar a autenticação de terceiros traz uma série de benefícios significativos para o desenvolvimento de aplicativos web e móveis. Algumas das principais razões pelas quais a autenticação de terceiros através do OAuth é uma escolha vantajosa:

  1. Simplifica o processo de registro e login: Com o OAuth, os usuários podem se inscrever e fazer login em um aplicativo usando suas credenciais de contas existentes em provedores de terceiros, como Google, Facebook, Twitter, GitHub, etc. Isso elimina a necessidade de criar e lembrar de novas senhas, tornando o processo mais simples e rápido para os usuários.
  2. Maior segurança e confiabilidade: Ao utilizar a autenticação de terceiros, o aplicativo não precisa armazenar senhas de usuário em seu banco de dados. Em vez disso, o fluxo de autenticação é delegado aos provedores de terceiros que têm medidas robustas de segurança para proteger as credenciais dos usuários. Isso reduz a probabilidade de ataques de força bruta ou vazamentos de dados relacionados às senhas.
  3. Redução do churn de usuários: Com a facilidade de login proporcionada pelo OAuth, os usuários são mais propensos a concluir o processo de registro e a permanecer engajados com o aplicativo. A complexidade do registro tradicional pode levar a taxas mais altas de abandono durante o processo de inscrição.
  4. Acesso a informações do perfil do usuário: Com a permissão adequada do usuário, o aplicativo pode acessar algumas informações do perfil do usuário fornecidas pelo provedor de terceiros. Isso pode ser útil para personalizar a experiência do usuário e oferecer recursos relevantes.
  5. Padrão de autenticação estabelecido: O OAuth é amplamente aceito e adotado como um padrão para autenticação de terceiros. Isso significa que os desenvolvedores podem contar com a solidez e a segurança do protocolo, evitando a necessidade de criar soluções personalizadas de autenticação.

OAuth oferece uma experiência de login mais conveniente e segura para os usuários, ao mesmo tempo em que reduz a complexidade e a sobrecarga de gerenciamento de contas para os desenvolvedores. É uma escolha inteligente para qualquer aplicativo moderno que valoriza a segurança e a satisfação do usuário.

O que vou precisar para começar?

Neste tutorial vamos utilizar a versão 3.1.4 do Ruby, Rails 7.0.4.3 e banco de dados sqlite. O ambiente utilizado neste tutorial é Ubuntu (linux).

Você pode utilizar outro banco de dados passando o parametro “-d=”, ex.: -d=postgresql, ficando:

$ rails new oauth_login --api -d=postgresql

Neste exemplo usaremos o sqlite mesmo:

$ rails new oauth_login --api

Após realizar a instalação, vamos entrar no diretório e instalar algumas gems:

$ cd oauth_login

Adicione as seguintes gems:

/oauth_login$ bundle add devise_token_auth omniauth-google-oauth2 omniauth-rails_csrf_protection

Aqui adicionamos 3 gems:

  1. devise_token_auth: É uma gem que se integra com o Devise, uma popular biblioteca de autenticação para Ruby on Rails, permitindo adicionar autenticação de token ao seu aplicativo.
  2. omniauth-google-oauth2: Essa gem é uma estratégia do OmniAuth para autenticação com o Google através do protocolo OAuth 2.0.
  3. omniauth-rails_csrf_protection: Esta gem é uma extensão do OmniAuth que adiciona proteção CSRF (Cross-Site Request Forgery) aos seus fluxos de autenticação. O CSRF é um tipo comum de ataque que tenta explorar a confiança entre um usuário autenticado e um site. Essa gem ajuda a mitigar esse tipo de ataque, fornecendo uma camada adicional de segurança para o processo de autenticação.

Vamos executar agora a instalação do devise token auth:

/oauth_login$ rails g devise_token_auth:install User auth

Você pode modificar o caminho da rota padrão (auth) mudando o “auth” para o nome desejado, ex.:

/oauth_login$ rails g devise_token_auth:install User users

Neste tutorial, seguiremos os padrões.

Rode as migrações executando:

/oauth_login$ rails db:migrate

Caso ocorre algum erro, experimente adicionar o seguinte ao seu model User.rb:
app/models/user.rb:

class User < ActiveRecord::Base
  extend Devise::Models
  
  # restante dos códigos

Rode as migrações novamente.
Agora vamos criar um arquivo de configuração do omniauth dentro da pasta initialize do rails:
config/initializer/omniauth.rb:

Rails.application.config.middleware.use OmniAuth::Builder do
  OmniAuth.config.allowed_request_methods = %i[post get]
  
  provider :google_oauth2, Rails.application.credentials.dig(:omniauth, :google, :key), 
  Rails.application.credentials.dig(:omniauth, :google, :secret), scope: 'email,profile'
end

Abaixo uma breve explicação:

  1. Rails.application.config.middleware.use OmniAuth::Builder do: Esta linha inicia a configuração do middleware do OmniAuth no aplicativo Rails.
  2. OmniAuth.config.allowed_request_methods = %i[post get]: Essa linha define os métodos de solicitação HTTP permitidos para o fluxo de autenticação do OmniAuth. Neste caso, os métodos “POST” e “GET” são permitidos. Isso é importante porque o fluxo de autenticação OAuth do OmniAuth.
  3. provider :google_oauth2, Rails.application.credentials.dig(:omniauth, :google, :key), Rails.application.credentials.dig(:omniauth, :google, :secret), scope: 'email,profile': Aqui, estamos configurando o provedor de autenticação do Google OAuth 2.0 usando o OmniAuth.
    • provider :google_oauth2: Indica que estamos configurando o provedor para autenticação com o Google OAuth 2.0.
    • Rails.application.credentials.dig(:omniauth, :google, :key) e Rails.application.credentials.dig(:omniauth, :google, :secret): Acesse as credenciais armazenadas no arquivo credentials.yml.enc do Rails, que são usadas para identificar o aplicativo no provedor de autenticação (Google). Essas credenciais geralmente incluem a chave do cliente (client key) do Google, que é um identificador exclusivo do aplicativo.
    • scope: 'email,profile': Define as permissões que o aplicativo solicitará ao usuário durante o processo de autenticação. Neste caso, o aplicativo solicita acesso ao email do usuário e ao perfil público.

Agora que configuramos o omniauth, vamos criar uma chave OAuth. Para isso, entre no console do google acessando https://console.cloud.google.com/welcome

Após o acesso, selecione um projeto ou crie um novo clicando em “Novo projeto”

Clique em APIs e serviços:

Agora em credenciais:

Clique em “Criar credenciais” e selecione “ID do Cliente OAuth”:

Você deverá criar uma tela de concentimento para utilizar este serviço. Siga as etapas da criação e após sua conclusão, clique novamente em “Credenciais”, “Criar credenciais” e “ID do cliente OAuth”

Selecione o tipo do aplicativo:

Na URIs de redirecionamento autorizados, adicione:
http://localhost:3000/omniauth/google_oauth2/callback e clique em “Criar”

Vamos adicionar as chaves ao arquivo de credenciais do rails:

Acesse o terminal novamente e vamos prosseguir com a edição:

Para linux:

/oauth_login$ EDITOR="nano" rails credentials:edit

Seu arquivo credentials deve ficar da seguinte forma:

# aws:
#   access_key_id: 123
#   secret_access_key: 345

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: 8147112cd2d1bc0d9b00b4aa46c9f4eab8da8f0200354c7f0c81c45e396a2b936dc4d341a5c67a8ff26c4046815a4928e7>

omniauth:
  google:
    key: "Seu cliente"
    secret: "sua chave"

Salve o arquivo pressionando CTRL + X, depois Y e então “ENTER”

Agora que temos a chave configurada corretamente, precisamos modificar o controller padrão de autenticação do devise token auth. Para isso, vamos criar o seguite:
app/controllers/omniauth_callbacks_controller.rb:

class OmniauthCallbacksController < DeviseTokenAuth::OmniauthCallbacksController

  def omniauth_success
    get_resource_from_auth_hash
    set_token_on_resource
    create_auth_params

    if confirmable_enabled?
      # don't send confirmation email!!!
      @resource.skip_confirmation!
    end

    sign_in(:user, @resource, store: false, bypass: false)

    @resource.save!

    yield @resource if block_given?

    if DeviseTokenAuth.cookie_enabled
      set_token_in_cookie(@resource, @token)
    end

    render json: { data: @resource, auth_params: @auth_params }

  rescue 
    return render json: {errors: ["Houve um problema ao processar sua requisição"]}
  end

  protected

  def render_error_email_already_exists
    render json: {errors: ["Este e-mail já está sendo utilizado."]}, status: :unprocessable_entity
  end
end

Colocamos algumas modificações no controller padrão do devise auth, afim de faze-lo retornar os dados de sessão do usuário no retorno, adicionamos a linha 27:

render json: { data: @resource, auth_params: @auth_params }

Na linha 29 em diante, adicionamos um rescue, para capturarmos problemas relacionados a autenticação e assim, poder informar o usuário:

 rescue 
    return render json: {errors: ["Houve um problema ao processar sua requisição"]}

Vamos adicionar uma validação de e-mail no model User.rb para evitar problemas de repetição no banco de dados:
app/models/user.rb:

# resto do código

validates :email, uniqueness: true, presence: true, allow_blank: false

Agora que criamos o controller, precisamos que o devise token auth utilize nosso controller para o omniauth:
config/routes.rb:

Rails.application.routes.draw do
  mount_devise_token_auth_for 'User', at: 'auth', controllers: {
    omniauth_callbacks: 'omniauth_callbacks'
  }
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Defines the root path route ("/")
  # root "articles#index"
end

Aqui modificamos o mount_devise_token_auth_for com:

, controllers: {
  omniauth_callbacks: 'omniauth_callbacks'
}

Por ultimo precisamos adicionar cookie e de sessões em nosso sistema, pois sem eles não é possível realizar a autenticação oauth em api:
config/application.rb

    config.api_only = true

    config.session_store :cookie_store, key: '_oauth_login_session'
    config.middleware.use ActionDispatch::Cookies
    config.middleware.use ActionDispatch::Session::CookieStore, config.session_options
  end
end

O application inteiro fica:

require_relative "boot"

require "rails/all"

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module OauthLogin
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 7.0

    # Configuration for the application, engines, and railties goes here.
    #
    # These settings can be overridden in specific environments using the files
    # in config/environments, which are processed later.
    #
    # config.time_zone = "Central Time (US & Canada)"
    # config.eager_load_paths << Rails.root.join("extras")

    # Only loads a smaller set of middleware suitable for API only apps.
    # Middleware like session, flash, cookies can be added back manually.
    # Skip views, helpers and assets when generating a new resource.
    config.api_only = true

    config.session_store :cookie_store, key: '_oauth_login_session'
    config.middleware.use ActionDispatch::Cookies
    config.middleware.use ActionDispatch::Session::CookieStore, config.session_options
  end
end

Para testar, precisamos iniciar o servidor:

/oauth_login$ rails s

Acesse: localhost:3000/auth/google_oauth2 no navegador e escolha uma conta:

Após a escolha, você será redirecionado com os dados de acesso:

os cabeçalhos de autenticação você pode encontrar no atributo auth_params

Conclusão

Com algumas modificações e comandos, foi possível realizar uma autenticação via google de uma forma simples e rápida utilizando o devise token auth e a gem omniauth-google-oauth2.

O projeto final você encontra no github, neste link: https://github.com/05104/oauth_login

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Precisa de ajuda?