[RUBY] [Rails 6] Enregistrez-vous et connectez-vous avec l'authentification Devise + SNS (plusieurs liens sont autorisés)

introduction

Créez une authentification pouvant être liée à plusieurs SNS. Devise continuera comme implémenté. Nous ne parlerons pas de l'acquisition de chaque clé API, veuillez donc vérifier en conséquence. Cette fois, nous allons l'implémenter sur Facebook et Twitter, mais je pense que c'est fondamentalement la même chose pour les autres SNS.

environnement

environnement


Windows10
ruby 2.6.6
Rails 6.0.3.1

Préparation

gemme ajoutée

Gemfile


gem 'omniauth'
gem 'omniauth-facebook'
gem 'omniauth-twitter'

Veuillez regrouper l'installation après l'enregistrement.

Écrivez la clé API dans credentials.yml

Pour Windows, veuillez vous reporter à Article précédent.

credentials.yml



facebook:
  api_key: pk_test_~
  secret_key: sk_test_~
twitter:
  api_key: pk_test_~
  secret_key: sk_test_~
Concevoir les paramètres

Dans config / initializer.

devise.rb


#Ajoutez ce qui suit
config.omniauth :facebook, Rails.application.credentials.facebook[:api_key], Rails.application.credentials.facebook[:secret_key], scope: 'email', info_fields: 'email,name'
config.omniauth :twitter, Rails.application.credentials.twitter[:api_key], Rails.application.credentials.twitter[:secret_key], scope: 'email', callback_url: 'https://localhost:3000/users/auth/twitter/callback'

Il semble que Twitter ait besoin de spécifier l'URL de rappel.

Créer un modèle social

Cette fois, on suppose que le modèle User a déjà été créé dans Devise. Vous pouvez ajouter des colonnes au modèle User, mais cette fois nous allons créer un nouveau modèle Social lié au modèle User. (Le modèle utilisateur et le modèle social ont une relation un-à-plusieurs.)

console


rails g model social

