티스토리 뷰

오늘은 소셜로그인에 대해 알아보도록 합시다.


많은 사이트에서 'OOO'로 로그인하기 라는 버튼을 보신적 있으신가요?

실제로 많은 사이트들이 SNS를 통해서 로그인하는 기능을 사용하고 있습니다.

그중에서 오늘은 Omniauth Gem을 활용한 페이스북구글 계정을 통해서 로그인하는 방법에 대해 배워봅시다.




먼저 Omniauth Gem에 대해 간단하게 알아볼까요?

Omniauth Gem : 웹어플리케이션에서 다양한 인증제공서비스를 사용할 수 있게 해주는 라이브러리


1. Facebook 로그인 버튼 클릭

2. Facebook 인증창으로 연결되어 로그인 기능 실행

3. Facebook은 우리에게 Access Token을 제공

4. 이 Token을 통해 사용자의 정보 (이름, 이메일, 프로필 사진 등)를 제공 받는다.


이 순서대로 실행이 되는데요, 그럼 직접 Gem을 사용해보도록 합시다.



[Gem  설치]


설치할 gem들을 입력해주세요.

1
2
3
4
gem 'devise'
gem 'omniauth'
gem 'omniauth-facebook'
gem 'omniauth-google-oauth2'

cs


bash창에 입력해서 gemfile들을 설치해줍시다.

1
2
bundle install

cs


 로그인 하기전 화면과 로그인 후의 화면을 구현하기 위해 두 개의 Controller를 만들어줍시다.

(bash창에 입력)

1
2
rails g controller home index
rails g controller register info

cs


home/index 

로그인 하기 전 초기 화면 

register/info 

로그인 후 화면 


(컨트롤러 이름은 원하는대로 작성해주세요 :) )

** 루트 설정 꼭 해주기!


[Devise 설정]


이제 Devise 설정을 해봅시다.


1
2
rails generate devise:install
rails generate devise user

cs


user모델에 devise가 제공하는 기능들에 대한 파일을 만들어줍니다.


1
2
rails generate devise:views
rails generate devise:controllers user

cs


위 코드를 통해 컨트롤러와 뷰를 Devise에 맞게 만들어주는 명령어입니다.

로그인 페이지, 회원가입 페이지를 수정할 수 있어요! (나중에 수정할거에요!)


1
2
3
rails g migration add_columns_to_users profile_img:string
rails g model identity user:references provider:string uid:string
rake db:migrate

cs


user모델에 칼럼을 추가해보아요.

추가할 수 있는 칼럼에 대한 정보는 Auto-hash Schema를 확인해보세요

https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema


user는 여러 경로의 소셜로그인을 통해 들어올 수 있으므로 각각 소셜 로그인 정보를 DB에 저장해야합니다. 한 명의 유저가 Facebook으로 로그인 할 수 도 있고 Google로도 로그인 할 수 있죠. 그래서 identity 라는 모델을 새로 만들어주세요. identity모델은 user모델과 belongs_to 관계로 설정하고 소셜 로그인 정보 (provider, uid)를 저장합니다.


마이그레이션은 필수!



[Config 설정]


1
#config/routes.rb

devise_for :users, :controllers => { omniauth_callbacks: ‘user/omniauth_callbacks’}

cs


모델과 컨트롤러가 제대로 작동하도록 설정해줍시다.


* 잠깐! Callback이란?

사용자: 이런 동작을 수행하겠다.

컴퓨터: 동작이 수행되었다. (Callback)



[API Key 설정]


1
2
3
4
#config/initializers/devise.rb
 
config.omniauth :facebook, ENV["Facebook_Key"], ENV["Facebook_Secret"]
config.omniauth :google_oauth2, ENV["Google_Key"], ENV["Google_Secret"]

cs


