Good morning.
I'm trying to implement OAuth1 authentification in OCaml to get secure LTI request with Moodle. I have some trouble when I want to rebuild the OAuth1 signature : it doesn't match with the signature Moodle sent me in the POST's payload.
I made manually the build of OAuth's signature following the twitter documentation and the OAuth core specification.
Here is my function :
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
Here is an example of a payload I can receive :
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
I tried to make the OAuth1 signature with a librairie but I got the same signature as my function.
I guess I am missing something in the creation of signature.
I'm building the signature with the same parameters as Moodle (sent in the payload), using the same secret key and the same algorithm.
Thanks in advance for your help.
I found the answer. It had 2 errors :
First one was the signing_key : I only need to make (Netencoding.Url.encode ~plus:false secret) ^ "&"
The other was from Moodle : when you configure an "Automatic tool, based on tool URL" and then switch to a Course Tool, Moodle doesn't care about the Course Tool's configuration. You need first to delete all the fields of the Automatic tool and then switch to your Course Tool.
What helped me to understand: