[RUBY] Je souhaite authentifier les utilisateurs auprès de Rails avec Devise + OmniAuth

Ce que je veux faire cette fois

Fonction d'authentification utilisateur de base à l'aide de Devise

Je souhaite enregistrer en un clic pour l'authentification SNS sans passer par un e-mail d'enregistrement temporaire

Lors de la modification des informations utilisateur par défaut dans Devise, un mot de passe vous sera demandé à chaque fois, mais comme il n'est pas convivial, je souhaite modifier les informations utilisateur sans entrer de mot de passe

Objectif personnel de cet article

mémorandum. Conservez le code source de ce projet sur GitHub.

https://github.com/zizynonno/devise_omniauth

1 Présentation de la devise

1.1 Créer un projet

Créez un nouveau projet.

$ rails new devise_omniauth
$ cd devise_omniauth

1.2 Ajout et installation de Gemfile

Ajoutez la gemme suivante au Gemfile.

Gemfile


source 'https://rubygems.org'

(réduction)...

# Devise
gem 'devise'
gem 'devise-i18n'
gem 'omniauth-twitter'
gem 'omniauth-facebook'
gem 'dotenv-rails'

Gemfile


gem 'devise' #Authentification d'utilisateur
gem 'devise-i18n' #concevoir i18n
gem 'omniauth-twitter' #authentification Twitter
gem 'omniauth-facebook' #authentification facebook
gem 'dotenv-rails' #Définition des variables d'environnement

Installez gem.

$ bundle install

2 paramètres de l'appareil

Ajout de fichiers liés au dispositif.

$ rails g devise:install

Lorsque vous exécutez cette commande, le terminal vous informe des paramètres du périphérique en anglais. Passons de 1 à 4.

** 2.1 Spécifiez l'URL par défaut **

config/environments/development.rb


Rails.application.configure do
  # Settings specified here will take precedence over those in config/application.rb.

  (réduction)...

  # mailer setting
  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
end

** 2.2 Spécification de root_url ** Spécifiez la page à afficher lors de l'accès à * http: // localhost: 3000 / * spécifié dans le n ° 1. Nous n'avons créé aucune page dans ce projet, nous les ajouterons donc en premier.

Ajoutons un contrôleur de pages et indexons et affichons les pages.

$ rails g controller Pages index show

Spécifiez ce qui suit dans routes.rb.

config/routes.rb


Rails.application.routes.draw do
  root 'pages#index'
  get 'pages/show'
  (réduction)...
end

** 2.3 Ajouter un message flash ** Lorsque vous vous connectez, un message comme "Vous êtes connecté" apparaîtra en haut. Insère la balise spécifiée juste en dessous de la balise «» dans le fichier suivant.

erb:app/views/layouts/application.html.erb


<!DOCTYPE html>
<html> 
 <head>
  <title>DeviseRails5</title>
  <%= csrf_meta_tags %>

  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
 </head>
 <body>
  <%#d'ici%>
  <p class="notice"><%= notice %></p>
  <p class="alert"><%= alert %></p>
  <%#Jusque là%>
                                                                                                                
  <%= yield %>

 </body> 
</html>

** 2.4 Générer une vue Devise **

$ rails g devise:views

Ensuite, le fichier suivant sera généré.

app/views/devise/shared/_links.html.erb (Partiel pour lien)
app/views/devise/confirmations/new.html.erb (Renvoyer l'écran du courrier d'authentification)
app/views/devise/passwords/edit.html.erb (Écran de changement de mot de passe)
app/views/devise/passwords/new.html.erb (Écran pour envoyer un email lorsque vous oubliez votre mot de passe)
app/views/devise/registrations/edit.html.erb (Écran de modification des informations utilisateur)
app/views/devise/registrations/new.html.erb (Écran d'enregistrement de l'utilisateur)
app/views/devise/sessions/new.html.erb (Écran de connexion)
app/views/devise/unlocks/new.html.erb (Déverrouiller l'écran de renvoi des e-mails)
app/views/devise/mailer/confirmation_instructions.html.erb (Texte de vérification du compte de messagerie)
app/views/devise/mailer/password_change.html.erb (instruction d'achèvement de changement de mot de passe de messagerie)
app/views/devise/mailer/reset_password_instructions.html.erb (Déclaration de réinitialisation du mot de passe par e-mail)
app/views/devise/mailer/unlock_instructions.html.erb (Déverrouiller le texte pour le courrier)

3 Paramètres du modèle utilisateur

3.1 Création d'un modèle utilisateur

$ rails g devise User

Lorsque vous exécutez, le fichier de migration et le fichier utilisateur sont créés.

db/migrate/20200912194315_devise_create_users.rb


class DeviseCreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      # ## Trackable
      # t.integer  :sign_in_count, default: 0, null: false
      # t.datetime :current_sign_in_at
      # t.datetime :last_sign_in_at
      # t.string   :current_sign_in_ip
      # t.string   :last_sign_in_ip

      # ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      # ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      t.timestamps null: false
    end
  end
end

app/models/user.rb


class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end

3.2 Édition du fichier de migration et du modèle utilisateur

Je ne commenterai que ceux qui l'utilisent.

db/migrate/20200912194315_devise_create_users.rb


class DeviseCreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Confirmable
      t.string   :confirmation_token
      t.datetime :confirmed_at
      t.datetime :confirmation_sent_at
      t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      t.string   :unlock_token # Only if unlock strategy is :email or :both
      t.datetime :locked_at


      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    add_index :users, :confirmation_token,   unique: true
    add_index :users, :unlock_token,         unique: true
  end
end

En plus de ce que vous mettez dans le fichier de migration, ajoutez ʻomniauth_providers: [: twitter,: facebook] `pour effectuer l'authentification OAuth.

app/models/user.rb


class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :confirmable, :lockable, :timeoutable, :omniauthable, omniauth_providers: [:twitter,:facebook]
end

3.3 Ajout d'une colonne pour l'omniauth

Ensuite, ajoutez provider, ʻuid et ʻusername utilisés dans omniauth-twitter et omniauth-facebook à la table User.

$ rails g migration add_columns_to_users provider uid username

Le fichier de migration suivant sera créé.

db/migrate/20200912194427_add_columns_to_users.rb


class AddColumnsToUsers < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :provider, :string
    add_column :users, :uid, :string
    add_column :users, :username, :string
  end
end

Une fois que vous avez fait cela, procédez comme suit:

$ rake db:migrate

4 Authentifiez-vous avec Twitter, Facebook

4.1 Obtenez chaque clé API et clé secrète pour l'authentification Twitter et l'authentification Facebook

Facebook

Créez une application à partir des éléments suivants.

Lorsque la création est terminée, sélectionnez "Ajouter une plateforme" -> "Site Web" dans les paramètres. Entrez l'URL dans l'URL du site (exemple: http: // localhost: 3000).

Twitter

Créez une application à partir des éléments suivants.

Une fois la création terminée, définissez les paramètres suivants dans "Paramètres".

  1. Callback URL
  1. Vérifiez les éléments suivants:

4.2 Édition du fichier de configuration

Copiez et collez chaque clé API et clé secrète aux emplacements appropriés ci-dessous.

config/initializers/devise.rb


Devise.setup do |config|
  # The secret key used by Devise. Devise uses this key to generate
  (réduction)...
  config.omniauth :facebook, 'Saisissez l'identifiant de l'application', 'Entrez le secret de l'application' #Je vais le corriger bientôt
  config.omniauth :twitter, 'Entrez la clé API', 'Entrez le secret de l'API' #Veuillez ne pas vous engager sur GitHub car nous le corrigerons bientôt
end

4.3 Implémentation du traitement des rappels dans le contrôleur de l'utilisateur

Vous devez définir une méthode avec le même nom que provider. Cependant, comme le traitement de rappel est fondamentalement commun à chaque fournisseur, il est unifié à la méthode callback_from.

$ rails generate devise:controllers users

app/controllers/users/omniauth_callbacks_controller.rb


class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    callback_from :facebook
  end

  def twitter
    callback_from :twitter
  end

  private

  def callback_from(provider)
    provider = provider.to_s

    @user = User.find_for_oauth(request.env['omniauth.auth'])

    if @user.persisted?
      flash[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize)
      sign_in_and_redirect @user, event: :authentication
    else
      session["devise.#{provider}_data"] = request.env['omniauth.auth']
      redirect_to new_user_registration_url
    end
  end
end

4.4 Processus de routage

Configurez le routage pour les rappels OAuth comme suit:

config/routes.rb


Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }

  # ...
end

5 Clé API privée et clé secrète

J'ai obtenu la clé API et la clé secrète pour l'authentification Twitter et Facebook. Ces informations sont très confidentielles et ne doivent jamais être divulguées à l'extérieur. Puisqu'il existe un risque d'utilisation abusive, il est nécessaire de prendre des mesures pour éviter que la clé API et la clé secrète ne soient accidentellement divulguées au public dans le référentiel distant de GitHub ou dans l'environnement de production.

Puisque nous avons bundle install`` gem'dotenv-rails '' pour définir les variables d'environnement au début, nous allons apprendre comment utiliser la clé API et la clé secrète en utilisant dotenv-rails`.

** 5.1 Installation du fichier .env ** Ensuite, placez le fichier .env qui définit les variables d'environnement dans la ** racine du projet de l'application **. Le fichier .env n'est pas généré automatiquement même si vous `` bundle install '' dotenv-rails`, vous devez donc créer manuellement le fichier en utilisant la commande tactile comme indiqué ci-dessous.

$ touch .env 

** 5.2 Mettez ce qui suit dans le fichier .env **

.env


TWITTER_API_KEY="Clé API Twitter obtenue"
TWITTER_SECRET_KEY="Obtention de la clé secrète Twitter"
FACEBOOK_API_ID="Obtention de la clé API Facebook"
FACEBOOK_API_SECRET="Obtention de la clé secrète Facebook"

** 5.3 Utiliser des variables d'environnement ** Attribuez des variables d'environnement au fichier codé en dur à l'aide d'une méthode de description telle que ʻENV ['SECRET_KEY'] `.

config/initializers/devise.rb


Devise.setup do |config|
  # The secret key used by Devise. Devise uses this key to generate
  (réduction)...
  config.omniauth :twitter, ENV['TWITTER_API_KEY'], ENV['TWITTER_API_SECRET_KEY']
  config.omniauth :facebook, ENV['FACEBOOK_API_ID'], ENV['FACEBOOK_API_SECRET']
end

6 Ajouter une méthode au modèle utilisateur

Créez ** self.from_omniauth ** et ** self.new_with_session ** dans le modèle User. Dans self.from_omniauth, si vous recherchez par uid et fournisseur, il sera créé, sinon il sera créé. Pour self.new_with_session, si vous n'ajoutez pas cette méthode, même si vous vous inscrivez sur la page d'inscription après l'authentification Twitter, l'uid et le fournisseur etc. que vous avez obtenus comme informations d'authentification ne seront pas enregistrés. Puisqu'ils ne sont pas enregistrés, vous serez redirigé vers la page d'inscription à chaque fois en tant qu'utilisateur non enregistré, même si vous vous authentifiez avec Twitter.

app/models/user.rb


class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :confirmable, :lockable, :timeoutable, :omniauthable, omniauth_providers: [:twitter]

  def self.from_omniauth(auth)
    find_or_create_by(provider: auth["provider"], uid: auth["uid"]) do |user|
      user.provider = auth["provider"]
      user.uid = auth["uid"]
      user.username = auth["info"]["nickname"]
    end
  end

  def self.new_with_session(params, session)
    if session["devise.user_attributes"]
      new(session["devise.user_attributes"]) do |user|
        user.attributes = params
      end
    else
      super
    end
  end
end

6.1 Implémenter la méthode de recherche dans le modèle utilisateur

La combinaison de «uid» et «provider» est unique, ce qui obtient l'utilisateur. Créez-le s'il n'existe pas dans l'enregistrement.

app/models/user.rb


class User < ActiveRecord::Base
  # ...

  def self.find_for_oauth(auth)
    user = User.where(uid: auth.uid, provider: auth.provider).first

    unless user
      user = User.create(
        uid:      auth.uid,
        provider: auth.provider,
        email:    User.dummy_email(auth),
        password: Devise.friendly_token[0, 20]
      )
    end
    user.skip_confirmation! #Inscription immédiate sans passer par un email d'inscription temporaire
    user
  end

  private

  def self.dummy_email(auth)
    "#{auth.uid}-#{auth.provider}@example.com"
  end
end

Si vous implémentez également l'authentification avec une adresse e-mail, vous devez enregistrer l'adresse e-mail lors de l'authentification avec OAuth. Ici, en profitant de la combinaison unique de ʻuidet deprovider, il est généré comme self.dummy_email`.

Modifiez le fichier suivant afin que le contrôleur que vous avez créé précédemment soit appelé comme contrôleur pour le rappel. Si vous n'écrivez pas ceci, le contrôleur côté appareil sera appelé.

config/routes.rb


Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
  root 'pages#index'
  get 'pages/show'
  (réduction)...
end

Vous pouvez maintenant vous authentifier avec Twitter. Lorsque vous effectuez l'authentification Twitter pour la première fois, vous serez redirigé vers la page d'inscription, où vous pouvez entrer votre adresse e-mail et votre mot de passe pour vous inscrire et vos informations d'utilisateur seront enregistrées. Depuis que j'ai inclus la fonction de confirmation cette fois, je reçois un message disant que j'ai envoyé un message de confirmation après l'inscription et que je ne peux pas me connecter tel quel. Si vous n'incluez pas cette fonction, vous serez connecté immédiatement après votre inscription.

7 Je souhaite pouvoir m'inscrire immédiatement pour l'authentification SNS sans passer par un e-mail d'enregistrement temporaire.

app/model/user.rb


class User < ActiveRecord::Base
  # ...

  def self.find_for_oauth(auth)
    user = User.where(uid: auth.uid, provider: auth.provider).first

    unless user
      user = User.create(
        uid:      auth.uid,
        provider: auth.provider,
        email:    User.dummy_email(auth),
        password: Devise.friendly_token[0, 20]
      )
    end
######Ajoute ça!######
user.skip_confirmation!
#######################
    user
  end

  private

  def self.dummy_email(auth)
    "#{auth.uid}-#{auth.provider}@example.com"
  end
end

8 J'en ai assez qu'on me demande un mot de passe chaque fois que je modifie les informations d'un utilisateur

8.1 Modifier routes.rb

routes.rb


devise_for :users, controllers: {  }

Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks', 
                                         registrations: 'users/registrations' }
  root 'pages#index'
  get 'pages/show'
  (réduction)...
end

8.2 Remplacer la méthode update_resource

registrations_controller.rb


class RegistrationsController < Devise::RegistrationsController

  protected
  #Ajouter
  def update_resource(resource, params)
    resource.update_without_password(params)
  end
end

8.3 Supprimer le formulaire current_password

erb:views/devise/registrations/edit.html.erb


<div class="field">
    <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
    <%= f.password_field :current_password, autocomplete: "current-password" %>
</div>

Supprimons ce formulaire.

Vous pouvez maintenant saisir vos informations d'enregistrement d'utilisateur sans avoir à saisir votre mot de passe Il est désormais possible de modifier!

9 Liste des documents pour ce que vous voulez faire

** En plus de la fonction d'authentification utilisateur de base, créez un mécanisme qui permet l'enregistrement en un clic avec l'authentification SNS. ** ** [* Rails *] Comment utiliser l'appareil (version rails5) Procédure pour implémenter l'authentification des utilisateurs avec Devise + OmniAuth in Rails

** Je souhaite utiliser des variables d'environnement pour masquer la clé API et la pousser à distance (je ne veux pas coder en dur App Secret, etc.) ** [Rails] Gérons les variables d'environnement en comprenant comment installer et utiliser dotenv-rails! Paramètres des variables d'environnement

** Je souhaite apporter l'e-mail enregistré sur Twitter ou Facebook à la base de données au lieu du mannequin (cela prend environ 3 jours) ** Omniauth-Get email information on twitter Essayez d'utiliser twitter oauth (obtenez également un e-mail) Essayez d'utiliser oauth sur facebook (obtenez également un e-mail) Problèmes et contre-mesures pour ne pas pouvoir obtenir une adresse e-mail avec l'authentification Facebook après le 9 juillet 2015

** Je souhaite pouvoir m'inscrire immédiatement sans utiliser d'e-mail d'enregistrement temporaire pour m'authentifier à l'aide de sites externes tels que Twitter, Google et Github ** Les enregistrements ne sont pas stockés même si l'authentification twitter omniauth est terminée dans Devise Ignorer la vérification et la transmission des e-mails lors de la connexion pour concevoir Twitter [Rails5] Implémentation qui permet l'enregistrement et la connexion sans adresse e-mail par authentification SNS

** Je veux traduire un devise en japonais avec i18n ** Localisation japonaise avec i18n

** J'en ai assez d'être invité à saisir un mot de passe chaque fois que je modifie les informations d'un utilisateur ** [Devise] Modifier les informations utilisateur sans entrer de mot de passe

** Inscrivez-vous en tant qu'utilisateur en utilisant uniquement votre adresse e-mail. ** ** Comment s'enregistrer en tant qu'utilisateur avec un appareil uniquement avec une adresse e-mail et définir un mot de passe ultérieurement How To: Email only sign up

** Comment se connecter avec une adresse autre que e-mail lors de la connexion ** How To: Allow users to sign in with something other than their email address

** Une méthode qui ne nécessite pas de confirmation lors de la mise à jour de l'adresse e-mail (je veux l'ignorer) ** Avez-vous besoin de vérifier les mises à jour d'adresses e-mail avec l'appareil? Ignorer la vérification de l'adresse e-mail dans Devise

