/// <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="parametersIn">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 parametersIn, string consumerSecret) { // Work with a copy of the parameters so the caller's data is not changed var parameters = new NameValueCollection(parametersIn); // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1 // The query component is parsed into a list of name/value pairs by treating it as an // "application/x-www-form-urlencoded" string, separating the names and values and // decoding them as defined by [W3C.REC - html40 - 19980424], Section 17.13.4. // // Unescape the query so that it is not doubly escaped by UrlEncodingParser. var querystring = new UrlEncodingParser(Uri.UnescapeDataString(url.Query)); parameters.Add(querystring); var signatureBase = GenerateSignatureBase(httpMethod, url, parameters); // Note that in LTI, the TokenSecret (second part of the key) is blank var hmacsha1 = new HMACSHA1 { Key = Encoding.ASCII.GetBytes($"{consumerSecret.ToRfc3986EncodedString()}&") }; var dataBuffer = Encoding.ASCII.GetBytes(signatureBase); var hashBytes = hmacsha1.ComputeHash(dataBuffer); return Convert.ToBase64String(hashBytes); }
/// <summary> /// Calculate the OAuth Signature for this request using custom parameters. /// </summary> /// <param name="parameters">The set of parameters to be included in the signature.</param> /// <param name="consumerSecret">The OAuth Consumer Secret to use.</param> /// <returns>The calculated OAuth Signature.</returns> /// <remarks> /// This is typically used by Tool Consumers that perform custom parameter substitution prior /// to signing the request. /// </remarks> public string GenerateSignature(NameValueCollection parameters, string consumerSecret) { // The LTI spec says to include the querystring parameters // when calculating the signature base string. Unescape the // query so that it is not doubly escaped by UrlEncodingParser. var querystring = new UrlEncodingParser(Uri.UnescapeDataString(Url.Query)); parameters.Add(querystring); var signature = OAuthUtility.GenerateSignature(HttpMethod, Url, parameters, consumerSecret); // Now remove the querystring parameters so they are not sent twice // (once in the action URL and once in the form data) foreach (var key in querystring.AllKeys) { parameters.Remove(key); } return signature; }