如何验证moodle LTI发布请求

时间:2014-10-11 01:10:57

标签: oauth moodle lti

我创建了一个与moodle集成的LTI工具。我创建了一个消费者密钥和秘密,但我不确定如何验证(验证)启动请求。

以下是我收到的原始请求,因此我猜测我需要验证oauth_signature以验证请求。我已经遇到过一些示例,但我也需要oauth令牌,但它在启动请求中没有返回。

我真的很感激任何帮助!

POST http://ltitest.cloudapp.net/launch HTTP/1.1
Host: ltitest.cloudapp.net
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://demo.moodle.net/mod/lti/launch.php?id=7
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 1296

oauth_version=1.0&oauth_nonce=d8e900f0b71e76c4b12e89681c9b5cb9&oauth_timestamp=1412987714&oauth_consumer_key=username&resource_link_id=1&resource_link_title=tool&resource_link_description=&user_id=2&roles=Instructor%2Curn%3Alti%3Asysrole%3Aims%2Flis%2FAdministrator&context_id=2&context_label=My+first+course&context_title=My+first+course&launch_presentation_locale=en&lis_result_sourcedid=%7B%22data%22%3A%7B%22instanceid%22%3A%221%22%2C%22userid%22%3A%222%22%2C%22launchid%22%3A449414780%7D%2C%22hash%22%3A%2226f6510ff6e91e1a7814805190c01a9e9d02575de135d7a1483a70626bae8782%22%7D&lis_outcome_service_url=http%3A%2F%2Fdemo.moodle.net%2Fmod%2Flti%2Fservice.php&lis_person_name_given=Admin&lis_person_name_family=User&lis_person_name_full=Admin+User&lis_person_contact_email_primary=demo%40moodle.a&ext_lms=moodle-2&tool_consumer_info_product_family_code=moodle&tool_consumer_info_version=2014051202&oauth_callback=about%3Ablank&lti_version=LTI-1p0&lti_message_type=basic-lti-launch-request&tool_consumer_instance_guid=demo.moodle.net&launch_presentation_return_url=http%3A%2F%2Fdemo.moodle.net%2Fmod%2Flti%2Freturn.php%3Fcourse%3D2%26launch_container%3D3%26instanceid%3D1&oauth_signature_method=HMAC-SHA1&oauth_signature=JmFLDbhi%2FstYEFTSNA%2F44biCQkM%3D&ext_submit=Press+to+launch+this+activity

2 个答案:

答案 0 :(得分:0)

LTI是IMS全球学习联盟定义的通信协议,允许工具提供商(TP)的远程工具和内容安全地集成到工具消费者(TC)中。

与OAuth 1.0一样,生成签名,方法是对所有请求参数进行排序,添加使用者密钥,时间戳和nonce,并使用共享密钥将它们一起散列。您必须验证签名并为经过身份验证的请求调用请求的链接。

RFC 5849中,您可以找到相关的文档和示例。

token
         A unique identifier issued by the server and used by the client
         to associate authenticated requests with the resource owner
         whose authorization is requested or has been obtained by the
         client.  Tokens have a matching shared-secret that is used by
         the client to establish its ownership of the token, and its
         authority to represent the resource owner.

   The original community specification used a somewhat different
   terminology that maps to this specifications as follows (original
   community terms provided on left):

   Consumer:  client

   Service Provider:  server

   User:  resource owner

   Consumer Key and Secret:  client credentials

   Request Token and Secret:  temporary credentials

   Access Token and Secret:  token credentials

同时检查:Validating launches

答案 1 :(得分:0)

我在一段时间后解决了这个问题,虽然对于寻找解决方案的人来说它可能会派上用场。

首先获取oauth lib:https://www.nuget.org/packages/Microsoft.Owin.Security.OAuth/

// parse out the signature from the http req.
ProviderRequest providerRequest = new ProviderRequest();
providerRequest.ParseRequest(httpRequest, false);
String httpSig = providerRequest.Signature;

// now generate a new signature from our secret
String generatedSig = GenerateOAuthSignature(secret, req);

if( generatedSig == httpSig ){
   // valid oauth request
}

生成OAuthSignature是owin lib的一部分,但是代码的作用是什么:

    internal static string GenerateSignatureBase(string httpMethod, Uri url, NameValueCollection parameters)
    {
        var normalizedUrl = string.Format("{0}://{1}", url.Scheme, url.Host);
        if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443)))
        {
            normalizedUrl += ":" + url.Port;
        }
        normalizedUrl += url.AbsolutePath;

        StringBuilder signatureBase = new StringBuilder();
        signatureBase.Append(httpMethod.ToRfc3986EncodedString().ToUpper()).Append('&');
        signatureBase.Append(normalizedUrl.ToRfc3986EncodedString()).Append('&');

        var excludedNames = new List<string> { OAuthConstants.SignatureParameter };
        signatureBase.Append(parameters.ToNormalizedString(excludedNames).ToRfc3986EncodedString());

        return signatureBase.ToString();
    }

    /// <summary>
    /// Generates a signature using the specified signatureType 
    /// </summary>
    /// <param name="httpMethod">The http method used</param>
    /// <param name="url">The full url to be signed</param>
    /// <param name="parameters">The collection of parameters to sign</param>
    /// <param name="consumerSecret">The OAuth consumer secret used to generate the signature</param>
    /// <returns>A base64 string of the hash value</returns>
    public static string GenerateSignature(string httpMethod, Uri url, NameValueCollection parameters, string consumerSecret)
    {
        var signatureBase = GenerateSignatureBase(httpMethod, url, parameters);

        // Note that in LTI, the TokenSecret (second part of the key) is blank
        HMACSHA1 hmacsha1 = new HMACSHA1();
        hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&", consumerSecret.ToRfc3986EncodedString()));

        var dataBuffer = Encoding.ASCII.GetBytes(signatureBase);
        var hashBytes = hmacsha1.ComputeHash(dataBuffer);

        return Convert.ToBase64String(hashBytes);
    }