** Autre ** [Rails] Que faire si "Unauthorized 403 Forbidden" apparaît dans l'authentification Twitter du devise concevoir la documentation

Recommended Posts

Je souhaite authentifier les utilisateurs auprès de Rails avec Devise + OmniAuth
Je veux jouer avec Firestore de Rails
[Rails] Je veux charger du CSS avec webpacker
Je veux pousser une application créée avec Rails 6 vers GitHub
J'étais accro à la configuration de default_url_options avec l'introduction de la conception de Rails
Je souhaite envoyer manuellement un e-mail d'autorisation avec Devise
Je souhaite ajouter une fonction de navigation avec ruby on rails
Je souhaite utiliser DBViewer avec Eclipse 2018-12! !!
Je veux ajouter un appareil dans Rails, mais je ne peux pas grouper l'installation
[Rails] Je souhaite ajouter des données aux paramètres lors de la transition avec link_to
Je veux introduire un comité avec des rails sans devenir trop sale
Je veux utiliser java8 forEach avec index
Je souhaite effectuer un traitement d'agrégation avec spring-batch
Manipuler le dispositif avec des rails
Je souhaite pouvoir lire des fichiers en utilisant refile avec administrate [rails6]
Rails6 Je veux créer un tableau de valeurs avec une case à cocher
[Rails] Je veux tester avec RSpec. Nous soutenons votre démarche [Procédure d'introduction]
Je veux utiliser une petite icône dans Rails
Je souhaite utiliser le mode sombre avec l'application SWT
Je souhaite surveiller un fichier spécifique avec WatchService
Je souhaite définir une fonction dans la console Rails
Je veux faire des transitions d'écran avec kotlin et java!
Je veux accéder à l'API avec Rails sur plusieurs docker-composes configurés localement
Je veux convertir des caractères ...
[Rails] Ajouter une colonne à concevoir
[Rails] [bootstrap] Je souhaite modifier la taille de la police de manière réactive
[Rails] J'ai essayé de créer une mini application avec FullCalendar
Je veux faire une liste avec kotlin et java!
Je veux créer une fonction avec kotlin et java!
Je souhaite créer un formulaire pour sélectionner la catégorie [Rails]
[Rails] J'ai essayé d'implémenter le traitement par lots avec la tâche Rake
Même en Java, je veux afficher true avec un == 1 && a == 2 && a == 3
Je veux implémenter diverses fonctions avec kotlin et java!
Je veux passer la commande de démarrage à postgres avec docker-compose.
[Java] Je souhaite tester l'entrée standard et la sortie standard avec JUnit
Après avoir publié un article avec Rails Simple Calendar, je souhaite le refléter dans le calendrier.
[Rails] Comment utiliser la "devise" des gemmes
[Rails] Comment utiliser l'appareil (Remarque)
Je veux créer un bouton avec un saut de ligne avec link_to [Note]
Je veux connecter un casque SONY WH-1000XM4 avec LDAC avec ubuntu 20.04! !!
Je veux accrocher la génération / ouverture d'un fichier journal avec log4j # FileAppender
Je veux revenir à l'écran précédent avec kotlin et java!
Je veux INSÉRER l'heure locale du printemps avec l'heure MySQL (également en millisecondes)
Je veux éviter OutOfMemory lors de la sortie de gros fichiers avec POI
J'ai essayé d'implémenter la fonction de prévisualisation d'image avec Rails / jQuery
J'ai essayé d'interagir avec Java
Ce à quoi j'étais accro lors de la mise en œuvre de l'authentification Google avec des rails
[Rails] Ajoutez des paramètres forts pour concevoir
Connectez-vous au serveur Rails avec iPhone