우리는 소셜로그인 서비스를 사용하기 위해, 각 provider의 developer사이트에 가서 발급을 받아야합니다. 발급 받은 키를 직접 devise.rb 파일에 직접 써도 되지만, 보안상의 문제가 생길 수 있으므로 환경변수 (ENV["~"])를 사용하겠습니다. 이를 사용할 수 있도록 하는 gem이 바로 'figaro'입니다.


일단 먼저 Key부터 발급 받아볼까요?



[API Key 발급]

* Facebook

1. developers.facebook.com 접속 후 페이스북 아이디로 로그인

2. 내 앱 > 새 앱 추가 > app 이름 적어주고 앱 ID 만들기 클릭!

3. 제품 추가 > Facebook 로그인 > 플랫폼: 선택

4. 유효한 Oauth 리디렉션 URI에 프로젝트 실행 주소 적어주기

5. 앱 ID, 앱 시크릿 코드 발급 완료!


* Google

1. console.developers.google.com 접속 후 google아이디로 로그인

2. Credentials > Create Credentials > Oauth client ID > Web Application

3. Name적고 프로젝트 실행 주소/users/auth/google_oauth2/callback 적어주기

4. Dashboard > +ENABLE API > Google+ 검색 후 ENABLE 누르기



[Gem Figaro 설치]


* Figaro란?


config에 applicaiton.yml파일을 생성하여 이것을 git에 업데이트 되지 않도록 하는 gem입니다.

git에 키가 노출된다면 보안상 문제가 생기겠죠?


1
#Gemfile
gem 'figaro'

cs


1
bundle install
bundle exec figaro install
cs


1
2
3
4
5
6
# config/application.yml
 
Facebook_Key: "실제 발급 받은 키"
Facebook_Secret: "실제 발급 받은 비밀번호"
Google_Key: "실제 발급 받은 키"
Google_Secret: "실제 발급 받은 비밀번호"
cs

위에서 발급받은 키를 적어주면 완료!


[Model 설정]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# app/models/user.rb
 
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :omniauthable
  
  def self.find_for_oauth(auth, signed_in_resource = nil)
    # user와 identity가 nil이 아니라면 받는다
    identity = Identity.find_for_oauth(auth)
    user = signed_in_resource ? signed_in_resource : identity.user
 
    # user가 nil이라면 새로 만든다.
    if user.nil?
      # 이미 있는 이메일인지 확인한다.
      email = auth.info.email
      user = User.where(:email => email).first
      unless self.where(email: auth.info.email).exists?
        # 없다면 새로운 데이터를 생성한다.
        if user.nil?
          user = User.new(
            email: auth.info.email,
            profile_img: auth.info.image,
            password: Devise.friendly_token[0,20]
          )
          user.save!
        end
      end
    end
 
    if identity.user != user
      identity.user = user
      identity.save!
    end
    user
  end
 
  # email이 없어도 가입이 되도록 설정
 
  def email_required?
    false
  end
  
end
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
# app/models/identity.rb
 
class Identity < ActiveRecord::Base
  belongs_to :user
  validates_presence_of :uid, :provider
  validates_uniqueness_of :uid, :scope => :provider
 
  def self.find_for_oauth(auth)
    find_or_create_by(uid: auth.uid, provider: auth.provider)
  end
  
end
 


1. devise 역할에 :omniauthable을 추가해주세요. 

2. self.find_for_oauth 함수를 정의해봅시다.


회원가입을 누른 사용자가 이미 가입한 유저인가?

- 신규가입자: 유저 정보를 새롭게 생성


이때 유저 정보는 원하는 만큼 받을 수 있습니다. 위에서 설명한 auto-hash를 수정하면, 사용자로부터 받고자하는 정보의 종류를 설정할 수 있습니다. 


* 참고

현재 실습중인 구글과 페이스북은 이메일을 api로 제공하는 서비스입니다.

하지만, 이메일을 api로 제공하지 않는 서비스들과 섞이게 되면 회원을 구분할 방법이 없어지게됩니다.

