LTI 認証とは
LTI認証という規格があります。
LTIとはLearning Tools Interoperability という単語の頭文字で、要するに学習支援ツール間で認証情報をやり取りする際の規格という意味です。
認証技術の中でも分野が特定されているかなりニッチな技術なので、知らない方も多いんではないでしょうか。僕も教育工学を専門にする前はLTIという単語すら知りませんでした。
以下にIMS GLOBAL から公式に出されているLTI認証の説明図をのっけて置きます。
個人的には、結局OAuthの一種と理解しているのですが、我々が開発するアプリケーションを Learning Tools, 認証の基盤となる大本のツールを Learning Platform として、Learning Tools は Learning Platform の拡張機能を提供する代わりに、認証情報を Learning Platform からもらいます。これによってユーザーは様々なアプリをユーザーを切り替えることなしに、使い分けることができるという利点があるわけです。このとき、Learning Toolsのほうを LTI Tool Provider, Learning Platformのほうを LTI Consumer と呼んだりもします。
ただ、問題はこれをどう実装するかです。実際、ニッチな技術ゆえにドキュメンテーションに乏しく、ネット上を探しても実装例はあまり公開されていません。そこで今回、この記事では Ruby on Rails を使った LTI 認証の実際について紹介したいと思います。
実装例
ライブラリのインストール
まずは、必要なライブラリをインストールします。
$ bundle add devise
$ bundle add ims-lti
$ bundle add oauth
Rails を使うメリットは lti 認証のためのライブラリがあるところです。今回は ims-lti
を使って実装します。
認証キーの登録
config
配下にlti_settings.yml
ファイルを作成します。
内容は以下の内容を記載してください(コンシューマーキー、LTIシークレットは適宜安全な文字列を使用してください)。
production:
__consumer_key__: '__lti_secret__'
development:
__consumer_key__: '__lti_secret__'
作成したら、これを読み込むための設定をconfig/application.rb
に追加します。
config.lti_settings = Rails.application.config_for(:lti_settings)
コントローラーの作成
ltis_controller
を作って以下の内容を記載しましょう
require 'oauth/request_proxy/action_controller_request'
class LtisController < ApplicationController
skip_before_action :verify_authenticity_token, only: :launch
def lti_launch
# 受け取った consumer key が config/lti_settings.yml の中にあるかどうかを確認
if not Rails.configuration.lti_settings[params[:oauth_consumer_key]]
render :launch_error, status: 401
return
end
shared_secret = Rails.configuration.lti_settings[params[:oauth_consumer_key]]
authenticator = IMS::LTI::Services::MessageAuthenticator.new(request.url, request.request_parameters, shared_secret)
#Check if the signature is valid
if not authenticator.valid_signature?
render :launch_error, status: 401
return
end
#check if the message is too old
if DateTime.strptime(request.request_parameters['oauth_timestamp'],'%s') < 5.minutes.ago
render :launch_error, status: 401
return
end
# LTI 情報をsessionに保存
session_data = {
"fullname" => authenticator&.message&.lis_person_name_full,
"email" => authenticator&.message&.lis_person_contact_email_primary,
"user_id" => authenticator&.message&.user_id,
"context_id" => authenticator&.message&.context_id,
"context_title" => authenticator&.message&.context_title,
"tool_consumer_instance_name" => authenticator&.message&.tool_consumer_instance_name
}
print(session_data)
session['lti-authenticator'] = session_data
sign_in_and_redirect(User.first)
end
end
MessageAuthenticator
にわたってきたリクエストと事前にこちらで保持しているキーの情報を渡すことで簡単に認証ができます。認証が成功したら、devise
ライブラリを使ってsign_inすることで、アプリ側での認証を実装しています。
最後にlti_launch
を起動するためのエンドポイントを定義しておきましょう。
match 'lti/launch' => 'ltis#lti_launch', via: [:get, :post], as: :lti_launch
Learning Platform 側での設定
ここまでできたら、あとは Learning Platform 側で事前に lti_settings.yml
に記載した認証情報を書いて指定したエンドポイントに遷移するように設定すれば完成です。このやり方は個々のLearning Platformによって異なるので割愛します。
(補足)LTI 遷移時に Rails で cross origin error が出たら
config/application.rb
に以下の内容を追記してください
config.lti_settings = Rails.application.config_for(:lti_settings)
config.action_dispatch.default_headers['Referrer-Policy'] = 'unsafe-url'
config.action_controller.forgery_protection_origin_check = false
config.action_controller.allow_forgery_protection = false