はじめに
こんにちは!エンジニアインターンをしている湯村です。
今回、社内向け管理ツールにGoogleログインを導入したので、その話をしたいと思います。
タスクの背景
現在crispyでは、SlackやKibelaなどのツールごとにメンバーのアカウントを作成しています。
社内向け管理ツールも同様に、管理ツール用に作成したアカウントのメールアドレスとパスワードでログインしていました。
現状はそれでも問題ないのですが、今後どんどんメンバーが増えてくると、アカウントの作成・削除をそれぞれのツールで行っていると手続きが煩雑になってしまいます。
そこで、今後はメンバーのアカウントをGoogle Workspaceで一元管理し、作業を簡略化しようと考えています。
その一環として、今回は社内向け管理ツールにGoogleアカウントでログインできるように実装を行いました。
OAuth2.0
Googleログインに限らず、FacebookやTwitterなど、ソーシャルアカウントでのログインにはOAuth(オーオース)という仕組みが使われていることが多いです。
現在のバージョンはOAuth2.0です。
ソーシャルログインでは、クライアントアプリケーション(今回の場合、管理ツール)がAPIを叩いてリソースサーバー(今回の場合、Google)にアクセスし、取得したユーザーのデータを使ってクライアントアプリケーションにログインしています。
この際、APIさえ叩けば誰でもユーザーのデータが取得できる、という状態だと、悪意のあるアプリケーションがユーザーの個人情報を取得してしまう恐れがあるので、そのような事態を回避するために、アクセストークンが使われています。
Googleログインをする際、「続行するにあたり、Googleはあなたの名前、メールアドレス、言語設定、プロフィール写真を(アプリケーション名)と共有します。」という画面が出るのを見たことがあると思います。
ここでアクセスを許可すると、アプリケーションにアクセストークンが付与され、そのアクセストークンを持った状態でAPIを叩くとGoogleアカウントのユーザーデータが参照できるという仕組みになっています。
この、「アクセストークンの要求とそれに対する応答」を標準化したものがOAuth2.0です。
実装した内容
それではいよいよ実装した内容について説明していきます。
crispyの社内向け管理ツールではRailsを使用しているので、今回はomniauth-google-oauth2というgemを使用し、基本的にこちらのREADMEに従ってGCPの設定とアプリケーションのコードの追加を行いました。
github.com
GCPの設定
アプリケーションからGoogleログインのAPIを叩くことができるようにするために、GCPの設定を行います。
「APIとサービス」から「OAuth同意画面」と「認証情報」の二項目を設定します。
OAuth同意画面
アプリケーションがOAuthを使用するために必要な情報を登録します。
アプリケーション名や連絡先メールアドレスなどの必須項目を入力してください。
認証情報
認証情報を作成し、クライアントIDとクライアントシークレットを発行します。
ここで発行したIDとシークレットは、後ほどAPIが叩けるように実装をする際に必要となります。
アプリケーション側の実装
元々deviseを使用してログイン機能を実装していたので、そこに追記する形で実装していきました。
設定ファイルを記述
deviseのOmniauthableモジュールを使うと簡単に書くことができるのですが、今回は既に別のモデルでOmniauthableモジュールを使用していたため使用することができませんでした。
代わりにconfig/initializers/omniauth.rb
というファイルを新しく作成し、そこに設定を記述しました。
Rails.application.config.middleware.use(OmniAuth::Builder) do provider( :google_oauth2, Rails.application.secrets.dig(:google, :client_id), Rails.application.secrets.dig(:google, :client_secret), ) end
client_id
とclient_secret
には、先ほどGCPで発行されたものを設定します。
ルーティングを追加
既にログイン/ログアウトのルーティングは定義済みだったため、omniauthのコールバックのルーティングのみ追加しました。
get 'auth/google_oauth2/callback', to: 'sessions#google_oauth'
コントローラとモデルにメソッドを追加
こちらもログイン/ログアウトのメソッドは存在するため、oauthのためのメソッドのみ追加します。
# コントローラ def google_oauth access_token = request.env['omniauth.auth'] @user = User.from_omniauth(access_token) if @user&.persisted? sign_in_and_redirect(@user, event: :authentication) else session['devise.google_data'] = access_token.except('extra') # NOTE: Removing extra as it can overflow some session stores redirect_to new_session_path, alert: @user.errors.full_messages.join("\n") end end
# モデル class << self def from_omniauth(access_token) data = access_token.info User.find_by!(email: data['email']) end end
あとはviewを整えて、実装完了です!
まとめ
Googleログインはgemを使うと簡単に実装できて便利なので、ぜひ導入を検討してみてください。
crispyでは、インターン生でも社員と変わらず幅広いタスクを任せてもらえます!
社内向け管理ツールの機能開発・改善だけではなく、アプリで使用するAPIの実装や、インフラ関連のタスクを行うこともあります。
開発未経験でも丁寧に教えていただけるので、安心して開発に取り組めます。
エンジニアとして成長するにはとてもいい環境だと思います!
Wantedlyで正社員・インターン共に募集しているので、覗いてみてください!