无法验证 Moodle 发送的 OAuth1 签名
Can't verify OAuth1 signature sent by Moodle
早上好。
我正在尝试在 OCaml 中实施 OAuth1 身份验证,以通过 Moodle 获得安全的 LTI 请求。
当我想重建 OAuth1 签名时遇到了一些麻烦:它与 Moodle 在 POST 的有效负载中发送给我的签名不匹配。
我按照 twitter documentation and the OAuth core 规范手动构建了 OAuth 签名。
这是我的功能:
let signature_oauth liste_args http_method basic_uri consumer_key secret =
let couple_encode = (* 1 : encode keys/values *)
List.map (
fun (k,v) -> (Netencoding.Url.encode ~plus:false k, Netencoding.Url.encode ~plus:false v))
@@ convert_to_gapi liste_args
in
let couple_trie = (* 2 : sort by key [and value] *)
List.sort
(fun (k1, v1) (k2,v2) ->
let res = compare k1 k2 in
if res = 0 then compare v1 v2 else res) couple_encode
in
let liste_concat = (* 3 : key=value&key2=value2 *)
String.concat "&"
@@ List.map
(fun (k,v) -> k ^ "=" ^ v) couple_trie
in
let signature_base_string = (* 4 :add HTTP_method and uri *)
sprintf "%s&%s&%s" (String.uppercase_ascii http_method) (Netencoding.Url.encode ~plus:false basic_uri) (Netencoding.Url.encode ~plus:false liste_concat)
in
let signing_key = (Netencoding.Url.encode ~plus:false consumer_key) ^ "&" ^ (Netencoding.Url.encode ~plus:false secret) in (* 5 : Créer la signing_key *)
let encodage = Netencoding.Base64.encode
@@ Cstruct.to_string
@@ Nocrypto.Hash.SHA1.hmac (Cstruct.of_string signing_key) (Cstruct.of_string signature_base_string)
in
encodage
- 我的函数调用:
signature_oauth liste_args "post" "localhost:8000/launch" !oauth_consumer_key my_secret
- liste_args参数是由“&”分割的有效载荷(例如:[oauth_version=1.0;oauth_nonce=5aa374e2728914002261bbb7b4bd8e3e ];...).
- convert_to_gapi 函数将此 liste_args 转换为一对列表(例如:[(oauth_version,1.0);(oauth_nonce,5aa374e2728914002261bbb7b4bd8e3e);...]. 它还删除 oauth_signature.
- 有效载荷是 application/x-www-form-urlencoded 编码的。
这是我可以接收的负载示例:
oauth_version=1.0&oauth_nonce=5aa374e2728914002261bbb7b4bd8e3e&oauth_timestamp=1588583843&oauth_consumer_key=rfrezFZErzfzHJmpmkBFT&user_id=2&lis_person_sourcedid=&roles=Instructor%2Curn%3Alti%3Asysrole%3Aims%2Flis%2FAdministrator%2Curn%3Alti%3Ainstrole%3Aims%2Flis%2FAdministrator&context_id=2&context_label=CT&context_title=Cours+test&resource_link_title=Test&resource_link_description=&resource_link_id=2&context_type=CourseSection&lis_course_section_sourcedid=1&lis_result_sourcedid=%7B%22data%22%3A%7B%22instanceid%22%3A%222%22%2C%22userid%22%3A%222%22%2C%22typeid%22%3A%221%22%2C%22launchid%22%3A2096392689%7D%2C%22hash%22%3A%225dbc6bff5ec32c9eee91ee3dcb476b3a553ae5337f8a21b3876b52e4e6cf862c%22%7D&lis_outcome_service_url=http%3A%2F%2Flocalhost%2Fmod%2Flti%2Fservice.php&lis_person_name_given=Admin&lis_person_name_family=User&lis_person_name_full=Admin+User&ext_user_username=user&lis_person_contact_email_primary=user%40example.com&launch_presentation_locale=en&ext_lms=moodle-2&tool_consumer_info_product_family_code=moodle&tool_consumer_info_version=2019111802&oauth_callback=about%3Ablank<i_version=LTI-1p0<i_message_type=basic-lti-launch-request&tool_consumer_instance_guid=localhost&tool_consumer_instance_name=%22New+Site%22&tool_consumer_instance_description=%22New+Site%22&launch_presentation_document_target=iframe&launch_presentation_return_url=http%3A%2F%2Flocalhost%2Fmod%2Flti%2Freturn.php%3Fcourse%3D2%26launch_container%3D3%26instanceid%3D2%26sesskey%3DPPPY9j3N8D&oauth_signature_method=HMAC-SHA1&oauth_signature=fuB7Qm0MXLrHPrvniQsBNcvj7BA%3D
我尝试使用 librairie 创建 OAuth1 签名,但我得到的签名与我的函数相同。
我想我在创建签名时遗漏了一些东西。
我正在使用与 Moodle 相同的参数(在负载中发送)构建签名,使用相同的 密钥 和相同的算法。
- 在我读到的 OAuth1 文档中,他们没有在有效负载中使用 oauth_callback,但 Moodle 使用了。
我应该删除它吗?
- 他们也在谈论 oauth_token。但是 Moodle 没有给我一个,我也不知道如何得到它。必须建立签名?
在此先感谢您的帮助。
我找到了答案。
它有 2 个错误:
第一个是 signing_key :我只需要制作 (Netencoding.Url.encode ~plus:false secret) ^ "&"
另一个来自 Moodle:当您配置 "Automatic tool, based on tool URL" 然后切换到 课程工具 时,Moodle 不关心课程工具的配置。您需要先删除自动工具的所有字段,然后切换到您的课程工具。
帮助我理解的内容:
早上好。
我正在尝试在 OCaml 中实施 OAuth1 身份验证,以通过 Moodle 获得安全的 LTI 请求。 当我想重建 OAuth1 签名时遇到了一些麻烦:它与 Moodle 在 POST 的有效负载中发送给我的签名不匹配。
我按照 twitter documentation and the OAuth core 规范手动构建了 OAuth 签名。
这是我的功能:
let signature_oauth liste_args http_method basic_uri consumer_key secret =
let couple_encode = (* 1 : encode keys/values *)
List.map (
fun (k,v) -> (Netencoding.Url.encode ~plus:false k, Netencoding.Url.encode ~plus:false v))
@@ convert_to_gapi liste_args
in
let couple_trie = (* 2 : sort by key [and value] *)
List.sort
(fun (k1, v1) (k2,v2) ->
let res = compare k1 k2 in
if res = 0 then compare v1 v2 else res) couple_encode
in
let liste_concat = (* 3 : key=value&key2=value2 *)
String.concat "&"
@@ List.map
(fun (k,v) -> k ^ "=" ^ v) couple_trie
in
let signature_base_string = (* 4 :add HTTP_method and uri *)
sprintf "%s&%s&%s" (String.uppercase_ascii http_method) (Netencoding.Url.encode ~plus:false basic_uri) (Netencoding.Url.encode ~plus:false liste_concat)
in
let signing_key = (Netencoding.Url.encode ~plus:false consumer_key) ^ "&" ^ (Netencoding.Url.encode ~plus:false secret) in (* 5 : Créer la signing_key *)
let encodage = Netencoding.Base64.encode
@@ Cstruct.to_string
@@ Nocrypto.Hash.SHA1.hmac (Cstruct.of_string signing_key) (Cstruct.of_string signature_base_string)
in
encodage
- 我的函数调用:
signature_oauth liste_args "post" "localhost:8000/launch" !oauth_consumer_key my_secret
- liste_args参数是由“&”分割的有效载荷(例如:[oauth_version=1.0;oauth_nonce=5aa374e2728914002261bbb7b4bd8e3e ];...).
- convert_to_gapi 函数将此 liste_args 转换为一对列表(例如:[(oauth_version,1.0);(oauth_nonce,5aa374e2728914002261bbb7b4bd8e3e);...]. 它还删除 oauth_signature.
- 有效载荷是 application/x-www-form-urlencoded 编码的。
这是我可以接收的负载示例:
oauth_version=1.0&oauth_nonce=5aa374e2728914002261bbb7b4bd8e3e&oauth_timestamp=1588583843&oauth_consumer_key=rfrezFZErzfzHJmpmkBFT&user_id=2&lis_person_sourcedid=&roles=Instructor%2Curn%3Alti%3Asysrole%3Aims%2Flis%2FAdministrator%2Curn%3Alti%3Ainstrole%3Aims%2Flis%2FAdministrator&context_id=2&context_label=CT&context_title=Cours+test&resource_link_title=Test&resource_link_description=&resource_link_id=2&context_type=CourseSection&lis_course_section_sourcedid=1&lis_result_sourcedid=%7B%22data%22%3A%7B%22instanceid%22%3A%222%22%2C%22userid%22%3A%222%22%2C%22typeid%22%3A%221%22%2C%22launchid%22%3A2096392689%7D%2C%22hash%22%3A%225dbc6bff5ec32c9eee91ee3dcb476b3a553ae5337f8a21b3876b52e4e6cf862c%22%7D&lis_outcome_service_url=http%3A%2F%2Flocalhost%2Fmod%2Flti%2Fservice.php&lis_person_name_given=Admin&lis_person_name_family=User&lis_person_name_full=Admin+User&ext_user_username=user&lis_person_contact_email_primary=user%40example.com&launch_presentation_locale=en&ext_lms=moodle-2&tool_consumer_info_product_family_code=moodle&tool_consumer_info_version=2019111802&oauth_callback=about%3Ablank<i_version=LTI-1p0<i_message_type=basic-lti-launch-request&tool_consumer_instance_guid=localhost&tool_consumer_instance_name=%22New+Site%22&tool_consumer_instance_description=%22New+Site%22&launch_presentation_document_target=iframe&launch_presentation_return_url=http%3A%2F%2Flocalhost%2Fmod%2Flti%2Freturn.php%3Fcourse%3D2%26launch_container%3D3%26instanceid%3D2%26sesskey%3DPPPY9j3N8D&oauth_signature_method=HMAC-SHA1&oauth_signature=fuB7Qm0MXLrHPrvniQsBNcvj7BA%3D
我尝试使用 librairie 创建 OAuth1 签名,但我得到的签名与我的函数相同。
我想我在创建签名时遗漏了一些东西。
我正在使用与 Moodle 相同的参数(在负载中发送)构建签名,使用相同的 密钥 和相同的算法。
- 在我读到的 OAuth1 文档中,他们没有在有效负载中使用 oauth_callback,但 Moodle 使用了。 我应该删除它吗?
- 他们也在谈论 oauth_token。但是 Moodle 没有给我一个,我也不知道如何得到它。必须建立签名?
在此先感谢您的帮助。
我找到了答案。 它有 2 个错误:
第一个是 signing_key :我只需要制作 (Netencoding.Url.encode ~plus:false secret) ^ "&"
另一个来自 Moodle:当您配置 "Automatic tool, based on tool URL" 然后切换到 课程工具 时,Moodle 不关心课程工具的配置。您需要先删除自动工具的所有字段,然后切换到您的课程工具。
帮助我理解的内容: