コード例 #1
0
ファイル: FacebookSession.cs プロジェクト: lkh/thanhpham
        /// <summary>
        /// Generates a MD5 signature for the Facebook session.
        /// </summary>
        /// <param name="secret">
        /// The app secret.
        /// </param>
        /// <param name="dictionary">
        /// The dictionary.
        /// </param>
        /// <returns>
        /// Returns the generated signature.
        /// </returns>
        /// <remarks>
        /// http://developers.facebook.com/docs/authentication/
        /// </remarks>
        internal static string GenerateSessionSignature(string secret, IDictionary <string, object> dictionary)
        {
            if (string.IsNullOrEmpty(secret))
            {
                throw new ArgumentNullException("secret");
            }
            if (dictionary == null)
            {
                throw new ArgumentNullException("dictionary");
            }

            var payload = new StringBuilder();

            // sort by the key and remove "sig" if present
            var parts = (from a in dictionary
                         orderby a.Key
                         where a.Key != "sig"
                         select string.Format(CultureInfo.InvariantCulture, "{0}={1}", a.Key, a.Value)).ToList();

            parts.ForEach(s => payload.Append(s));
            payload.Append(secret);

            var hash = FacebookWebUtils.ComputerMd5Hash(Encoding.UTF8.GetBytes(payload.ToString()));

            var signature = new StringBuilder();

            foreach (var h in hash)
            {
                signature.Append(h.ToString("x2", CultureInfo.InvariantCulture));
            }

            return(signature.ToString());
        }
コード例 #2
0
        public void ItShouldBeDecodedCorrectly()
        {
            // encryptedData = FacebookUtils.Base64UrlDecode("YGym4poQnMTrEgiAOkFTVI85ll5RuUiEl-IgqfxTOTHQNIvVVI8Y8kVuOoeKaWOeassWFTEv0Qg_7wCCBEen7lUBBzlFJ1V63HJ3Af0SIngcxWTJ7L6YLatMmwXgDAvWn5PsfqzWk4ml9h9DLnYptWHmDGL6iBiOhN7WyI7p6oEpVriFuJw_chLoPb8a3vGDnoW8e2Sxx06A2x2xkiapvg");
            var encryptedData = new byte[]
            {
                96, 108, 166, 226, 154, 16, 156, 196, 235, 18, 8, 128, 58, 65, 83, 84, 143, 57, 150,
                94, 81, 185, 72, 132, 151, 226, 32, 169, 252, 83, 57, 49, 208, 52, 139, 213, 84, 143,
                24, 242, 69, 110, 58, 135, 138, 105, 99, 158, 106, 203, 22, 21, 49, 47, 209, 8, 63,
                239, 0, 130, 4, 71, 167, 238, 85, 1, 7, 57, 69, 39, 85, 122, 220, 114, 119, 1,
                253, 18, 34, 120, 28, 197, 100, 201, 236, 190, 152, 45, 171, 76, 155, 5, 224, 12,
                11, 214, 159, 147, 236, 126, 172, 214, 147, 137, 165, 246, 31, 67, 46, 118, 41, 181,
                97, 230, 12, 98, 250, 136, 24, 142, 132, 222, 214, 200, 142, 233, 234, 129, 41,
                86, 184, 133, 184, 156, 63, 114, 18, 232, 61, 191, 26, 222, 241, 131, 158, 133, 188,
                123, 100, 177, 199, 78, 128, 219, 29, 177, 146, 38, 169, 190
            };

            // key = Encoding.UTF8.GetBytes("13750c9911fec5865d01f3bd00bdf4db")
            var key = new byte[]
            {
                49, 51, 55, 53, 48, 99, 57, 57, 49, 49, 102, 101, 99, 53, 56, 54, 53, 100, 48, 49, 102, 51,
                98, 100, 48, 48, 98, 100, 102, 52, 100, 98
            };

            // iv = FacebookUtils.Base64UrlDecode("fDLJCW-yiXmuNa24eSarJg")
            var iv = new byte[] { 124, 50, 201, 9, 111, 178, 137, 121, 174, 53, 173, 184, 121, 38, 171, 38 };

            var result = FacebookWebUtils.DecryptAes256CBCNoPadding(encryptedData, key, iv);

            Assert.Equal(result, "{\"access_token\":\"101244219942650|2.wdrSr7KyE_VwQ0fjwOfW9A__.3600.1287608400-499091902|XzxMQd-_4tjlC2VEgide4rmg6LI\",\"expires_in\":6412,\"user_id\":\"499091902\"}");
        }
