PicasaAPIを使ってOAuth2.0のフロー(Authorization Code)を確認した。
OAuth、書籍やネット上の記事などから大まかに仕組みは理解していたのですが、具体的にリクエスト/レスポンスをどう送り合ってやりとりを行っているのかがよくわかっていませんでした。 OAuthの一連の流れを理解するために、今回は実際にOAuth2.0から認可してもらう流れをライブラリを使わずに実装していきたいと思います。
OAuth1.0はsignetureを作るのが少しメンドクサそうだったので、今回はOAuth2.0だけやります。
参考
OAuth2.0について
Google Photosへのアップロードについて
やること・ゴール
- Rubyで簡易的な実装で流れを掴んで行きたいと思います。
- Google PhotosにOAuth2.0で画像をアップロードできるよう認可してもらい、実際に画像をアップロードできるようにするところまでやっていきたいと思います。 (自宅のPCはUbuntuを使っているのですが、Google PhotosのクライアントはWindowsとMacしかないので、今後自作でちゃんとしたクライアント作っていくために、今回Google Photosへアップロードする流れを確認しました。)
- Google Photosは統合前のサービスPicasa、このAPIが使えます。(Google Photosというのは残念ながらないようです。)
OAuth2.0の認可フロー(Grant Type)
OAuth2.0の認可フローには4種類あります。 各フローにyoutubeに解説の動画があるので、リンクを貼っておきます。
Authorization Code 動画:https://www.youtube.com/watch?v=j0pIlZdD7-A&feature=youtu.be
- サーバサイドで多くの処理を行うウェブアプリケーション向けのフロー
Implicit 動画:https://www.youtube.com/watch?v=fF1mJB64xAg
- スマホアプリやJSを用いたクライアント再度で処理の多くを行うアプリケーション向けのフロー
Resource owner password credentials 動画:https://www.youtube.com/watch?v=qS0YY9Fo04Q
- サーバサイドを利用しないアプリケーション向けのフロー
Client Credentials 動画:https://www.youtube.com/watch?v=LLIMOYk5Syc
- ユーザ単位での認可を行わないアプリケーション向けのフロー
今回は、今後WEBアプリケーションで使っていけるよう、上記フローのうちAuthorization Codeで実装します。
googleからクライアント ID、クライアントシークレットをもらう
Google APIs Consoleへログインし、クライアント ID、クライアント シークレットをもらいます。 手順は検索すると多くの記事がでてくるので割愛します。
今回はAuthorization Codeで実装を行うので、アプリケーションの種類
はウェブ アプリケーション
を選択しました。
承認済みのリダイレクト URI
は、ユーザが認可のためGoogleにログイン後にリダイレクトされるURIなのですが、ここにクエリとしてアクセストークンがくっついてきます。
その他
にすると、リダイレクトされず、トークンが画面に表示されるようになります。
(Android、Chromeアプリ、iOS、PlayStation4にするとどういう動きになるかがわかりませんが、気になる方は調べてみると良いでしょう。)
認可コード(Authorization Code)をもらう
以下のコードで、認可コード(Authorization Code)をもらうためのログイン画面を表示します。 ここでは、uriの組み立てだけなのですが、hashでいい感じにクエリ付のuriを生成してくれるので、net/httpを使って実装しています。 (リクエストは送っていません。)
パラメータの仕様は以下です。 https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters
state
も指定できるので、WEBアプリケーションを実装するときにはつけておいた方が良いでしょう。
# -*- coding: utf-8 -*- require 'uri' require 'net/http' client_id = { クライアントID } redirect_uri = { リダイレクトURI } # Google APIs Consoleで登録したリダイレクトURIを入力します。異なる場合を入れた場合はエラーになります。 scope = 'https://picasaweb.google.com/data/' # Google Photosはpicasaのapiを利用しているので、次のURLを入れます。 uri = URI('https://accounts.google.com/o/oauth2/v2/auth') params = { response_type: 'code', client_id: client_id, redirect_uri: redirect_uri, scope: scope } uri.query = URI.encode_www_form(params) puts uri.to_s
ログインが完了したら、redirect_uriで指定したuriにリダイレクトされます。 その際に、クエリにcode={Authorization Code}がついてくるので、それをコピーしておきます。 WEBアプリケーションを実装する場合は、コールバック用のuriを用意しておき、Authorization Codeを取得できるようにしておくと良さそうです。
アクセストークンを取得する
以下のリクエストで、アクセストークンを取得します。 WEBアプリケーションを選択した場合は、有効期限はないため、リフレッシュトークンは発行されません。
# -*- coding: utf-8 -*- require 'uri' require 'net/http' require 'openssl' authorization_code = { 先ほど取得したauthorization_code } client_id = { クライアントID } client_secret = { クライアントシークレット } redirect_uri = { リダイレクトURI } uri = URI.parse('https://www.googleapis.com/oauth2/v4/token') https = Net::HTTP.new(uri.host, uri.port) https.use_ssl = true request = Net::HTTP::Post.new(uri.request_uri) request.set_form_data({ code: authorization_code, client_id: client_id, client_secret: client_secret, redirect_uri: redirect_uri, grant_type: 'authorization_code' }) response = https.request(request) puts response.code puts response.body
アクセストークンを使って、画像アップロード
以下のコードで画像をアップロードしてみます。
# -*- coding: utf-8 -*- require 'uri' require 'net/http' require 'openssl' user_id = { アップロードするユーザのid } access_token = { アクセストークン } upload_file = 'sample.jpg' uri = URI.parse("https://picasaweb.google.com/data/feed/api/user/#{user_id}/?access_token=#{access_token}") https = Net::HTTP.new(uri.host, uri.port) https.use_ssl = true request_header = { 'Content-Type': "image/jpeg", 'Content-Length': File.size(upload_file).to_s, 'Slug': upload_file } request = Net::HTTP::Post.new(uri.request_uri, request_header) request.body = File.read(upload_file) response = https.request(request) puts response.code puts response.body
アップロードされた画像を確認する
Google Photesアクセスし、画像がアップロードされていることを確認します。
OAuth2.0でGoogle PhotosへのアクセスをGoogleに認可してもらい、実際にアップロードできるところまで確認しました。 Authorization Code以外の認可フローについてはまた別の機会にやろうと思います。
RHEL7でRailsサーバを構築した サーバの基本設定
こちらは、
RHEL7でRailsアプリのサーバを構築した - takapiのブログ
の サーバの基本設定
に関する記事です。
OS(RHEL7)のアップデート
まずは、yum コマンドでOS(RHEL7)を更新します。
$ sudo yum -y update
ロケールの確認・変更
RHEL7からは、ロケール設定の確認・変更は 'localectl' コマンドを使用するようです。
こちらのサイトを参考に確認・変更します。 http://zero-config.com/centos/changelocale-002.html
現在の状態を確認します。
$ localectl status System Locale: LANG=ja_JP.utf8 VC Keymap: us X11 Layout: us
EC2で設定したRHEL7の System Locale
はデフォルトで日本語になっておりました。
VC Keymap、 X11 Layout
については、SSHからの接続のみなので無視して良さそうです。
ちなみに、 System Locale
の修正は以下のように行います。
sudo localectl set-locale LANG=ja_JP.utf8 # ja_JP.utf8で設定を行う場合
日付の変更
RHEL7からは、システムの日付および時間に関する情報の設定は 'timedatectl' コマンドを使用するようです。
こちらのサイトを参考に確認・変更します。
第2章 日付と時刻の設定 - Red Hat Customer Portal
現在の状態を確認します。
$ timedatectl status Local time: 土 2017-06-24 01:24:37 EDT Universal time: 土 2017-06-24 05:24:37 UTC RTC time: 土 2017-06-24 05:24:37 Time zone: America/New_York (EDT, -0400) NTP enabled: yes NTP synchronized: yes RTC in local TZ: no DST active: yes Last DST change: DST began at 日 2017-03-12 01:59:59 EST 日 2017-03-12 03:00:00 EDT Next DST change: DST ends (the clock jumps one hour backwards) at 日 2017-11-05 01:59:59 EDT 日 2017-11-05 01:00:00 EST
どうやら Time zone
が America/New_York
になっているようなので、タイムゾーンの変更します。
$ sudo timedatectl set-timezone Asia/Tokyo
もう一度、 timedatectl status
を実行し Time zone
が Asia/Tokyo
になっていることを確認します。
$ timedatectl status Local time: 土 2017-06-24 14:29:26 JST Universal time: 土 2017-06-24 05:29:26 UTC RTC time: 土 2017-06-24 05:29:26 Time zone: Asia/Tokyo (JST, +0900) NTP enabled: yes NTP synchronized: yes RTC in local TZ: no DST active: n/a
SElinuxの無効化
EC2のRHELはデフォルトでSElinuxが有効になっているようですが、現在はSElinux力がないので、実力がつくその日まで無効にしておきます。
こちらのサイトを参考に確認・変更します。
5.4. SELinux の有効化および無効化 - Red Hat Customer Portal
以下の設定ファイルを修正します。
/etc/selinux/config
の以下の箇所を disabled
に修正します。
SELINUX=enforcing ↓ SELINUX=disabled
設定変更後は、OSの再起動が必要なので再起動します。
以上で、サーバの基本設定は完了です。
RHEL7でRailsアプリのサーバを構築した【Railsアプリケーション・Unicorn のインストール・設定】
こちらは、
RHEL7でRailsアプリのサーバを構築した - takapiのブログ
の Railsアプリケーション・Unicorn のインストール・設定
に関する記事です。
Railsアプリケーションは完成している前提で進めます。
Railsアプリケーションをクローンする
github等からRailsアプリケーションをクローンします。
例: $ git clone --depth 1 https://github.com/takapi86/my-app.git
bundler のインストール
RubyのGem管理ツールである bundler
をインストールします。
gem install bundler
Node.jsのインストール
必要に応じて設定します。 必須ではないので、Node.jsを使用しない場合はスキップします。
$ sudo yum remove -y nodejs npm # 最新のバージョンをインストールしたいので、すでにインストールされている場合は削除します。 $ sudo rpm -i https://rpm.nodesource.com/pub_6.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm $ sudo yum -y install nodejs
sqliteのインストール
必要に応じて設定します。 必須ではないので、 sqlite を使用しない場合はスキップします。
$ sudo yum -y install sqlite $ sudo yum -y install sqlite-devel
Railsアプリケーションのproduction設定
アセットのプリコンパイル
$ bundle exec rake assets:precompile RAILS_ENV=production
SECRET_KEY_BASEの設定
Railsでは config/secrets.yml にCookieのなりすまし対策のため、SECRET_KEY_BASE をCookie暗号化/復号化をしているようです。
production環境の場合、SECRET_KEY_BASE を環境変数に設定してあげる必要があります。
$ bundle exec rake secret b1cb4a8933d20deaafb19e152217b7a53f784912ceb51dce6507e7336e671eef0136438d81604ca4c4c39cffc2ee93ba472b2d6cc597c0f4f3d39c05343dede1
動作確認のため、一時的にこの値を環境変数にセットします。
export SECRET_KEY_BASE=b1cb4a8933d20deaafb19e152217b7a53f784912ceb51dce6507e7336e671eef0136438d81604ca4c4c39cffc2ee93ba472b2d6cc597c0f4f3d39c05343dede1
各Gemのインストール
bunlde install しGemのインストールします。
$ cd ~/my-app/ $ bundle install
DB設定
$ vi config/database.yml
production: adapter: mysql2 database: [DB名を入力します] pool: 5 username: [DBのユーザを入力します] password: [DBのパスワードを入力します] host: localhost # 今回はDBサーバも同じサーバなので、localhostをしています。
DBマイグレーション
以下のコマンドで、アプリケーションのDB、テーブル、データを作成します。
RAILS_ENV=production bundle exec rake db:create RAILS_ENV=production bundle exec rake db:migrate RAILS_ENV=production bundle exec rake db:seed
Railsアプリケーションの動作確認
最終的に sustemdで起動・停止できるようにしますが、ひとまずunicornコマンドを実行し、 production
モードで起動できるか確認します。
unicornはデフォルトでは port8080 であがるので、8080宛にアクセスして動作確認を行います。
unicorn -E production
ここまで確認ができればRailsアプリケーション側の設定は完了です。
systemd の設定
設定したRailsアプリケーションをsystemdで起動・停止できるようにします。
config/unicorn.rb を編集
systemdからは unicornの設定ファイル config/unicorn.rb
の内容で起動・停止できるようにします。
必要に応じて、以下に設定を追加・削除するとよいでしょう。
# config/unicorn.rb app_path = '/home/ec2-user/my-app' worker_processes 2 listen "#{app_path}/tmp/sockets/unicorn.sock", :backlog => 64 listen 8080, :tcp_nopush => true pid "#{app_path}/tmp/pids/unicorn.pid" rails_root = File.expand_path('../../', __FILE__) ENV['BUNDLE_GEMFILE'] = rails_root + "/Gemfile" stderr_path "#{app_path}/log/unicorn.stderr.log" stdout_path "#{app_path}/log/unicorn.stdout.log" before_exec do |server| ENV['BUNDLE_GEMFILE'] = "#{ENV['RAILS_ROOT']}Gemfile" end
上記の設定でサーバがあがるかひとまず unicorn コマンドで確認してみます。
bundle exec unicorn -c config/unicorn.rb -E production
systemdの設定
/etc/systemd/system/unicorn.service
[Unit] Description = unicorn Rack application server Wants=mysqld.service After=mysqld.service [Service] Environment=RAILS_ENV=production Environment=SECRET_KEY_BASE=[SECRET_KEYを設定します。] PIDFile=/home/ec2-user/my-app/tmp/pids/unicorn.pid ExecStart=/home/ec2-user/.rbenv/shims/unicorn -c "/home/ec2-user/my-app/config/unicorn.rb" "/home/ec2-user/my-app/config.ru" -E production [Install] WantedBy = multi-user.target
自動起動の設定
$ sudo systemctl enable unicorn.service
以下のコマンドで登録できているか確認します。
$ sudo systemctl list-unit-files --type=service | grep unicorn unicorn.service enabled
起動できるか確認します。
$ sudo systemctl start unicorn.service
NginxからUnicornを呼び出す
/etc/nginx/conf.d/
以下のような設定ファイルを追加し、リバースプロキシできるようにします。
必要に応じて、以下に設定を追加・削除するとよいでしょう。
server { listen 80 default_server; server_name www.example.com; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; root /home/ec2-user/my-app/public; client_max_body_size 100m; error_page 404 /404.html; error_page 500 502 503 504 /500.html; try_files $uri/index.html $uri @unicorn; location @unicorn { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://localhost:8080; } }
nginxを再起動します。
$ sudo systemctl restart nginx
ページにアクセスして確認する
ブラウザなどでサーバのURLへアクセスし、システムのページなどが表示されていればOKです。
表示されない場合は、ネットワーク周りやファイアウォールなどの設定を見直すとよいでしょう。
RHEL7でRailsアプリのサーバを構築した【Nginxのインストール・設定】
こちらは、
RHEL7でRailsサーバを構築した - takapi86のブログ
の Nginxのインストール・設定
に関する記事です。
Nginxのインストール・設定
Stable version(nginx-1.12.0)をインストールしていきます。
Nginxのyumリポジトリの追加
$ sudo rpm -i http://nginx.org/packages/rhel/7/noarch/RPMS/nginx-release-rhel-7-0.el7.ngx.noarch.rpm
Nginxのインストール
$ sudo yum -y install nginx
自動起動の設定
sudo systemctl enable nginx.service
nginx を起動する
$ sudo systemctl start nginx.service
デフォルトページにアクセスして確認する
サーバのURLへアクセスし、Nginxのデフォルトページが表示されていればOKです。
表示されない場合は、ネットワーク周りやファイアウォールなどの設定を見直すとよいでしょう。
以上で、nginxの設定は完了です。
RHEL7でRailsアプリのサーバを構築した
AWS EC2(RHEL7)でRailsサーバを構築したので、手順を備忘録として残しておきます。
OSはAmazon Linuxでも良かったのですが、Systemdなど、RHEL7からの機能に慣れたいという思いからRHEL7を使っています。
AWSの設定(インスタンスの立ち上げ方、セキュリティグループ、Elastic IPの設定など)はここでは取り上げません。
構成
- OS Red Hat Enterprise Linux Server release 7.3
- Webサーバ nginx 1.12.0
- APサーバ unicorn 5.3.0 (ruby 2.4.1, Rails 5.1.1)
- DB MySQL 5.7
すべて1サーバにまとめています。
やること
1.サーバの基本設定
2.Nginxのインストール・設定
3.MySQLのインストール・設定
4.Rubyのインストール・設定
5.Railsアプリケーション・Unicorn のインストール・設定
以上、必要に応じてログの設定やセキュリティ・バックアップの設定等を追加していくと良いでしょう。
RHEL7でRailsアプリのサーバを構築した【MySQLのインストール・設定】
こちらは、
RHEL7でRailsアプリのサーバを構築した - takapi86のブログ
の MySQLのインストール・設定
に関する記事です。
EC2のRHEL7にMySQLのインストール・設定を行います。
MariaDBを削除する
EC2のRHELはデフォルトでMySQLと互換のあるMariaDBが入っています。 どうやら、どちらもインストールされていると競合するという噂があるので、削除してしまいます。
$ sudo yum -y remove mariadb-libs $ sudo rm -rf /var/lib/mysql/
MySQLのyumリポジトリの追加
$ sudo yum -y localinstall https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
rpmについては、以下のURLから該当するものを選択しました。 https://dev.mysql.com/downloads/repo/yum/
MySQLのインストール
以下のコマンドで、 mysql, mysql-devel をインストールします。
$ sudo yum -y install mysql-community-server mysql-devel
バージョンを確認します。
$ mysqld --version mysqld Ver 5.7.18 for Linux on x86_64 (MySQL Community Server (GPL))
$ sudo systemctl enable mysqld.service
MySQLを起動します。
$ sudo systemctl start mysqld.service
MySQLのrootユーザーの初期パスワードを確認し、メモしておきます。
MySQL5.7からは、rootの初期パスワードは /var/log/mysqld.log
に書き込まれます。
$ less /var/log/mysqld.log
このようにパスワードが含まれています。この場合だと GI(8KOU;xZvi
がパスワードです。
[Note] A temporary password is generated for root@localhost: GI(8KOU;xZvi
セキュリティの初期設定
mysql_secure_installation
を実行しセキュリティに関する初期設定を行います。
パスワードは先ほどメモした /var/log/mysqld.log
に書かれていたものを使用します。
設定する内容については、以下のサイトを参考にするとよいでしょう。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 4.4.5 mysql_secure_installation — MySQL インストールのセキュリティー改善
$ mysql_secure_installation
文字コードの設定
/etc/my.cnf
に以下の設定を追加することで、デフォルトの文字コードをutf8に変更します。
character-set-server = utf8
設定後はMySQLを再起動します。
$ sudo systemctl restart mysqld.service
ユーザを作成する
rootでMySQLにログインします。
$ mysql -u root -p
今回は、外部からは参照しないので、以下の設定を追加します。
mysql> CREATE USER 'ユーザ名'@'localhost' IDENTIFIED WITH mysql_native_password BY 'パスワード'; mysql> GRANT ALL PRIVILEGES ON DB名.* TO `ユーザ名`@`localhost`;
以上で、MySQLの設定は完了です。
この手順は、以下のサイトを参考に作成しました。
RHEL7でRailsアプリのサーバを構築した【Rubyのインストール・設定】
こちらは、
RHEL7でRailsアプリのサーバを構築した - takapiのブログ
の Rubyのインストール・設定
に関する記事です。
インストール済みの Ruby の削除
EC2のRHEL7では、元々インストールはされていませんでしたが、環境によってはデフォルトでRubyが入っている場合があります。 ほとんどの場合は、古いRubyが入っているので、一旦削除してしまいましょう。
$ sudo yum -y remove ruby
gitをインストールする
後ほど、 rbenv
,ruby-build
といったツールをダウンロードするのに必要です。
$ sudo yum -y install git
rbenvをインストールする
Rubyのバージョンの切り替えなどが簡単にできるツールであるrbenvをインストールします。 以下のサイトを参考にインストールします。
https://github.com/rbenv/rbenv
クローンします。
$ git clone --depth 1 https://github.com/rbenv/rbenv.git
.bash_profile に PATHを通します。
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile $ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
で何をしているかは、
こちらを参考にするとよいでしょう。
一度、ログアウトし直すか、以下のコマンドで ~/.bash_profile
を読みなおします。
$ source ~/.bash_profile
rbenv
コマンドが使えるか確認します。
$ rbenv rbenv 1.1.1-2-g615f844 Usage: rbenv <command> [<args>] Some useful rbenv commands are: commands List all available rbenv commands local Set or show the local application-specific Ruby version global Set or show the global Ruby version shell Set or show the shell-specific Ruby version rehash Rehash rbenv shims (run this after installing executables) version Show the current Ruby version and its origin versions List all Ruby versions available to rbenv which Display the full path to an executable whence List all Ruby versions that contain the given executable
ruby-buildをインストールする
rbenv の プラグインである ruby-build をインストールします。 実際にRubyをコンパイルしてインストールしてくれるものです。
クローンします。
$ git clone --depth 1 https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
もう一度、rbenv
コマンドを実行します。
$ rbenv rbenv 1.1.1-2-g615f844 Usage: rbenv <command> [<args>] Some useful rbenv commands are: commands List all available rbenv commands local Set or show the local application-specific Ruby version global Set or show the global Ruby version shell Set or show the shell-specific Ruby version install Install a Ruby version using ruby-build uninstall Uninstall a specific Ruby version rehash Rehash rbenv shims (run this after installing executables) version Show the current Ruby version and its origin versions List all Ruby versions available to rbenv which Display the full path to an executable whence List all Ruby versions that contain the given executable
ruby-build をクローンする前になかった install
,uninstall
が表示されていれば成功です。
Ruby2.4.1をインストール
EC2のRHEL7では、Rubyをコンパイルに以下のライブラリが必要なのでインストールしておきます。
$ sudo yum install -y gcc bzip2 openssl-devel readline-devel zlib-devel
rbenv install 2.4.1
スペックによりますが、結構時間がかかるので待ちます。
インストールしたRuby2.4.1を使うので、以下のコマンドで使えるようにします。
rbenv global 2.4.1
Rubyがインストールされているか確認する。
ruby -v ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]
以上でRuby のインストールは完了です。