Ruby on Rails Kakao Login API only mode
in Development on Rails
전반적인 설명과 Google Login방법은 Ruby on Rails Google Login API only mode에서 이미 했으니 그것을 참고하길 바란다.
이 글에서는 관련 코드만을 다루겠다.
1. kakao developers에 App 등록
https://developers.kakao.com로 들어가서 애플리케이션 추가하기
을 하여 카카오 로그인
을 활성화 한다. Redirect URI에서 http://localhost:3000/auth/kakao/callback
을 추가한다. 요약정보 탭으로 가서 REST API 키
를 확인한다. 아래에서 필요한 정보이다.
2. Gem Install
Gemfile에 아래 줄을 추가한다.
gem 'omniauth-kakao', git: "https://github.com/DevStarSJ/omniauth-kakao"
omniauth-kakao는 현재 관리되지 않는 gem으로 여겨진다. 그래서 omniauth-oauth2 최신버전을 사용하는 omniauth-google-oauth2와는 같이 사용이 안된다. 그래서 필자가 수정한 DevStarSJ/omniauth-kakao를 사용할 예정이다. 원래 gem에서 어디가 수정되었는지는 이 글 마지막에 설명하겠다.
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
password
는 nullable로 설정하였다. 왜냐면 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 :kakao, ENV['KAKAO_CLIENT_ID'] , {:redirect_path =>'/auth/kakao/callback'}
end
기본 redirect_path는 http://localhost:3000/kakao/oauth
이다. 다른 Social Login과의 URL 통일성을 위해서 수정하였다.
.env
파일에 위에서 확인한 REST API 키
를 KAKAO_CLIENT_ID
로 등록한다. 참고로 .env
파일을 적용하려면 dotenv-rails를 설치해야 한다.
4. Route 선언
routes.rb
파일에 아래 내용을 추가한다.
get 'auth/kakao/callback', to: 'auth#kakao'
5. Controller, Service 선언
auth_controller.rb
파일을 생성하여 아래와 같이 입력한다.
class AuthController < ApplicationController
def kakao
user = SocialAuthService.kakao(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.naver(params)
apply(params, 'kakao')
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/kakao 를 Browser에서 실행하면 서버를 실행한 로그에 각 Model이 생성되는 SQL문을 볼 수 있으며, 화면에도 새로 생성된 사용자 정보를 볼 수 있다. 참고로 request.env['omniauth.auth']
정보를 확인해보고 싶다면 AuthController.kakao
의 내용을 render json: omniauth_params
로 수정을 하던지, 아니면 해당 method 안에서 binding.pry
를 걸어서 확인해보면 된다.
아래의 모양으로 되어 있다.
{
"provider"=>"kakao",
"uid"=>"1234567890",
"info"=>
{
"name"=>"Jayden",
"image"=>"http://k.kakaocdn.net/dn/3eMbq/btqG7q3ZMrg/gkloh4aIRKGzwgZQL3V3D0/img_110x110.jpg",
"profile_needs_agreement"=>false,
"has_email"=>true,
"email_needs_agreement"=>false,
"is_email_valid"=>true,
"is_email_verified"=>true,
"email"=>"seokjoon.yun@gmail.com",
"has_birthday"=>true,
"birthday_needs_agreement"=>false,
"birthday"=>"0726",
"birthday_type"=>"SOLAR",
"has_gender"=>true,
"gender_needs_agreement"=>false,
"gender"=>"male"
},
"credentials"=>
{
"token"=>"xcxcxcxcxcxcxcxcxcxcxcxcxcxc",
"refresh_token"=>"XCXCXCXCXCXCXXC",
"expires_at"=>1606485271,
"expires"=>true
}
}
7. 수정한 omniauth-kakao 정보
7.1 omniauth-oauth2 버전 Upgrade
원본 gem인 omniauth-kakao는 omniauth-oauth2 1.3에서 정상동작하게 되어 있다. 하지만 다른 Social Login들이 대부분 1.6이상을 사용하도록 되어 있는데, 그 둘이 호환이 되지 않아서 같이 사용 할 수가 없다. 그래서 그 부분을 수정하였다.
omniauth-kakao.gemspec 파일에서 1.7.0 이상으로 설정하였다.
s.add_dependency 'omniauth-oauth2', '~> 1.7.0'
이렇게만 수정하면 redirect_uri_mismatch
오류가 계속 발생하는데, 그걸 해결하기 위해서 lib/omniauth/strategies/kakao.rb에 다음 method를 추가한다.
def callback_url
if @authorization_code_from_signed_request_in_cookie
''
else
options[:callback_url] || (full_host + script_name + callback_path)
end
end
그러면 이제 정상동작했으면 좋겠지만, 아직 오류가 난다.
7.2 Kakao Profile API Upgrade 및 email 정보 추가
원래 https://kapi.kakao.com/v1/user/me
API를 통해서 profile 정보를 가져왔는데 이젠 더 이상 제공하지 않는 API이다. https://kapi.kakao.com/v2/user/me
로 수정해야 한다. raw_info
를 아래와 같이 수정한다.
def raw_info
@raw_info ||= access_token.get('https://kapi.kakao.com/v2/user/me', {}).parsed || {}
end
이제는 실행하면 정상동작한다. 기존에는 제공해주지 않던 email 정보도 제공을 해주기 때문에 그걸 request.env['omniauth.auth']
에서 활용하려면 한 곳을 더 수정해야 한다. raw_info
의 kakao_acount
정보를 모두 내려주도록 수정하였다. info do ~ end
부분을 아래와 같이 수정하였으며,
info do
{
'name' => raw_properties['nickname'],
'image' => raw_properties['thumbnail_image'],
}.merge(kakao_account)
end
kakao_acount
를 추가하였다.
def kakao_account
@kakao_account ||= raw_info['kakao_account'].except('profile')
end
이렇게 수정해주면 이제 위에서 적어놓은 내용들이 request.env['omniauth.auth']
에 포함되어진다.
마치며…
위에서 소개한 방법을 적용한 예제코드는 아래 Link에서 확인이 가능하다.
https://github.com/DevStarSJ/backend_boilerplates/tree/master/rails
https://github.com/DevStarSJ/omniauth-kakao
이로서 Kakao Login
에 대한 안내는 마치겠다.
다른 Social Login의 방법은 아래에서 확인이 가능하다.
- Ruby on Rails Google Login API only mode
- Ruby on Rails Facebook Login API only mode
- Ruby on Rails Naver Login API only mode
- Ruby on Rails Kakao Login API only mode
- Ruby on Rails Line Login API only mode
이 글이 도움이 되셨다면 공감 및 광고 클릭을 부탁드립니다 :)