따라서! 사용하고자하는 서비스의 종류에 따라 코드를 다르게 작성해주어야합니다.


이메일을 api로 제공하는 서비스: facebook, google, naver ...

이메일을 api로 제공하지 않는 서비스: kakao, instagram, line, twitter ...



[Controller 설정]


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# app/controllers/user/omniauth_callback_controller.rb
 
class User::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def self.provides_callback_for(provider)
    class_eval %Q{
      def #{provider}
        @user = User.find_for_oauth(env["omniauth.auth"], current_user)
 
        if @user.persisted?
          sign_in_and_redirect @user, event: :authentication
        else
          session["devise.#{provider}_data"= env["omniauth.auth"]
          redirect_to new_user_registration_url
        end
      end
    }
  end
  
  [:facebook, :google_oauth2].each do |provider|
    provides_callback_for provider
  end
  
  def after_sign_in_path_for(resource)
    auth = request.env['omniauth.auth']
    @identity = Identity.find_for_oauth(auth)
    @user = User.find(current_user.id)
    if @user.persisted?
      register_info_path
    else
      home_index_path
    end
  end
end
 
cs


find_for_oauth 함수를 호출해서 현재 session 데이터와 provider로부터 제공받은 토큰 데이터를 사용하도록 합니다.


after_sign_in_path_for함수를 통해 사용자가 로그인 하고 후의 경로를 설정해줍니다.

처음에 만들었던 home/index와 register/info 기억하시나요?


만약 유저가 유효하다면? -> register/info로

유저가 유효하지않다면?  -> home/index로



[View 설정]


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# app/views/home/index.html.erb
 
<div class="container">
  <h1 style = "margin-top: 40px; text-align: center"> HOME </h1>
  <h1 style = "margin-top: 40px; text-align: center"> 로그인을 해봅시다. </h1>
  <div class="form-group" style="margin-top: 50px; text-align: center">
    <if user_signed_in? %>
      <p> 현재 로그인된 유저의 이메일: <%= current_user.email %> </p>
      <p> <%= link_to "로그아웃", destroy_user_session_path, 
              method: :delete, data: {confirm: "로그아웃 하시겠습니까?"},
              class'btn btn-default' %> </p>
    <else %>
      <p> <%= link_to "로그인", new_user_session_path, class'btn btn-default' %> </p>
    <end %>
  </div>
</div>
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# app/views/register/info.html.erb
 
<div class="container">
  <h1 style = "margin-top: 40px; text-align: center"> LOGIN 로그인 </h1>
  <div class="form-group" style="margin-top: 50px; text-align: center">
    <if user_signed_in? %>
      <p> 현재 로그인된 유저의 이메일: <%= current_user.email %> </p>
      <p> <%= link_to "로그아웃", destroy_user_session_path, 
              method: :delete, data: {confirm: "로그아웃 하시겠습니까?"},
              class'btn btn-default' %> </p>
    <else %>
      <p> <%= link_to "로그인", new_user_session_path, class'btn btn-default' %> </p>
    <end %>
  </div>
</div>
cs


중요한 코드는 바로 6~13번째 코드입니다. 

나머지 css는 알아서 이쁘게 꾸며주세요 :) 


[RUN~]


페이스북과 구글 모두 로그인이 잘 되나요?

그렇다면 성공!



[참고 문헌]


페이스북 omniauth gem에 대해 자세하게 알아볼까요? :)


facebook omniauth gem: https://github.com/mkdynamic/omniauth-facebook


Omniauth gem의 auto hash에 대해 알아보아요 :)


https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema


페이스북과 구글 말고도 여러가지 SNS를 활용해보도록해요 :)


카카오계정으로 로그인 하기: https://hcn1519.github.io/articles/2016-12/omniauth_devise_configuration


회원가입 창을 아직 꾸미지 않았죠? 이쁘게 꾸며보아요 :)


회원가입창 이쁘게 꾸미기: https://semantic-ui.com/introduction/getting-started.html



댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함