#author("2023-08-29T03:21:30+00:00","default:iseki","iseki")
** Hack for [[Moodle]] - [[LTI]] [#w4c22429]
- [[Moodle+JupyterHub]]
- [[Moodle]], [[JupyterHub]]
- [[LTI]]


*** iframe を使用すると,chrome, edgeでは 405 : Method Not Allowed が返される件 [#id5b6e70]
- SameSite=Lax であるため,iframe 使用時は Moodleのホストと JupyterHub のホストが異なる場合は,cookie が送信されない.


**** JupyterHub の log [#y1916cbf]
- 返されたステータス
-- 302 POST
-- 302 GET (通常はここで 200が返る)
-- 302 GET
-- 405 GET


**** ソースコード トレース (数字はトレース順) [#oaf0a04f]
- ltiauthenticator/lti11/auth.py   
-- 0. authenticate() 

- jupyterhub/handlers/base.py 
-- 4. login_user()  self.current_user -> None
-- 5. self.get_current_user_cookie()
-- 6. self._user_for_cookie()   cookie_id-> None  cookie_name=jupyterhub-hub-login

- tornado/web.py
-- 1. _unimplemented_method()  HTTPError(405) を返す
-- 2. wrapper()  で 302 が返る.通常なら 200 が返るはず.
-- 3. self.current_user -> None
-- 7. get_secure_cookie()   ''結局,jupyterhub-hub-login のクッキーありません.(Webブラウザから送信されていません)''


**** Moodle ホスト上で,JupyterHub へ接続するための feserver を動かしてみる. [#a6a32ef6]
- cookie が送信されない理由について推測が正しいならば,MoodleとJupyterHubを同じホストで動かせば(若しくは動いているように見せれば),iframeは問題なく使用できるはず.
- feserver のSSLのサーバ証明書で手こずったが,Apacheで使用している証明書使用したところ上手く繋がった.
- chrome, edge でも iframe の埋め込みが問題なく動作.
- でも問題点を確認したのみで,解決にはなっていない.

- ''問題点: Moodleと JupyterHubを別のホストで動かすと,iframe を使用した場合,chrome, edge から cookieが送信されない.''(その内 FireFoxもだよね)

**** 解決方法 [#f974d825]

 c.JupyterHub.tornado_settings = {
     "headers":{ "Content-Security-Policy": "frame-ancestors 'self' https://www.nsl.tuis.ac.jp" },
     "cookie_options": {"SameSite": "None", "Secure": True }
 }

 c.Spawner.args = ['--NotebookApp.tornado_settings={
         "headers":{"Content-Security-Policy": "frame-ancestors \'self\' https://www.nsl.tuis.ac.jp" }, 
         "cookie_options": { "SameSite": "None", "Secure": True } 
     }'
 ]

**** 参考:DB [#vf633496]
 MariaDB [moodle_db]> show columns from mdl_lti;
 +-------------------------------+--------------+------+-----+---------+----------------+
 | Field                         | Type         | Null | Key | Default | Extra          |
 +-------------------------------+--------------+------+-----+---------+----------------+
 | id                            | bigint(10)   | NO   | PRI | NULL    | auto_increment |
 | course                        | bigint(10)   | NO   | MUL | 0       |                |
 | name                          | varchar(255) | NO   |     |         |                |
 | intro                         | longtext     | YES  |     | NULL    |                |
 | introformat                   | smallint(4)  | YES  |     | 0       |                |
 | timecreated                   | bigint(10)   | NO   |     | 0       |                |
 | timemodified                  | bigint(10)   | NO   |     | 0       |                |
 | typeid                        | bigint(10)   | YES  |     | NULL    |                |
 | toolurl                       | longtext     | NO   |     | NULL    |                |
 | securetoolurl                 | longtext     | YES  |     | NULL    |                |
 | instructorchoicesendname      | tinyint(1)   | YES  |     | NULL    |                |
 | instructorchoicesendemailaddr | tinyint(1)   | YES  |     | NULL    |                |
 | instructorchoiceallowroster   | tinyint(1)   | YES  |     | NULL    |                |
 | instructorchoiceallowsetting  | tinyint(1)   | YES  |     | NULL    |                |
 | instructorcustomparameters    | longtext     | YES  |     | NULL    |                |
 | instructorchoiceacceptgrades  | tinyint(1)   | YES  |     | NULL    |                |
 | grade                         | bigint(10)   | NO   |     | 100     |                |
 | launchcontainer               | tinyint(2)   | NO   |     | 1       |                |
 | resourcekey                   | varchar(255) | YES  |     | NULL    |                |
 | password                      | varchar(255) | YES  |     | NULL    |                |
 | debuglaunch                   | tinyint(1)   | NO   |     | 0       |                |
 | showtitlelaunch               | tinyint(1)   | NO   |     | 0       |                |
 | showdescriptionlaunch         | tinyint(1)   | NO   |     | 0       |                |
 | servicesalt                   | varchar(40)  | YES  |     | NULL    |                |
 | icon                          | longtext     | YES  |     | NULL    |                |
 | secureicon                    | longtext     | YES  |     | NULL    |                |
 +-------------------------------+--------------+------+-----+---------+----------------+

            <option value="1" selected="">デフォルト</option>
            <option value="2">埋め込み</option>
            <option value="3">埋め込み (ブロックなし)</option>
            <option value="5">既存のウィンドウ</option>
            <option value="4">新しいウィンドウ</option>

*** [[JupyterHub]] の Swapner での LTI 情報の受け取り処理 [#vd91a1e1]
- jupyterhub_config.py
 import os
 os.environ['JUPYTERHUB_CRYPT_KEY'] = 'c283a5e73c8f74cdc8c6fef5415f1c97948a5a5450b5dc7524b9939093a2bd1d'
 .......
 .......
     def userdata_hook(self, auth_state):
         print("AURTH")
         print(auth_state)
 .......
 .......
 c.Spawner.auth_state_hook = ProjectDockerSpawner.userdata_hook
 c.Authenticator.enable_auth_state = True

- 環境変数 JUPYTERHUB_CRYPT_KEY の設定が必要
-- キーは openssl rand -hex 32 で生成(Moodle側と一致させる)



**** JupyterHub へのパラメータ送信 [#h7f6bcb7]
- Moodleの外部ツールの設定で,「一般」の「さらに表示する」でカスタムパラメータを指定すると,JupyterHub に任意のパラメータを送れる.
-- ''XXX=ZZZ'' と入力すると,上記方法で ''{'costom_xxx': 'ZZZ'}'' として受け取れる(キーは小文字化される).
-- # - などの特殊文字は ''_'' になる.''snake_case'' と言うらしい.


- 予約語
-- next=


*** [[JupyterHub]] が [[Moodle]] から受け取ったデータ [#uff7064e]
- 一般的に認証モジュールが引数として受け取る値 
 {
   'user_id': '2', 
   'lis_person_sourcedid': '', 
   'roles': 'Instructor,urn:lti:sysrole:ims/lis/Administrator,urn:lti:instrole:ims/lis/Administrator', 
   'context_id': '98', 
   'context_label': 'JupyterHub-devel', 
   'context_title': 'JupyterHub 開発', 
   'resource_link_title': 'JupyterHub', 
   'resource_link_description': '', 
   'resource_link_id': '11', 
   'context_type': 'CourseSection', 
   'lis_course_section_sourcedid': '', 
   'lis_result_sourcedid': '{
     "data":{
       "instanceid":"11",
       "userid":"2",
       "typeid":"2",
       "launchid":1442412989
     },
     "hash":"a526aa576887b4dc19c16107e9ac7b0dbc92f852e23f044d55356ba83f3b7037"
   }',
   'lis_outcome_service_url': 'https://el.mml.tuis.ac.jp/moodle/mod/lti/service.php', 
   'lis_person_name_given': 'Admin', 
   'lis_person_name_family': '管理ユーザ', 
   'lis_person_name_full': 'Admin 管理ユーザ', 
   'ext_user_username': 'admin', 
   'lis_person_contact_email_primary': 'fumi.hax@gmail.com', 
   'launch_presentation_locale': 'ja', 
   'ext_lms': 'moodle-2', 
   'tool_consumer_info_product_family_code': 'moodle', 
   'tool_consumer_info_version': '2020110902', 
   'lti_version': 'LTI-1p0', 
   'lti_message_type': 'basic-lti-launch-request', 
   'tool_consumer_instance_guid': '5384b0f81508b987c188b1985f5cd4e0', 
   'tool_consumer_instance_name': 'EL MML', 
   'tool_consumer_instance_description': 
   'e-Learning of MML', 
   'custom_mdl_user': '*', 
   'custom_mdl_teacher': 'iseki, admin', 
   'custom_mdl_image': 'jupyterhub/singleuser-mdl2 : latest', 
   'custom_mdl_suburl': '', 
   'custom_mdl_sessioninfo': '3,11', 
   'custom_mdl_vol_zzzz': '課題2', 
   'custom_mdl_vol_iseki': 'へへへ', 
   'custom_mdl_vol_jogrid': 'へへへ', 
   'custom_mdl_vol_': 'えええええええ', 
   'custom_mdl_vol_hhhhhggjjj': 'あああ', 
   'custom_mdl_vol_xxxx': 'いいいい', 
   'custom_mdl_sub_xxxx': '課題提出場所', 
   'custom_md_teacher': 'iseki', 
   'custom_ssss': '777', 
   'custom_zzzz': '', 
   'launch_presentation_document_target': 'window', 
   'launch_presentation_return_url': 'https://el.mml.tuis.ac.jp/moodle/mod/lti/return.php?course=98&launch_container=4&instanceid=11&sesskey=6wL3CYeL7Z'
 }

** Moodle DB [#sab902e6]
*** LTIの typeid (External Tool 情報) を格納するテーブル [#d76ec06b]
 MariaDB [moodle_db]> select id, name,baseurl,tooldomain,state,course,clientid  from   mdl_lti_types ;
 +----+------------------+----------------------------------------------------+-----------------------------+-------+--------+-----------------+
 | id | name             | baseurl                                            | tooldomain                  | state | course | clientid        |
 +----+------------------+----------------------------------------------------+-----------------------------+-------+--------+-----------------+
 |  3 | antares:443      | https://antares.nsl.tuis.ac.jp/hub/lti/launch      | antares.nsl.tuis.ac.jp      |     1 |      1 | Oh9MyHxutcfbvhA |
 |  4 | GITLAB:FE 8100  | https://gitlab.nsl.tuis.ac.jp:8100/hub/lti/launch  | gitlab.nsl.tuis.ac.jp:8100  |     1 |      1 | NULL            |
 | 10 | procyon:443      | https://jupyterhub.nsl.tuis.ac.jp/hub/lti/launch   | jupyterhub.nsl.tuis.ac.jp   |     1 |      1 | NULL            |
 | 12 | JupyterHub00:443 | https://jupyterhub00.nsl.tuis.ac.jp/hub/lti/launch | jupyterhub00.nsl.tuis.ac.jp |     1 |      1 | NULL            |
 | 13 | JupyterHub01:443 | https://jupyterhub01.nsl.tuis.ac.jp/hub/lti/launch | jupyterhub01.nsl.tuis.ac.jp |     1 |      1 | NULL            |
 | 14 | JupyterHub02:443 | https://jupyterhub02.nsl.tuis.ac.jp/hub/lti/launch | jupyterhub02.nsl.tuis.ac.jp |     1 |      1 | NULL            |
 | 15 | JupyterHub03:443 | https://jupyterhub03.nsl.tuis.ac.jp/hub/lti/launch | jupyterhub03.nsl.tuis.ac.jp |     1 |      1 | NULL            |
 | 19 | antares:8000     | https://antares.nsl.tuis.ac.jp:8000/hub/lti/launch | antares.nsl.tuis.ac.jp:8000 |     1 |      1 | NULL            |
 | 20 | aldebaran:443    | https://aldebaran.nsl.tuis.ac.jp/hub/lti/launch    | aldebaran.nsl.tuis.ac.jp    |     1 |      1 | NULL            |
 +----+------------------+----------------------------------------------------+-----------------------------+-------+--------+-----------------+
- tooldomain は baseurl から抽出したようだ. 
- clientid ???

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 ページ一覧 検索 最終更新   ヘルプ   最終更新のRSS