コード例 #3
0
ファイル: GivenADataThen.cs プロジェクト: lkh/thanhpham
        public void ItShouldGenerateCorrectMd5Hash()
        {
            var input    = System.Text.Encoding.UTF8.GetBytes("access_token=124973200873702|2.OAaqICOCk_B4sZNv59q8Yg__.3600.1295118000-100001327642026|vz4H9xjlRZPfg2quCv0XOM5g9_oexpires=1295118000secret=lddpssZCuPoEtjcDFcWtoA__session_key=2.OAaqICOCk_B4sZNv59q8Yg__.3600.1295118000-100001327642026uid=1000013276420263b4a872617be2ae1932baa1d4d240272");
            var expected = new byte[] { 29, 149, 250, 75, 61, 250, 91, 38, 192, 28, 138, 200, 103, 109, 128, 184 };

            var md5Hash = FacebookWebUtils.ComputerMd5Hash(input);

            Assert.True(expected.SequenceEqual(md5Hash));
        }
コード例 #4
0
        public void CIsSetCorrectly(string cancelUrlPath)
        {
            var result = GetCanvasUrlBuilder(cancelUrlPath).PrepareCanvasLoginUrlOAuthState(
                _returnUrlPath, null, _state, _loginParameters);

            cancelUrlPath = FacebookWebUtils.RemoveStartingSlash(cancelUrlPath);

            Assert.Equal("http://apps.beta.facebook.com/csharpsamplestwo/" + cancelUrlPath, result["c"]);
        }
コード例 #5
0
        public void ItShouldBeDecodedCorrectly()
        {
            var encryptedData = FacebookWebUtils.Base64UrlDecode("YGym4poQnMTrEgiAOkFTVI85ll5RuUiEl-IgqfxTOTHQNIvVVI8Y8kVuOoeKaWOeassWFTEv0Qg_7wCCBEen7lUBBzlFJ1V63HJ3Af0SIngcxWTJ7L6YLatMmwXgDAvWn5PsfqzWk4ml9h9DLnYptWHmDGL6iBiOhN7WyI7p6oEpVriFuJw_chLoPb8a3vGDnoW8e2Sxx06A2x2xkiapvg");
            var key           = System.Text.Encoding.UTF8.GetBytes("13750c9911fec5865d01f3bd00bdf4db");
            var iv            = FacebookWebUtils.Base64UrlDecode("fDLJCW-yiXmuNa24eSarJg");

            var result = FacebookWebUtils.DecryptAes256CBCNoPadding(encryptedData, key, iv);

            Assert.Equal(result, "{\"access_token\":\"101244219942650|2.wdrSr7KyE_VwQ0fjwOfW9A__.3600.1287608400-499091902|XzxMQd-_4tjlC2VEgide4rmg6LI\",\"expires_in\":6412,\"user_id\":\"499091902\"}");
        }
コード例 #6
0
        public void ItShouldComputeTheHashCorrectly()
        {
            var data = System.Text.Encoding.UTF8.GetBytes("eyJhbGdvcml0aG0iOiJBRVMtMjU2LUNCQyBITUFDLVNIQTI1NiIsImlzc3VlZF9hdCI6MTI4NzYwMTk4OCwiaXYiOiJmRExKQ1cteWlYbXVOYTI0ZVNhckpnIiwicGF5bG9hZCI6IllHeW00cG9Rbk1UckVnaUFPa0ZUVkk4NWxsNVJ1VWlFbC1JZ3FmeFRPVEhRTkl2VlZJOFk4a1Z1T29lS2FXT2Vhc3NXRlRFdjBRZ183d0NDQkVlbjdsVUJCemxGSjFWNjNISjNBZjBTSW5nY3hXVEo3TDZZTGF0TW13WGdEQXZXbjVQc2ZxeldrNG1sOWg5RExuWXB0V0htREdMNmlCaU9oTjdXeUk3cDZvRXBWcmlGdUp3X2NoTG9QYjhhM3ZHRG5vVzhlMlN4eDA2QTJ4MnhraWFwdmcifQ");
            var key  = System.Text.Encoding.UTF8.GetBytes("13750c9911fec5865d01f3bd00bdf4db");

            var expected = new byte[]
            {
                183, 173, 233, 101, 14, 16, 221, 148, 199, 38, 221, 33, 58, 194, 171, 99, 106, 91, 219,
                204, 81, 149, 219, 150, 210, 152, 56, 148, 191, 217, 134, 94
            };

            var hash = FacebookWebUtils.ComputeHmacSha256Hash(data, key);

            Assert.True(expected.SequenceEqual(hash));
        }
コード例 #7
0
        public void ItShouldRemoveTheTrailingSlash(string inputUrl, string expectedUrl)
        {
            var result = FacebookWebUtils.RemoveTrailingSlash(inputUrl);

            Assert.Equal(expectedUrl, result);
        }
コード例 #8
0
        public void ItShouldConvertToStringCorrectly(string base64UrlString, byte[] encodedData)
        {
            var result = FacebookWebUtils.Base64UrlEncode(encodedData);

            Assert.Equal(result, base64UrlString);
        }
