既存 Rails アプリに追加した REST API ドキュメンテーションにOAuth2 認可情報を反映する
回を追うごとにタイトルが長くなっていくのはご愛嬌。
Rails チュートリアルで作成したアプリに
- REST API を追加
- OAuth2 で保護
- Swagger でドキュメンテーション
と進めてきた。
前回の Swagger ドキュメンテーションではセキュリティの定義をしていないので追加していく。
Swagger の SecurityDefinition
This page is in progress. Please check back later.
まぁオープンソースだしね、文句があるなら自分でパッチ送れや的な?
GrapeSwaggerRails の doorkeeper 連携
そもそも GrapeSwaggerRails が doorkeeper と連携できるんでは?と思って見てみたらやはり。
user.rb は上記例の通り。
has_one :token, -> { order 'created_at DESC' }, class_name: Doorkeeper::AccessToken, foreign_key: :resource_owner_id
swagger.rb は、以下のようにある。
GrapeSwaggerRails.options.before_action do |request| GrapeSwaggerRails.options.api_key_default_value = current_user.token.token end
最終的な GrapeSwaggerRails.options.before_action は以下のようになった。
GrapeSwaggerRails.options.before_action do |request| GrapeSwaggerRails.options.app_url = request.protocol + request.host_with_port if (user_id = session[:user_id]) current_user ||= User.find_by(id: user_id) if (current_user_token = current_user.token) GrapeSwaggerRails.options.api_key_default_value = current_user_token.token end else session[:forwarding_url] = request.fullpath redirect_to(GrapeSwaggerRails.options.app_url + '/login') end end
さらに こちら を参考に、api_key の値をクエリパラメータでは無くヘッダーで渡すよう設定する。
GrapeSwaggerRails.options.api_auth = 'bearer' GrapeSwaggerRails.options.api_key_name = 'Authorization' GrapeSwaggerRails.options.api_key_type = 'header'
これで、irb から AccessToken 取得まで進めておけば、そのユーザーでログインした(セッションが有効な)状態で https://host:port/swagger にアクセスすればアクセストークンを api_key として持った状態で Swagger UI が表示できる。
各 API の Try it out! ボタンも正常に動作する。
その他
irb 使わなくても、Swagger UI から認可のフローが実行できないものか。。?
ちょっと だいぶ調べて、できそうなんだけどうまくいかないので断念。
api/v1/root.rb に以下を追加したところ、Swagger の json には SecurityDefinition の定義もできているが、Authorize 用の UI が表示されない。
add_swagger_documentation \
info: {
title: "SAMPLE APP",
description: "This is the sample application for the tutorial.",
contact_name: "kfurue",
contact_email: "contact@example.com",
contact_url: "http://example.com/contact",
license: "the MIT License",
license_url: "http://example.com/license"
},
security_definitions: {
oauthAccessCode: {
type: "oauth2",
authorizationUrl: "https://host:port/oauth/authorize",
tokenUrl: 'https://host:port/oauth/token',
flow: "accessCode",
scopes: {
user: "User scope"
}
},
oauthImplicit: {
type: "oauth2",
authorizationUrl: "https://host:port/oauth/authorize",
flow: "implicit",
scopes: {
user: "User scope"
}
}
}
GrapeSwaggerRails のせいか?と思い、grape-swagger で生成した JSON を元に、ローカルで Swagger UI を立ち上げてみるとなるほど、Authorization 用の UI は出てくる。 が、今度は
Validation Erroroauth2RedirectUri configuration is not passed. Oauth2 authorization cannot be performed.
などと表示されて認可フローは通せず。
まだまだ壁は多そうなのでここらで諦めよう。
やりたいことはできてるっぽいし?