Merry Christmas!
クリスマスイブなのでネタ記事にしようかと思って煽り系の記事を書いてたのですが、使いたいAPIの仕様上厳しそうだったので断念しました。私はできるかどうかちゃんと調べる前に作りたいとこから作り始めるクセがあるようで来年はこのクセを治すのを目標にしようと思います。
ということで、書きかけで断念していた記事がKobitoに眠っていたので完成させて今日のAdvent Calendarということにしたいと思います。
「Facebook内のアプリ」別名「Facebook Canvas」をRailsで作った話です。
自己署名証明書の作成
次の「アプリ登録」の項でFacebookアプリを登録しますが、その中の必須項目にSecure Canvas URLという項目があり、 https:// でないと通りません。 http://localhost:3000/ とかでうまくいってほしいところですが、このように設定する方法を調べてもなかったので、「ローカル環境で https:// が使えるようにする」という方向で進めます。
オレオレ証明書をopensslで作る(詳細版) - ろば電子が詰まっている を参考に、下記コマンドで自己署名証明書を作ります。
$ mkdir certs && cd certs
$ openssl genrsa 2048 > localhost.key
$ openssl req -new -key localhost.key > localhost.csr
$ openssl x509 -days 3650 -req -signkey localhost.key < localhost.csr > localhost.crt
このとき、 Common Name (e.g. server FQDN or YOUR name) []:localhost
としておきました。
WebRickで作成した証明書を使用するよう設定
次に作成した証明書を使用してHTTPS接続を受け付けるよう、 bin/rails
を編集します。
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rubygems'
require 'rails/commands/server'
require 'rack'
require 'webrick'
require 'webrick/https'
require 'webrick/ssl'
module Rails
class Server < ::Rack::Server
def default_options
super.merge(
Port: 3000,
environment: (ENV['RAILS_ENV'] || "development").dup,
daemonize: false,
debugger: false,
pid: File.expand_path("tmp/pids/server.pid"),
config: File.expand_path("config.ru"),
SSLEnable: true,
SSLVerifyClient: OpenSSL::SSL::VERIFY_NONE,
SSLPrivateKey: OpenSSL::PKey::RSA.new(File.open("certs/localhost.key").read),
SSLCertificate: OpenSSL::X509::Certificate.new(File.open("certs/localhost.crt").read),
SSLCertName: [["CN", 'localhost']]
)
end
end
end
require 'rails/commands'
あとはいつものように起動します。
$ bin/rails s
起動したら https://localhost:3000/ で確認します。自己署名証明書なので警告が出ますが気にしないことにします。
アプリ登録
Secure Canvas URLには https://localhost:3000/
と指定しました。
Facebookアプリで表示されることを確認します……。といけばいいのですが、ハマりポイントがあります。
HTTPメソッドがPOST
なので、 POST を受けられるようにしないとだめです。こんな感じでしょうか。
post '/', controller: :users, action: :new
X-Frame-Optionsヘッダが勝手につく
Railsはデフォルトで X-Frame-Options: SAMEORIGIN
ヘッダをつけてレスポンスするようで、他のドメイン内から iframe で埋め込まれるのを拒否するようになっています。なので、 application_controller.rb
に下記のようにいれておきます。
before_action def allow_iframe_requests
response.headers.delete('X-Frame-Options')
end
と、こんな感じでひとまずFacebook内でRailsアプリを動かせました。