コード例 #9
0
        public void ItDecodesCorrectly(string base64UrlString, byte[] decodedData)
        {
            var result = FacebookWebUtils.Base64UrlDecode(base64UrlString);

            Assert.True(result.SequenceEqual(decodedData));
        }
コード例 #10
0
        public void ItShouldReturnEmptyString()
        {
            var result = FacebookWebUtils.RemoveTrailingSlash("");

            Assert.Equal(string.Empty, result);
        }
コード例 #11
0
        public void ItShouldBeTheSameAsInput(string input, string expected)
        {
            var result = FacebookWebUtils.RemoveTrailingSlash(input);

            Assert.Equal(expected, result);
        }
コード例 #12
0
        public void TheResultShouldBeEmptyString()
        {
            var result = FacebookWebUtils.RemoveTrailingSlash("/");

            Assert.Equal(string.Empty, result);
        }
コード例 #13
0
        /// <summary>
        /// Parse the signed request string.
        /// </summary>
        /// <param name="secret">
        /// The secret.
        /// </param>
        /// <param name="signedRequestValue">
        /// The signed request value.
        /// </param>
        /// <param name="maxAge">
        /// The max age.
        /// </param>
        /// <param name="currentTime">
        /// The current time.
        /// </param>
        /// <param name="throws">
        /// The throws.
        /// </param>
        /// <returns>
        /// The FacebookSignedRequest.
        /// </returns>
        internal static IDictionary <string, object> TryParse(string secret, string signedRequestValue, int maxAge, double currentTime, bool throws)
        {
            if (string.IsNullOrEmpty(secret))
            {
                throw new ArgumentNullException("secret");
            }
            if (string.IsNullOrEmpty(signedRequestValue))
            {
                throw new ArgumentNullException("signedRequestValue");
            }
            if (maxAge < 0)
            {
                throw new ArgumentOutOfRangeException("maxAge", "maxAge must be greater than 0");
            }
            if (currentTime < 0)
            {
                throw new ArgumentOutOfRangeException("currentTime", "currentTime must be greater than 0");
            }

            try
            {
                // NOTE: currentTime added to parameters to make it unit testable.
                string[] split = signedRequestValue.Split('.');
                if (split.Length != 2)
                {
                    // need to have exactly 2 parts
                    throw new InvalidOperationException(FacebookUtils.Resources.InvalidSignedRequest);
                }

                string encodedSignature = split[0];
                string encodedEnvelope  = split[1];

                if (string.IsNullOrEmpty(encodedSignature))
                {
                    throw new InvalidOperationException(FacebookUtils.Resources.InvalidSignedRequest);
                }

                if (string.IsNullOrEmpty(encodedEnvelope))
                {
                    throw new InvalidOperationException(FacebookUtils.Resources.InvalidSignedRequest);
                }

                var envelope = (IDictionary <string, object>)JsonSerializer.Current.DeserializeObject(Encoding.UTF8.GetString(FacebookWebUtils.Base64UrlDecode(encodedEnvelope)));

                string algorithm = (string)envelope["algorithm"];

                if (!algorithm.Equals("AES-256-CBC HMAC-SHA256") && !algorithm.Equals("HMAC-SHA256"))
                {
                    // TODO: test
                    throw new InvalidOperationException("Invalid signed request. (Unsupported algorithm)");
                }

                byte[] key    = Encoding.UTF8.GetBytes(secret);
                byte[] digest = FacebookWebUtils.ComputeHmacSha256Hash(Encoding.UTF8.GetBytes(encodedEnvelope), key);

                if (!digest.SequenceEqual(FacebookWebUtils.Base64UrlDecode(encodedSignature)))
                {
                    throw new InvalidOperationException(Facebook.Web.Properties.Resources.InvalidSignedRequestSignature);
                }

                IDictionary <string, object> result;

                if (algorithm.Equals("HMAC-SHA256"))
                {
                    // for requests that are signed, but not encrypted, we're done
                    result = envelope;
                }
                else
                {
                    result = new JsonObject();

                    result["algorithm"] = algorithm;

                    long issuedAt = (long)envelope["issued_at"];

                    if (issuedAt < currentTime)
                    {
                        throw new InvalidOperationException(Web.Properties.Resources.OldSignedRequest);
                    }

                    result["issued_at"] = issuedAt;

                    // otherwise, decrypt the payload
                    byte[] iv            = FacebookWebUtils.Base64UrlDecode((string)envelope["iv"]);
                    byte[] rawCipherText = FacebookWebUtils.Base64UrlDecode((string)envelope["payload"]);
                    var    plainText     = FacebookWebUtils.DecryptAes256CBCNoPadding(rawCipherText, key, iv);

                    var payload = (IDictionary <string, object>)JsonSerializer.Current.DeserializeObject(plainText);
                    result["payload"] = payload;
                }

                return(result);
            }
            catch
            {
                if (throws)
                {
                    throw;
                }

                return(null);
            }
        }