2018年10月29日月曜日

Google の OAuth 認証を使ってみた

概要

Google の OAuth2 認証を Ruby アプリを使って実装してみました
アカウントの作り方が少しクセがあるようです

環境

  • macOS 10.14
  • Ruby 2.5.1p57
  • Google OAuth2 (2018/10/29 時点)
  • Google Drive API (2018/10/29 時点)

事前作業

GCP でプロジェクトを作成しておきましょう

Google Drive API の有効化

今回は認証後に Google Drive API をコールしてドライブ内にあるファイルの一覧を取得します
プロジェクトが Google Drive API を有効な状態にしておく必要があるので有効にします
google_oauth6.png

OAuth 認証画面の設定

これを設定しないとクライアント ID を作成できないので先に作成しておきます
設定するのはアプリケーション名だけで OK です
google_oauth2.png

クライアント ID の作成

OAuth 用のクライアント ID を作成します
作成の導線はたくさんあるのでお好きな方法で作成してください
google_oauth1.png

GCP では用途に合わせていろいろな認証情報が作成できます
今回は OAuth なので「OAuth クライアント ID」を選択します

クライアントのタイプを選択する必要があるので「ウェブアプリケーション」を選択しましょう
google_oauth3.png

あと大事なのはコールバック用の URL です
今回は localhost で開発するので http://localhost:9292/redirect と入力しましょう
あとでこのルーティングをアプリ上で実装します

クライアント ID を作成すると client_secret_279273981030-rj9ivjoip1ocvs3f5bh2ldoavk6erums.apps.googleusercontent.com.json というような名前の認証用の JSON ファイルをダウンロードできるようになります
ダウンロードして名前を client_secrets.json に変更しましょう

ライブラリインストール

それではアプリを作成します
まずはライブラリをインストールします

  • bundle init
  • vim Gemfile
gem "sinatra"
gem "google-api-client"
  • bundle install --path vendor

サンプルアプリ

  • vim config.ru
require './app'
run TestWebApp
  • vim app.rb
require 'sinatra/base'
require 'google/api_client/client_secrets'
require 'google/apis/drive_v2'
require 'json'

module Rack
  class Lint
    def call(env = nil)
      @app.call(env)
    end
  end
end

class TestWebApp < Sinatra::Base

  before do
    client_secrets = Google::APIClient::ClientSecrets.load
    @auth_client = client_secrets.to_authorization
  end

  get '/' do
    @auth_client.update!(
      :redirect_uri => 'http://localhost:9292/redirect',
      :scope => 'https://www.googleapis.com/auth/drive.metadata.readonly'
    )
    auth_uri = @auth_client.authorization_uri.to_s
    redirect auth_uri
  end

  get '/redirect' do
    @auth_client.code = request['code']
    @auth_client.fetch_access_token!
    auth_client = Signet::OAuth2::Client.new(JSON.parse(@auth_client.to_json))
    drive = Google::Apis::DriveV2::DriveService.new
    files = drive.list_files(options: { authorization: auth_client })
    "<pre>#{JSON.pretty_generate(files.to_h)}</pre>"
  end
end

説明

ポイントを説明します
before で client_secrets = Google::APIClient::ClientSecrets.load とすることでダウンロードして JSON ファイルを読み込みクライント ID とシークレットを設定します
更にそこからトークンを取得するための @auth_client を作成しておきましょう
今回は before でやっていますがリクエストごとに毎回やる必要はないです

@auto_client.update!redirect_urlscope を設定します
redirect_url は先程クライアント ID 作成時に設定した http://localhost:9292/redirect を設定します
また scope はこのアプリが使用する API を指定します
今回は Google Drive API を使ってドライブの情報を確認するので https://www.googleapis.com/auth/drive.metadata.readonly を指定します
スコープの一覧はこちらを参考にしてください

redirect_uri と scope を指定したら @auth_client.authorization_uri.to_s で認証ページの URI を取得します
あとはこれにリダイレクトします

認証が成功したあとは /redirect に戻ってきます
戻ってきたら code を取得します
これを使って更にリクエストすることで token を取得します
あとは Drive API ようのクライアントを作成して drive.list_files でドライブ内のファイルの一覧を取得しています

動作確認

  • bundle exec rackup config.ru

localhost:9292 にアクセスすると認証画面にリダイレクトされます
google_oauth4.png

認証が成功すると Google Drive API にアクセスしても良いか確認する画面になるので許可を選択します
google_oauth5.png

すると Google Drive API から取得した JSON の生データがブラウザで確認できると思います
あとはお好きなように HTML なりを組み立てれば独自の Google Drive ブラウザができます

最後に

Google の OAuth を使ってみました
基本は OAuth なのでそれにそってクライアントを使うだけです

ポイントになりそうなのはスコープの指定方法かなと思います
基本は URL で指定する必要があります
あとは大量にスコープがあるのでどの API がどのスコープに紐付いているかわかりづらいです
また取得したい情報がどのスコープを有効にすることで取得できるのかもわからいづらいかなと思います
その辺りは各種 Google の API ドキュメントを見るしかないかなと思います

参考サイト

0 件のコメント:

コメントを投稿