Closed cccties closed 2 years ago
Moodleは3.7以降で対応している https://tracker.moodle.org/browse/MDL-62599
BlackBoardも対応している模様(こちらは実際に確認できていませんが) https://help.blackboard.com/ja-jp/Learn/Administrator/Hosting/System_Integration/LTI#add-a-new-lti-tool-provider_OTP-4
BlackBoardも対応している模様
昨年 10 月リリースの Blackboard version 3700.9.0 からの対応: https://help.turnitin.com/release-notes/blackboard/blackboard-LTI-release-notes.htm#2019-october-2nd
実際に使って頂く各学校などが現在利用している LMS のバージョンを確認して、すべて LTI v1.3 対応が可能であればこちらを v1.3 対応に変えた上で切替計画を、LMS 側が LTI v1.3 に対応していない古いものを使い続けている場合、不味いと思うのでどうするんですかの相談からですね (できれば更新して貰って LTI v1.2 以前は捨てたい)。
TODO: 認証機構の実装に伴い、LTIのロールとの対応関係を明確にする
本IssueではLTIのロールによって一意に定まる対応関係を認証機構に組み込む 権限の制御の実装は別課題としたい
NOTE: 実装方針
- LTI v1.3ならばLMSをOpenID (~OAuth 2.0)プロバイダーとして登録できるハズ
Authorization Code GrantへのサポートはLMSによって異なる (MoodleはAuthorization Code Grant非対応)
参考文献
LMSの対応状況
ユーザーの認証認可のためにLMSを使おうと思うと、それぞれのLMSに依ってフローと構造が異なる
TODO: 想像以上に厄介な問題なので今期の開発のスコープに含めないという方針も含めて検討し方針を決める
TODO: 想像以上に厄介な問題なので今期の開発のスコープに含めないという方針も含めて検討し方針を決める
利用者の利便性と手間を優先して、LTI 1.0/1.1 を採用し今回の開発スコープでは見送ることにした。
Moodleだと OIDC Authorization flow の response_type=id_token
MoodleのAuthentication request URLは次の手順で調べることが可能だと分かった。
All this info is provided by moodle after you create your LTI 1.3 External Tool in Moodle UI. Path in moodle: "Site administration -> Plugins -> Activity modules -> External tool". You need to login as a moodle admin to access the UI.
After you create an external tool, the following info can be seen in the tool configuration details ui.
Srinivas Jonnala, Moodle in English: Interfacing an external tool with LTI 1.3
実際に /moodle/mod/lti/auth.php に OIDC Authorization flow における Authentication Request を投げることで、次の id_token が得られた。
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjUxN2M3ZmM3YWIzMTg3ODdkY2UzIn0.eyJub25jZSI6ImJhciIsImlhdCI6MTYyMDYzMjgzMSwiZXhwIjoxNjIwNjMyODkxLCJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3Q6ODA4MSIsImF1ZCI6IkNwelRyMlVzV1Z1QkJBTSIsImh0dHBzOlwvXC9wdXJsLmltc2dsb2JhbC5vcmdcL3NwZWNcL2x0aVwvY2xhaW1cL2RlcGxveW1lbnRfaWQiOiIxIiwiaHR0cHM6XC9cL3B1cmwuaW1zZ2xvYmFsLm9yZ1wvc3BlY1wvbHRpXC9jbGFpbVwvdGFyZ2V0X2xpbmtfdXJpIjoiaHR0cDpcL1wvbG9jYWxob3N0OjgwODAiLCJzdWIiOiIyIiwiaHR0cHM6XC9cL3B1cmwuaW1zZ2xvYmFsLm9yZ1wvc3BlY1wvbHRpXC9jbGFpbVwvbGlzIjp7InBlcnNvbl9zb3VyY2VkaWQiOiIiLCJjb3Vyc2Vfc2VjdGlvbl9zb3VyY2VkaWQiOiIifSwiaHR0cHM6XC9cL3B1cmwuaW1zZ2xvYmFsLm9yZ1wvc3BlY1wvbHRpXC9jbGFpbVwvcm9sZXMiOlsiaHR0cDpcL1wvcHVybC5pbXNnbG9iYWwub3JnXC92b2NhYlwvbGlzXC92MlwvaW5zdGl0dXRpb25cL3BlcnNvbiNBZG1pbmlzdHJhdG9yIiwiaHR0cDpcL1wvcHVybC5pbXNnbG9iYWwub3JnXC92b2NhYlwvbGlzXC92MlwvbWVtYmVyc2hpcCNJbnN0cnVjdG9yIiwiaHR0cDpcL1wvcHVybC5pbXNnbG9iYWwub3JnXC92b2NhYlwvbGlzXC92Mlwvc3lzdGVtXC9wZXJzb24jQWRtaW5pc3RyYXRvciJdLCJodHRwczpcL1wvcHVybC5pbXNnbG9iYWwub3JnXC9zcGVjXC9sdGlcL2NsYWltXC9jb250ZXh0Ijp7ImlkIjoiMiIsImxhYmVsIjoiQzEiLCJ0aXRsZSI6IkMxIiwidHlwZSI6WyJDb3Vyc2VTZWN0aW9uIl19LCJodHRwczpcL1wvcHVybC5pbXNnbG9iYWwub3JnXC9zcGVjXC9sdGlcL2NsYWltXC9yZXNvdXJjZV9saW5rIjp7InRpdGxlIjoibGluazEiLCJpZCI6IjEifSwiaHR0cHM6XC9cL3B1cmwuaW1zZ2xvYmFsLm9yZ1wvc3BlY1wvbHRpLWJvXC9jbGFpbVwvYmFzaWNvdXRjb21lIjp7Imxpc19yZXN1bHRfc291cmNlZGlkIjoie1wiZGF0YVwiOntcImluc3RhbmNlaWRcIjpcIjFcIixcInVzZXJpZFwiOlwiMlwiLFwidHlwZWlkXCI6XCIxXCIsXCJsYXVuY2hpZFwiOjI2NDI4NzIzN30sXCJoYXNoXCI6XCJmMzU5NDM1OWE5YjdjNTc5NTlhNjkxYTE5Y2YyMmE5M2U2NTY4OWQyZjhlNTdmNjlkOGUzMTQ0YThmZWY3NDE0XCJ9IiwibGlzX291dGNvbWVfc2VydmljZV91cmwiOiJodHRwOlwvXC9sb2NhbGhvc3Q6ODA4MVwvbW9kXC9sdGlcL3NlcnZpY2UucGhwIn0sImdpdmVuX25hbWUiOiJBZG1pbiIsImZhbWlseV9uYW1lIjoiVXNlciIsIm5hbWUiOiJBZG1pbiBVc2VyIiwiaHR0cHM6XC9cL3B1cmwuaW1zZ2xvYmFsLm9yZ1wvc3BlY1wvbHRpXC9jbGFpbVwvZXh0Ijp7InVzZXJfdXNlcm5hbWUiOiJ1c2VyIiwibG1zIjoibW9vZGxlLTIifSwiZW1haWwiOiJ1c2VyQGV4YW1wbGUuY29tIiwiaHR0cHM6XC9cL3B1cmwuaW1zZ2xvYmFsLm9yZ1wvc3BlY1wvbHRpXC9jbGFpbVwvbGF1bmNoX3ByZXNlbnRhdGlvbiI6eyJsb2NhbGUiOiJlbiIsImRvY3VtZW50X3RhcmdldCI6ImlmcmFtZSIsInJldHVybl91cmwiOiJodHRwOlwvXC9sb2NhbGhvc3Q6ODA4MVwvbW9kXC9sdGlcL3JldHVybi5waHA_Y291cnNlPTImbGF1bmNoX2NvbnRhaW5lcj0zJmluc3RhbmNlaWQ9MSZzZXNza2V5PUx2NzNGUlBoTW8ifSwiaHR0cHM6XC9cL3B1cmwuaW1zZ2xvYmFsLm9yZ1wvc3BlY1wvbHRpXC9jbGFpbVwvdG9vbF9wbGF0Zm9ybSI6eyJwcm9kdWN0X2ZhbWlseV9jb2RlIjoibW9vZGxlIiwidmVyc2lvbiI6IjIwMjAxMTA5MDEiLCJndWlkIjoiN2YzZGViYmFjNDFkM2ZkZWJjZGExMTM3M2NmOWQyMDEiLCJuYW1lIjoiTmV3IFNpdGUiLCJkZXNjcmlwdGlvbiI6Ik5ldyBTaXRlIn0sImh0dHBzOlwvXC9wdXJsLmltc2dsb2JhbC5vcmdcL3NwZWNcL2x0aVwvY2xhaW1cL3ZlcnNpb24iOiIxLjMuMCIsImh0dHBzOlwvXC9wdXJsLmltc2dsb2JhbC5vcmdcL3NwZWNcL2x0aVwvY2xhaW1cL21lc3NhZ2VfdHlwZSI6Ikx0aVJlc291cmNlTGlua1JlcXVlc3QifQ.imTZmabCj0rux1APGKCcQ9dsXmBDJ7Hnf5T9pHWHVTSNQgFHMsy11MxbohSnSxIj6xQ6S1Pn_gu8tu6bMeHptZ3ktSgVgfw9-11bBdY0sGGQPIms3ioE7zh3WiS-HJLChirMXsrywdVhHSdRF_wU6MznNfqzttmj4IlBEvBz8QHbIVjtZMMZAn2edSC4vXQtuvnsiaNlr0yK19z9lXKgJCfYJVZQ6HAFAevrvPxZlRci5Rh50nqGg5zWfbTTUo5bKximCRD9fSQ81teQQRoMHrxpjBM3yc-Y6Jvvk3Jgf9nm3vY__F7QxeaNmPQOAqpHYkn2X5-IFo3UObgbmaJNKw
header:
{
"typ": "JWT",
"alg": "RS256",
"kid": "517c7fc7ab318787dce3"
}
payload:
{
"nonce": "bar",
"iat": 1620632831,
"exp": 1620632891,
"iss": "http://localhost:8081",
"aud": "CpzTr2UsWVuBBAM",
"https://purl.imsglobal.org/spec/lti/claim/deployment_id": "1",
"https://purl.imsglobal.org/spec/lti/claim/target_link_uri": "http://localhost:8080",
"sub": "2",
"https://purl.imsglobal.org/spec/lti/claim/lis": {
"person_sourcedid": "",
"course_section_sourcedid": ""
},
"https://purl.imsglobal.org/spec/lti/claim/roles": [
"http://purl.imsglobal.org/vocab/lis/v2/institution/person#Administrator",
"http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor",
"http://purl.imsglobal.org/vocab/lis/v2/system/person#Administrator"
],
"https://purl.imsglobal.org/spec/lti/claim/context": {
"id": "2",
"label": "C1",
"title": "C1",
"type": [
"CourseSection"
]
},
"https://purl.imsglobal.org/spec/lti/claim/resource_link": {
"title": "link1",
"id": "1"
},
"https://purl.imsglobal.org/spec/lti-bo/claim/basicoutcome": {
"lis_result_sourcedid": "{\"data\":{\"instanceid\":\"1\",\"userid\":\"2\",\"typeid\":\"1\",\"launchid\":264287237},\"hash\":\"f3594359a9b7c57959a691a19cf22a93e65689d2f8e57f69d8e3144a8fef7414\"}",
"lis_outcome_service_url": "http://localhost:8081/mod/lti/service.php"
},
"given_name": "Admin",
"family_name": "User",
"name": "Admin User",
"https://purl.imsglobal.org/spec/lti/claim/ext": {
"user_username": "user",
"lms": "moodle-2"
},
"email": "user@example.com",
"https://purl.imsglobal.org/spec/lti/claim/launch_presentation": {
"locale": "en",
"document_target": "iframe",
"return_url": "http://localhost:8081/mod/lti/return.php?course=2&launch_container=3&instanceid=1&sesskey=Lv73FRPhMo"
},
"https://purl.imsglobal.org/spec/lti/claim/tool_platform": {
"product_family_code": "moodle",
"version": "2020110901",
"guid": "7f3debbac41d3fdebcda11373cf9d201",
"name": "New Site",
"description": "New Site"
},
"https://purl.imsglobal.org/spec/lti/claim/version": "1.3.0",
"https://purl.imsglobal.org/spec/lti/claim/message_type": "LtiResourceLinkRequest"
}
id_tokenをざっと確認した範囲では従来のLTI v1.1 launch request message bodyに相当するデータが含まれており問題無さそうに見える。(user_id→sub, lti_resource_link→"https://purl.imsglobal.org/spec/lti/claim/resource_link".id など) 互換性を保ちつつ移行するにはOAuth Consumer IDと、iss/deployment_id/client_idとのマッピングや、roleの変換、等が課題。 加えて、リクエストパラメータの過不足の確認処理、id_tokenの検証が必要になると思う。
成績の統合について:
Basic Outcomes serviceのほうが古く基本的な機能 lis_result_sourcedid, lis_outcome_service_url はLTI v1.1/1.3 においていずれもオプションではあるが実際Moodle起動時のパラメータとして含まれていることを確認
XMLペイロードをOAuth 署名してlis_outcome_service_urlにPOSTすることによってlis_result_sourcedid 一つに対して数値の評点 (0.0 ~ 1.0) を設定可能
XMLペイロードをOAuth 署名してlis_outcome_service_urlにPOSTすることによってlis_result_sourcedid 一つに対して数値の評点 (0.0 ~ 1.0) を設定可能
なるほど、評点を返すための LIS エンドポイント URL は LTI 起動 (launch) する時点で受け取っていて任意のタイミングで OAuth 署名付きデータを POST して評点を返すことが出来る仕組みなのですね。
返すことが可能な評点は仕様書で言う numeric grade (0.0 - 1.0) だけだから LTI で紐付けるブック毎での進捗を返すことは出来るがその中のトピック単位での進捗までは返す手段はない。そんな感じですかね?
LTI で紐付けるブック毎での進捗を返すことは出来るがその中のトピック単位での進捗までは返す手段はない。
少なくともBasic Outcomes Serviceについてはおそらくそうだと思います。 一方Grade Servicesについては対応状況がLMS/LTIバージョンに依っては変わってきそうですがより高度な、具体的にはline itemという単位で同じresource linkに紐付けて複数の成績の詳細の最大スコアとスコアを返せるかもしれません。(Grade Services については現在調査不足)
互換性を保ちつつ移行するにはOAuth Consumer IDと、iss/deployment_id/client_idとのマッピングや、roleの変換、等が課題。
LtiResourceLinkSchema:
aud
"https://purl.imsglobal.org/spec/lti/claim/resource_link"
"https://purl.imsglobal.org/spec/lti/claim/context"
{id, label, title}LtiLaunchBody: (これはmodelsに移行したほうが正しいな…)
aud
"https://purl.imsglobal.org/spec/lti/claim/version"
"https://purl.imsglobal.org/spec/lti/claim/resource_link"
{id, title}sub
"https://purl.imsglobal.org/spec/lti/claim/context"
{id, label, title}"https://purl.imsglobal.org/spec/lti/claim/launch_presentation"
return_urlMoodle Moodleのロールのマッピングはドキュメントが見当たらず… 実装はおそらく下記の通り
下の表のような素朴な実装に見える
LTI 1.1 context role | LTI 1.3 context role |
---|---|
urn:lti:role:ims/lis/* | http://purl.imsglobal.org/vocab/lis/v2/membership#* |
urn:lti:instrole:ims/lis/* | http://purl.imsglobal.org/vocab/lis/v2/institution/person#* |
urn:lti:sysrole:ims/lis/* | http://purl.imsglobal.org/vocab/lis/v2/system/person#* |
上記以外 | http://purl.imsglobal.org/vocab/lis/v2/membership#* |
Blackboard Blackboardヘルプより引用:
LTI role mapping
Course role mapping
Learn course role LTI 1.1 context role LTI 1.3 context role COURSE_BUILDER urn:lti:role:ims/lis/ContentDeveloper http://purl.imsglobal.org/vocab/lis/v2/membership#ContentDeveloper GRADER urn:lti:role:ims/lis/TeachingAssistant/Grader http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor TEACHING_ASSISTANT urn:lti:role:ims/lis/TeachingAssistant http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor STUDENT urn:lti:role:ims/lis/Learner http://purl.imsglobal.org/vocab/lis/v2/membership#Learner GUEST urn:lti:role:ims/lis/Learner/GuestLearner http://purl.imsglobal.org/vocab/lis/v2/membership#Learner All others urn:lti:role:ims/lis/Instructor http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor Mapping for roles not in a course
Roles not in course LTI 1.1 context role LTI 1.3 context role system.administration.top.VIEW urn:lti:sysrole:ims/lis/Administrator http://purl.imsglobal.org/vocab/lis/v2/institution/person#Administrator All others urn:lti:sysrole:ims/lis/None http://purl.imsglobal.org/vocab/lis/v2/institution/person#None
リクエストパラメータの過不足の確認処理
LTI 1.3 に必要なクレイム https://www.imsglobal.org/spec/lti/v1p3/#required-message-claims
追加する必要がありそうないくつかのパラーメーター:
["id_token"]
固定でも可能https://purl.imsglobal.org/spec/lti/claim/deployment_id
- 1つのツールに使用可能なコンテキストの制約を複数持たせたいのであれば必要だがまずはロールベースで十分、というかLTI 1.1との下位互換は破綻しうるのでLTI 1.1との相互運用を維持している限りにおいては取得はできても識別はできないゴールとしては下記の3点
ターゲットはまずはMoodle
課題としては大きく分けると下記の3点
実装方針としてはopenid-clientを使ったRPの実装をベースに、既存の本システムのLTI 1.1の実装との互換性の確保しつつLTI v1.3のための実装を追加していく方針
IMS は SHA-1 の危殆化に伴い LTI 1.0/1.1/1.2 についてはセキュリティ上 deprecated にすると 2018/2 に宣言している。 https://www.imsglobal.org/security-bulletin-deprecation-notice-sha-1-hash-algorithm
従っていずれ LTI v1.3 へのアップグレード対応が必要となる。スケジュールとしては早い方が望ましいが、deadline としては以下の deprecation schedule、つまり 2021 年末または 1.0.1/1.1.2 にして延命措置をしても 2022年 6 月末と考えられる: https://www.imsglobal.org/lti-security-announcement-and-deprecation-schedule#LTIdeprecation
1~1.5 年の延命のための実装に手間をかけるくらいなら 21 年末までに LTIv1.3 へのアップグレードを行うべきと考えられる。