Ruby on Rails Facebook Login API only mode


전반적인 설명과 Google Login방법은 Ruby on Rails Google Login API only mode에서 이미 했으니 그것을 참고하길 바란다.

이 글에서는 관련 코드만을 다루겠다.

1. FACEBOOK for Developers에 App 등록

https://developers.facebook.com로 들어가서 Facebook Login App을 생성한다. Client OAuth Login, Web OAuth LoginYes로 설정한다. In development 상태를 On하면 다른 설정들은 특별히 없어도 정상동작한다. App IDApp Secret을 확인한다. 아래에서 필요한 정보이다.

2. Gem Install

Gemfile에 아래 줄을 추가한다.

gem 'omniauth-facebook'

Bundle을 실행하여 Install을 한다.

bundle install

2. Model 생성

필자의 경우 User Model과 SocialAuth Model을 분리하였다. 왜냐면 1명의 User에게 여러 Social Login을 가능하게 하기 위해서이다.

2.1 User Model 생성

rails g model User 를 실행하여 Migration 파일을 수정한다.

class CreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      t.string :email, null: false
      t.string :password_digest

      t.timestamps
    end
  end
end

passwordnullable로 설정하였다. 왜냐면 password가 없는 경우 Social Login만을 허용하기 위해서다. 하지만 Model에서 Null Check를 하므로 validation을 하지 않는 것으로 선언해야 한다.

  • user.rb
    class User < ApplicationRecord
    include ActiveModel::SecurePassword
    has_secure_password validations: false
    end
    

rails db:migrate 를 실행하여 Model을 생성한다.

2.2 SocialAuth Model 생성

rails g model SocialAuth를 실행하여 Migration 파일을 생성 후

class CreateSocialAuths < ActiveRecord::Migration[6.0]
  def change
    create_table :social_auths do |t|
      t.string :provider, null: false
      t.string :uid, null: false
      t.string :first_name
      t.string :last_name
      t.string :email
      t.string :photo
      t.references :user, null: false, foreign_key: false

      t.timestamps
    end
  end
end

위 내용과 같이 수정한다.

  • social_auth.rb
    class SocialAuth < ApplicationRecord
    belongs_to :user
    end
    

Model 파일을 수정한 뒤 rails db:migrate 를 실행하여 Model을 생성한다.

3. Initialize 선언

config/initializers/omniauth.rb 파일을 생성하여 아래와 같이 입력한다.

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET']
end

.env 파일에 위에서 확인한 App IDApp Secret를 각각 FACEBOOK_APP_IDFACEBOOK_APP_SECRET로 등록한다. 참고로 .env파일을 적용하려면 dotenv-rails를 설치해야 한다.

4. Route 선언

routes.rb파일에 아래 내용을 추가한다.

 get 'auth/facebook/callback', to: 'auth#facebook'

5. Controller, Service 선언

auth_controller.rb 파일을 생성하여 아래와 같이 입력한다.

class AuthController < ApplicationController
  def facebook
    user = SocialAuthService.facebook(omniauth_params)
    render json: user
  end

  private
  def omniauth_params
    request.env['omniauth.auth'].except('extra').to_h
  end
end

참고로 인증받은 구글에서의 profile정보는 request.env['omniauth.auth']에서 확인이 가능하다. 예제에서는 User Model을 그대로 response해주는 것으로 해 놓았다. 실제 사용할때는 생성되거나 찾은 사용자 정보에서 JWT Token등을 생성해서 전달해 준다던지, request.env['omniauth.auth']안에 있는 token을 그대로 사용하는 방법이 있겠다.

social_auth_service.rb 파일을 생성하여 아래와 같이 입력한다.

class SocialAuthService
  def self.facebook(params)
    apply(params, 'facebook')
  end

  def self.apply(params, provider)
    return nil unless params["provider"].present? && params["uid"].present? && params["info"].present?
    return nil unless params["provider"].include?(provider)

    social_auth = initialize(params, provider)
    social_auth.user
  end

  def self.initialize(params, provider)
    SocialAuth.where(provider: provider, uid: params["uid"]).first_or_create do |auth|
      auth.provider = provider
      auth.uid = params["uid"]
      auth.email = params["info"]["email"]
      auth.first_name = params["info"]["first_name"] ||  params["info"]["name"]
      auth.last_name = params["info"]["last_name"]
      auth.photo = params["info"]["image"]
  
      link_user(auth)
    end
  end

  def self.link_user(auth)
    return if auth.user_id.present?

    user = User.find_by(email: auth.email)
    user = User.create(email: auth.email) if user.blank?
    auth.user = user
  end
end

.first_or_create는 앞에 조건에 만족하는 첫번째 instance를 반환하거나 없다면 block에 선언한대로 새로 생성을 한다. 여기서 찾거나 새로 생성한 SocialAuth에서 전달받은 email정보를 가지고 User를 검색한 후, 있으면 그 User와 연결을 하고 없다면 User를 새로 생성한다. 이 부분 역시 .first_or_create를 사용해도 된다.

6. 실행 및 확인

이제 서버를 실행해서 확인해보자.

rails s

로 서버를 실행한 다음 http://localhost:3000/auth/facebook 를 Browser에서 실행하면 서버를 실행한 로그에 각 Model이 생성되는 SQL문을 볼 수 있으며, 화면에도 새로 생성된 사용자 정보를 볼 수 있다. 참고로 request.env['omniauth.auth'] 정보를 확인해보고 싶다면 AuthController.facebook의 내용을 render json: omniauth_params로 수정을 하던지, 아니면 해당 method 안에서 binding.pry를 걸어서 확인해보면 된다.

아래의 모양으로 되어 있다.

{
  "provider"=>"facebook",
  "uid"=>"1234567890",
  "info"=>
  {
    "email"=>"seokjoon.yun@gmail.com",
    "name"=>"Seok-joon Yun",
    "image"=>"http://graph.facebook.com/v4.0/4368718413198581/picture"
  },
  "credentials"=>
  {
    "token"=>"xxxx.xxxxxxxxcxcxcxcxcxcxcxcxcxcxcxcxxcxc",
    "expires_at"=>1611636890,
    "expires"=>true
  }
}

마치며…

위에서 소개한 방법을 적용한 예제코드는 아래 Link에서 확인이 가능하다.

https://github.com/DevStarSJ/backend_boilerplates/tree/master/rails

이로서 Facebook Login에 대한 안내는 마치겠다.

다른 Social Login의 방법은 아래에서 확인이 가능하다.


이 글이 도움이 되셨다면 공감 및 광고 클릭을 부탁드립니다 :)