Le modèle social doit avoir user_id, provider (qui contient «facebook», «twitter», etc.) et uid (qui contient l'id à associer à chaque compte SNS).

2020~create_socials.rb


class CreateSocials < ActiveRecord::Migration[6.0]
  def change
    create_table :socials do |t|
      t.references :user, null: false, foreign_key: true
      t.string :provider, null: false
      t.string :uid, null: false
      t.timestamps
    end
  end
end

Après l'enregistrement, rails db: migrate.

Association

user.rb


has_many :socials, dependent: :destroy#ajouter à
devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, 
          :omniauthable#ajouter à

social.rb


belongs_to :user
validates :uid, uniqueness: {scope: :provider}#Empêcher les enregistrements multiples chez le même fournisseur

Empêchez le même compte SNS d'être lié à plusieurs utilisateurs. Je pense que ce n'est pas grave si vous n'avez pas "{scope :: provider}", mais juste au cas où.

la mise en oeuvre

Créer un processus de rappel

routes.rb


devise_for :users, controllers: {
  sessions: 'users/sessions',
  password: 'users/password',
  registrations: 'users/registrations',
  omniauth_callbacks: 'users/omniauth_callbacks'#ajouter à
  }

Ci-dessous dans app / controllers / users / omniauth_callbacks_controller.rb. (Vérifiez avec les itinéraires ferroviaires, etc. et définissez la méthode pour chaque destination de redirection.)

omniauth_callbacks_controller.rb


class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

 def facebook
    if request.env['omniauth.auth'].info.email.blank?#Autorisez-vous les e-mails sur Facebook?
      redirect_to '/users/auth/facebook?auth_type=rerequest&scope=email'
    end
    callback_from :facebook
  end

  def twitter
    callback_from :twitter
  end


  private

  def callback_from(provider)
    provider = provider.to_s

    if user_signed_in?
      @user = current_user
      User.attach_social(request.env['omniauth.auth'], @user.id)#Joindre plus tard_marque sociale. Transmettez les informations de SNS et l'identifiant de l'utilisateur connecté.
    else
      @user = User.find_omniauth(request.env['omniauth.auth'])#Trouver plus tard_Faites omniauth. Transmettez les informations de SNS.
    end

    if @user.persisted?#Enregistré ou si vous pouvez vous inscrire
      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

Passez le type de SNS de la source de redirection à "callback_from" et isolez-le. Dans "callback_from", "l'enregistrement d'un nouvel utilisateur par authentification SNS ou connexion de l'utilisateur authentifié SNS" ou "Coopération SNS de l'utilisateur connecté" a été séparé. Les traitements «après enregistrement», «après connexion» et «après coopération» ne sont pas divisés cette fois, mais tous sont redirigés vers la page utilisateur.

Ensuite, écrivez chaque processus dans User.rb.

user.rb


 def self.find_omniauth(auth)#Nouvel enregistrement ou connexion SNS avec authentification SNS
    social = Social.where(uid: auth.uid, provider: auth.provider).first
    unless social.blank?#certifié sns(S'identifier)
      user = User.find(social.user.id)
    else#Nouvel enregistrement avec authentification SNS
      temp_pass = Devise.friendly_token[0,20]#Cette fois, je vais créer un mot de passe aléatoire pour le moment
      user = User.create!(
        username: auth.info.name,
        email: auth.info.email,
        password: temp_pass,
        password_confirmation: temp_pass,
      )
      social = Social.create!(
        user_id: user.id,
        provider: auth.provider,
        uid: auth.uid,
      )
    end

    return user
 end

 def self.attach_social(auth, user_id)#Lors de l'ajout d'une liaison sns
    social = Social.create!(
      user_id: user_id,
      provider: auth.provider,
      uid: auth.uid,
    )
  end

Au moment de «l'enregistrement d'un nouvel utilisateur par authentification SNS ou connexion d'un utilisateur authentifié SNS», il est en outre divisé en «nouvel enregistrement» et «connexion». Au moment de la "nouvelle inscription", l'utilisateur et le social sont créés (en même temps, l'utilisateur et le social sont liés), et l'utilisateur est renvoyé. Au moment de la "connexion", Social est recherché à partir des informations (auth.uid et auth.provider) envoyées par SNS, et l'utilisateur associé est renvoyé. Seul Social est créé au moment du "lien SNS de l'utilisateur connecté". Il reçoit user_id à associer à l'utilisateur connecté.

C'est la fin du processus. Après cela, si vous créez un lien avec "user_facebook_omniauth_authorize_path" etc., une nouvelle inscription, une nouvelle connexion et une coopération seront effectuées en fonction de la situation de l'utilisateur.

La fin

En fait, je pense qu'il serait préférable d'avoir un lien vers le SNS lié, un mécanisme de réinitialisation du mot de passe lors de la nouvelle inscription sur le SNS, l'authentification mail de Devise, un bouton pour annuler le lien, etc., mais pour le moment la configuration minimale vient de le faire. J'étudie les rails, donc je pense qu'il y a beaucoup d'endroits qui ne sont pas intelligents. Si vous faites quelque chose d'étrange, faites-le moi savoir!

Recommended Posts

[Rails 6] Enregistrez-vous et connectez-vous avec l'authentification Devise + SNS (plusieurs liens sont autorisés)
[Ruby on Rails] Comment se connecter avec seulement votre nom et mot de passe en utilisant le bijou
Créer une fonction d'authentification dans l'application Rails à l'aide de devise
Créer une API de tableau d'affichage avec autorisation dans Rails 6 # 12 Association d'utilisateur et de publication
Agrégation et analyse de journaux (utilisation d'AWS Athena en Java)
[Rails] Recherche à partir de plusieurs colonnes + conditions avec Gem et ransack
[rails] Problèmes qui ne peuvent pas être enregistrés / connectés avec l'appareil
Implémentez la fonction de connexion simplement avec le nom et le mot de passe dans Rails (3)
Implémenter la fonction d'enregistrement des utilisateurs et la fonction d'enregistrement de l'entreprise séparément dans Rails concevoir
[Rails] Obtenez access_token au moment de l'authentification Twitter avec Sorcery et enregistrez-le dans la base de données
Créer une API de tableau d'affichage avec autorisation de certification dans Rails 6 # 11 Test et validation du modèle utilisateur ajoutés
Japaneseize en utilisant i18n avec Rails
Implémenter l'authentification LTI dans Rails
Utilisez plusieurs bases de données avec Rails 6.0
Utilisez plusieurs cases à cocher dans Rails6!