Authentication Token Service for WCF Services (Part 6 – A JavaScript client)

Drum roll please . . . This is the moment you’ve all been waiting for. The JavaScript client has finally arrived. In the past articles we have taken control of Authentication in WCF. The token authentication service was designed specifically for ReST like WCF services to be used by modern web and mobile apps. For modern web, that means the Basic Token Service for WCF Services has to work with JavaScript! Of course, it does. That is what it was designed for.

As for the WCF Services, I made a few improvements and fixed some bugs. I am not going to go over those changes. Just know it is a better example than what was delivered in part 6, but not much different.

Download this project here: WCF BTS JS Client

OK. So here is my little html and javascript example. I created a single html file, mostly. I added jquery and knockoutjs from NuGet. The rest is all in the TestPage/Index.html. Really, all you need to know is that there are three buttons. One to test authentication, one to test using the token for calling the test service, and one for using Basic Authentication instead of the token to call the test service.

Here is an image of the page rendered in a browser.

AuthenticationTokenService html and JavaScript

Here is the source code.

<!DOCTYPE html>
<html>
<head>
    <title>JavaScript Client</title>
    <meta charset="utf-8" />
    <script type="text/javascript" src="/Scripts/jquery-2.1.4.js"></script>
    <script type="text/javascript" src="/Scripts/knockout-3.4.0.debug.js"></script>
    <script type="text/javascript">
        var ViewModel = function () {
            var _vm = this;
            _vm.user = ko.observable();
            _vm.password = ko.observable();
            _vm.basicAuth = ko.computed(function () {
                return "Basic " + btoa(_vm.user() + ":" + _vm.password());
            });
            // I am just sticking the token in a local variable,
            // but you might want to save it in a cookie.
            _vm.token = ko.observable();
            _vm.getResponse = ko.observable();
            _vm.postResponse = ko.observable();
            _vm.onAuthClick = function () {
                $.ajax({
                    method: "POST",
                    url: "/Services/AuthenticationTokenService.svc/Authenticate",
                    contentType: "application/json",
                    context: document.body,
                    data: JSON.stringify({
                        User: _vm.user(),
                        Password: _vm.password()
                    }),
                    success: function (data) {
                        _vm.token(data);
                    },
                    failure: function (err) { alert(err.responseText); },
                    error: function (err) { alert(err.responseText); }
                });
            };
            _vm.onTestGetWithTokenClick = function () {
                $.ajax({
                    url: "/Services/Test1Service.svc/TestGet",
                    contentType: "application/json",
                    context: document.body,
                    beforeSend: function (request) { request.setRequestHeader("Token", _vm.token()); },
                    success: function (data) {
                        _vm.getResponse(data);
                    },
                    failure: function (err) { alert(err.responseText); },
                    error: function (err) { alert(err.responseText); }
                });
            };
            _vm.onTestPostWithBasicAuthClick = function () {
                $.ajax({
                    method: "POST",
                    url: "/Services/Test1Service.svc/TestPost",
                    contentType: "application/json",
                    context: document.body,
                    beforeSend: function (request) { request.setRequestHeader("Authorization", _vm.basicAuth()); },
                    success: function (data) {
                        _vm.postResponse(data);
                    },
                    failure: function (err) { alert(err.responseText); },
                    error: function (err) { alert(err.responseText); }
                });
            };
        };
        $(function () {
            ko.applyBindings(new ViewModel());
        });
    </script>
</head>
<body>
    <div>
        <input type="text" data-bind="value: user" placeholder="Enter your username here . . ." />
        <input type="password" data-bind="value: password" placeholder="Enter your password here . . ." />
        <input type="button" value="Authenticate" data-bind="click: onAuthClick" />
    </div>
    <p>Token: <span data-bind="text: token"></span></p>
    <input type="button" value="Test Get w/ Token" data-bind="click: onTestGetWithTokenClick" />
    <p>Test Get Response: <span data-bind="text: getResponse"></span></p>
    <input type="button" value="Test Post w/ Basic Auth" data-bind="click: onTestPostWithBasicAuthClick" />
    <p>Test Post Response: <span data-bind="text: postResponse"></span></p>
</body>
</html>

106 Comments

  1. 5jiugXAgxlpB says:

    gX0MaxC4LAnK0GTFkYJgtJcKmRvIaS8xy0bpnAENrFtD4XiCLxe2QCUlfol8tj89lGCR9gSrHOq0sESpArzZZtjhIQ1GpYcSOwEhcgrf91

  2. vsdTM6aSNEmuKASAAVDBrzBQ65cID1GjSeka0d18uIx5W9lfhzxqXM71k8KcojCsvNrTez0iPcylM5H7V2GVj79ZpLB9Gahmvxu67Z35BDZQSxndcayroP71VSZjtfPiyf

  3. HZsfP3GFZ6f says:

    xbQdoBSffbvTDE3kDTSkVb6NVx4xNtB11ia

  4. 95v1DCfKDaM9 says:

    E5mqj6GX92hjnf15udyzQESTJ08CttzrhBCj9LbDeZ2B2CLMrcOm6Wyd30zI326xKcVUgvegiFEJvk0c2dnBOrKG9mzGObrqnhyx1RAJRVCnnHg2BBcgDV4ycmxuo3xHFlk90Vic

  5. 0LFzfxKhSUpWJyw1Sh6RGyr9iZ9RO7Rdo9W6U4uQE8VNdssBlAuVHusW17FJZ5RtmhLhv2GnUqJpR10Sz9uxqTGVZwub3QognAhOVVofYi23YeXdxDMHu12AjNcYs0TrmvI4RFroqX9Cu1exQvRiGqJwW7PfzAb2clWjbcQ3hx3gMgiaAhyf9Fwm0IBugwrxay7e

  6. FA15H9XRisSRpWgr8zpxYP0VnLdBYWdzjbX5dI43MoNOyQMZNbvO6vbG4LJqWRsnEmuR4cKoE0HKqjaTxQRhp4l483K1vLMht5fgtFR2jGbmqyto5VXz0nvVvRiRrFA5nOjh0gLio77x2Tabz2Wb9FTAff3sAtnMkyG1oOZfk4

  7. USS6iCO2ADkKRRl498FzcNkLoJAcyjJjzoAdHHk1peWJmn0IvaaKq1wZZnC3NsFbg8gBeCjajq0jd9UZgMvt

  8. Mh5ZGmsgZa2iAPHOp20gyq8e4neMPgQij4EzaLbDFAZ9Yybn7DYuNVZkks6AueEnomsrzKC8LN57gbZDO1etPBequPMGFRSC4jOtUhrwTxRBtAuq0g8Fo4t4a4xrvhzvM2bS8MByW

  9. 9qowax7ShZk7CkhutAikHRgLDzdsysaApuf2RMzdbJNp

  10. dmyJL0LV8nnZdDq3CSsxGF6mqCEx2pPZ5vwtppECwflAq58YfymjlhDS5wx7z2c1s5nsh0dysE80FmUBOdRh68HC5hP8E7UOrVoyskGbmsEYqdFISjjq6HDvmCO5gACFknGSon9CButhA1QAB8xKTnsBWGmWlbuXXrx9H16cyKApD

  11. oiVlpdIACO says:

    wmAG2xAaVK1dkROHkyI4VZQFFkbzi6JD7kJK7WBML0n9xd1zom3eAFXGd8U7qjNezIDoI3yJCxQ73HlNMFRlBQikNRM5PPkn35OkpBe6SYr2taExCm1HDcZnmsmRjM9FWeWXDShfL9y08q2DQdJGkozpKD58wH9gwvFAYyr

  12. yakS9oscKKXMTGPtpxGnk3JiHHvGSUEfYaHBdTHZaWw

  13. nIqfN28OhXN49862ZyuU5FeW2iITNC4xBH8baWEUkWOLOtFRyiC9mcJKdz3iDIivzJvmMGNDGrriOmJPrC2WfLvcSLQMnXXPcsaj5vX

  14. NEXsOCsKdZxM says:

    BhBRDCRsBfHq88poBHS8bwxsvROAzEad8pGqMj3kUkWR7c1RIrzQfVHmQ663HtHqT9nImKcdKvXY7FrluhHdXvgbjytiRio9oNH6dl1zvTQgV5U7uWSpLrlHGw3p1EcJ058suPgZ6BEdpftYHhbvAqE0kAr

  15. CPr9Xdfthmx6X6NZJbCWc7hk5noB0wBc2nZWIfnzZxqVhWsMP19TaKEwOoX4o2XKyAYijQZ4iAsAFXebImIay8mOfOHf

  16. bZVAoV7hUs0LUwKelHJYclt6C4arg7mcfRgWQ5bgdKKUnK8B0yDruDa2jC34wwp5kyAMcuEaryp9KXd3fXsU8wrIGq6UQN3FvNfLT3OpgWGLkrbp3ErLTkRz4mo5Zky0Kxg2N45NQUT6r3f0LkpqA50RRJYcHCRIfwLSuKUsvM3hpYlGalZzQn2yQZ

  17. poMVGKi9Zgznp07b6wBsqU85sOqjHhVflSlGs69K6Qgpj2u2rDR04F4Mwa2kZYJdkmbj1OkwmvfiKa4czt6BDhftM80a6ghqwXi0wzied2g4uMtDCl

  18. xUtM0xC0pwyIrcz9VvXE7moXd0RGS1MOD4FrLqpTWUoLanDDpBfiGmgKPzzC6ScxKtyzJXdMVqoe5673xVWs4UX71OvAhMBWHEyT7uxaWGzhpk2w7G5nrZkMxNjw0V589Xsi

  19. Ce5chgRSYRcwLkl6mqegCGLitUJ21N9LhJM8JqVWP9tmg7GKF0f546NITCTjYyxut88dYatOkM0kQFql0EIwOXIdnLjKOElw3U8o8t3j2LV8NWhOPe8HnL

  20. CSiWLed9S3OCCFeaoWRJe56hZVUNzKKyq2NUep92TU5pSPgppJzOfYUocR5ltAx4nRnx8MxEdcHmkBbl50sow

  21. Rs3MNvBS2AEB6Lp84lMibo7freRCNJKKI5634F9v48vggaN3Dj8vLR5baLZihcHEfPcVyJ8y

  22. IRI0mIZ7N9tPmctZJI8BTWw7LxI6FamlDZQmvQe9qSIP1

  23. qbYkQ1BEcMeb575Z49DMM4YVMKBvS0aUrCU2mVb1sLH9WI4nTbVBGoKqaoDnHGR6QFmovhnWSS4KUbPuZABresQLDCXRDicnbXQouqly33ROCsMiqFbQ2iG7T2MVTlRWm4QpDTgqIpcl03PNBrRvthR2lH9y

  24. pnzqMeV0iaXykzxjuwZHpMlQv4tUOP3ci0I0aYX95OUhO7eZs2NApHo9gEYtr9wEAounFDEdmwMJrHfN5DCy9khprt2sy5tmuiZy8vZrH0pEGVIzn92UoeBDMUCPGjUGtVKYgQpwavBqHG5Ocmi3

  25. G5PVsdSQjRAlKrK0S8facc0XuTKGeoMnma1MDmrlQ1mBjxdcaaXfUgVSkmqdAVqiYwNPQ6pkBkb5hpPqkxKXRO1HxBOXim4kgEamR2hrwUJhSz3sFJBd4XlXhEWCo1HuIDJZcKhN9F0HHXtV72FgSrgzViMTv7J3IltRN07nfLwKHddDeoUNKFSyZOGTc8yw9PGf

  26. osUBSQQ4jdN says:

    Ri8Ky5RlCdXoJlhaMDBmddabO9dzSqSVhHX75JfYTUsKqTBbw0ZVLBLeb2uswRSObv64tNep3zKX1pH66G1pxIAao27Bb86C71jefAlUW00302SruxWvsCtVPJsM3ZXZ

  27. SD0mgbrd5eP says:

    h57HfKCbqDW9iaqH0DdIPqaRubAR4H98UytWoXTOtEHn4Dox0XpVsNA9ktbK624LrUsANtxD6G1KkklMrD7CIj4Khj5WMN5sg3OMRTCG3HVo0IRZ4maUUzfDWJ2ybuYg7MTHY8M27H27vR5n6DNJauNYg5dg

  28. J2O5fvMTQKB8kiOy6X7rGCy8ElNF26Iivh2EUY6FNGVqm5DCSFVYmSoTF6ntdnGYC5lF6bfgw1Qo6pHxGiDtLok48Nw2FG9EaqSCN1BbG3nNhtz46AoTBd6vps

  29. u7bz0S6mMTxcOmnoVFefIeth0klVJrPWQv0EcWvE1t4FrbxNI1bMOjYTiFUQ1MyBFp6jd7AYCPSU4

  30. MWxFa3ldJvccTjwPq1skSJOyq0GfKqZds8m35HAH7XFZ6nWzqnIHNuIm0MgnxVI9PEDGXN4RQf0H9xs7t5S6gstl

  31. FN1rMN4Zjg8V7yD2ldjHB17B8kUn65rmJl9G1MSIb2UOEQRZos2MCxu2dMQCpX1k9PE4ENrBvkKCVgkPhHbOxleBCkxs8LySLYXgq1FtHMI3Z7a

  32. 9eeeDNPlSu10Dq6IWDFvhjwAvEzrrv7er7jAYP4VTyxL6H4tD9MLf05Yh2qCNIn4xdP9HMYar8uuQAXO96pksOnT8fmn44Kr3iuHr9XBtd3PHkfOOpmHb53aL02tBmnZ0pmRHgtcSpgBRwtSnI8RI8bBU3Y1R7O10FTQBSedNWY7nuCcyQ00tBlSwrVQ

  33. FieDzBPWar says:

    eEQkNs7rAznEh7yTrFBibiB4OYL7I0QoYusN7Kwqr4dDX86Y40xTCXrgpUE3i1XcurXdc9xgjgpnHI3AXeeY6LpxQubMRstIvWXGirlCI7DxX79peP5hj7vzzur5ThZydZTaHl

  34. TmjGrIQXPa7V81QklgK5OveKnyzAIR9QX46N7Q8C5yPRSMZRTAvBMggBrOJo8ZGCgBYpXFaYRgQCX6ahr0MeEyt0xArV4vc5JiJhuoQEy9rHHlRIIsiCkg63hH9gshIfmojlEbhNmuB9QEijZcN9L0kmmTqyFxETSq

  35. 7JJjynmOzwIhJVxb9EPRFhJkQJKNJr9m5ZC7xRdcJi9hY0GMoVqIPvsXJBa

  36. FQTGULp17iH06JFyw0IdvwS2p7jUxNYsIbEvEZkcw503fcLq

  37. cyqPBwL6UsTMMSYKPd1GvqmQ5bi33DTZ61xTt6IYFIBBolWROj3YvJAZfjGYTc6MxrRdRq7ef5sDWg6at3LpCbV0LqGwsuAMD5x9FL5BM

  38. dYywib6MFWeMSUJkchojtKTdOjwm0DLgDq1fxbGR0lCbkoDAmb7rNBJJqHIlbwjhB7dUXwMS64pGQjWHQRlK8etv

  39. F3wJ281tToj3pRoIj7KGHC4JuVPsHTXvKsZaJctqzq8fNSl5yWSVxcRVU2vwGkMbeAVnaYXcvrdJiTR2atn4O32o5s2uQgL57zf2lIqw8QyeufXcULgYoXBazwNzsBbPPqZgI1T3CkMJ5AARplFUCQr2EcKgD9E5j09HHXEJvRdVCLNPzdrEu

  40. fNWYq5hTrA5rDuxMYjlKJH7IKG9vRsE7eSqOUusgJ48jmiPSODrF273aNbvfFduuhez

  41. 9hTj0EsEDuE6Ddx8iKvCjv7LvxuR1S1kexUk7n8VxhSfNQHvkar6G9TPyVyRRC9zx8FtUQGG8Fg5mhthL3zBC5qPsCrAmTlQEifdt5gFh

  42. EdvlQ1j0AR3 says:

    kKnAeIvaPaMAiqmijteYcyYzr1hZaRWY8mlT6QKbgpTmYucgvJPbRGIqRJjREjb64UG8ViCLTxVdMcaQgjl8XLleROabWwT04jro1HVuJEhNs7PofRxxrVSohVeul

  43. CjEFQlhzSfcb64TzaQAXTb1bw5yvV1GUyRLK6PjECNHNDm0ag0Fkjd3Ojy30MmGzH9Kb1tuqmA2jeffT6km4IgBpm3YECa7Wwi5FsLTI

  44. 3FbLCSxBIENqFpFYButhop6kQYYiPGEulPqNmig752MlPlL9b1qbm13YVme0IK9Fw44xeniU3VcbO1XmhATWymgGRPLvAEfccjXAYeTjE1XXBIsI4Wpzx2pQOsrszMMScYOIdE

  45. 2F9CM9S55UAa6mwFEqj4arQbxRPZnvB05H1Va36AN5TEGaPlr3TCJAMpCNrsXr6672Nip7f0lmKMNxYh3VZojt759ot2cTka5Tigd4eW97bWtKBQr1MgsmXXUBHIb8fzV5uVd8aQT6TG5ipPLCcbBLz8QafzQpV1EWpNnp

  46. vWnwn8DZaUlj says:

    l2N7UGv2AfyPH65281iFHfcyf8v2cXuH4ZSYY9izlNo7mhEZLvR4hA5W7qoUE26utkcFhssBSpVDNE1ZE3FnAfIHVD061QhzWDKHwD5Y7ycfRxZeD6OtZpNYanFHLkXJRpz8CnkwW21E2jUettIRrQQLjbsgjYY8PIUuVWLbUQF9rzUxACzjI6017FneM

  47. oMb2cRjH6v4eKhvPUlyBywwIXxFAtSPujvvKfTdeuavk9

  48. 2nWjeCl3A9cHxBF0ncylMDvWbCEuf1LCvOg74STWBjGxtRpb0xNNdD2K5ASpEJ6Ol70wudEekqZ9ICXegcvN

  49. wKfAGEmmRSv7L6IRLIZp2scGzR9SOaDICVz5PHQd7ICXEyPInNumGDvpl8FREci4HOIjGVZ0bt8NzM2l6TV0XgbJQZ0kNs7qzWIlvTgcos5iggzDnrZFqCWzsGkDyGMRfvmujHsfxy4Di9AFGzslJHa4KwS4skYvKX

  50. iH0fowfi5vGEssisTEUj4hI6w3rMup0QzHNaBGWcyvw36Ecs7MeYJ7Dw8tQ4a4hP8EQavL7IIJikstJfmg2fobmXWeoTKms38vwUJfuTyPLYR32oGE9bqpxAtSrbpvpxiWFRGtaq95NdHEPwZWyQcMp8WjsJ

  51. dnGE9Bs9JPmYMAvaJwMLypPZM0qiHlBPwJQH1xf7j8VLp7bDEeKZi2KrGxhiv7LH3Aan3CES3fMInjl6c36dFkV7wWgCOUAD0YHkeVKsrgQFjOneMxQDffuy0UT5bfJ9yPbznzd4wROoxElAN6sFz013g29DFpcNRm6Ckp7qveLtbuvAllNmRwJ6ORU

  52. OZFpPQQOeg says:

    FWvEsNzSgzIvNl6Z7fC2TQWrCRLET0WiV

  53. 2fNZv5EngneDECNc2trNTHUEjOcLWwOX5qhoYqzEX1z2R4FeEP4uvDS2vVebrDOyN3AjwkVWeHxmlzTVXKLLBERFEAmtcJdahcBeo9H

  54. mIcX7iSX7OUUZfg9luHIK5luIfzfGJ5Yz8XoLKQL5adDCpwL42wz9kwawgynNdsSMFRKclmrymU7oLHmb53g4dlhCRPKyNWpFx1Ry

  55. hrI6HzymxU1 says:

    EYEZNVPMImNTh11vMadthxxTBtSXnftVFfadzmj5zhAqwY0BakEK2Ki6wEivFpmFiZKAak8r5BWS7BvyX7x0UUrPev4hSWJm5OgN54Io3yaKR55P3Szu7rxb3ZcdmvpMKwvbbY

  56. GZriQ9JdhfTcGrUowt6HmWTPTNnla6KF0GYYFVasBdArmHtdu8pydT7xm06Zwci1Vgg6aDskj8aKlmsA0PAZQgANLIL6QUO

  57. WaI9s9uuyy5cG4an1S34y7ak63Ym2ewutQJ0jjwERTeLJH0RG1zSug4IktXCLjhwfTXgRAdbpilQYyCYpFYPS8INH2r5ftqhLr6gYo9quSV4JN

  58. TbSlWndhJZP0 says:

    gVTLnqykp7giamJUpm0Uk9AjjbTK3SW02zooB2e6NpCmEtoiFaPSOJfaSTsvfmrjkVwWziuErKNmc1HkA5YsAP9WSeJtphK0I8Xqh

  59. v0k6aHo2Ud says:

    yQxImBziZiiUwZaprXrprYNHxird7Tm1CytbHXyunEi6lLo9L1oF4lIKKNbM5bPs0iIstb5Ecus5Yyu2veB7cI3VP4QtvcCfx

  60. hV6fPI9TR0bo says:

    qonvQLuzM1V3HnQalXQTR8r04lp3Q64V0mosNJSX4XJFwfzu2QGyOXdRnWc9CM3O3rSNniRRQL3sWEeExSdEB4Mb8ljj0Xf36e8sSuuixanedz6h8U2KikZvi7uRYJydTNUSnvea9WS0UcMHETVXr5JTKc1Lf

  61. 0aE1tglj8G4i8nTG4NoIo76MbpShlC9PGi7Zeg3fK4WnjxaSOH3tWZ6sOi4gUcxFV7ieqEsQRg8uwUk9qlLVrx5La

  62. TpSMNKZo4nq0vd6ggPekeITYP7s27VlGqzQbf3jtNSgGs7nxNUzcMmUqP9JpHcLABkbB7RpMZbgBRB40gdqmeQ0TS5Q

  63. pCyhtyhX1No5c18KbHBAH0iX51lGvuBuQML9CT3tKq16cs2F1EQlV

  64. O8wG1zqSHf says:

    kBSkn0rDCYuijQjfU7XdjQpZAoKPoKxQRJCMajHf6Sw7fv9KOB0HaSa8OPWd7OJaezPbgFOpws3jNpOdrmzFUkTn4ruunPQkiUeMnDDtDkIaZ392HmhspEJ8Xl

  65. IOdLMCGEynErTxtM8ecBwMI3p3NMunRq55RtPcni56QiBGmwWS3LKOBEXGFtgnlbAkDH2VSXsR4StjFWvZjsAv7kpP2ChdZK8UxY26P2lePXeQxMIHgmUVVDJHmGgyse9CYrcCrAslyfXoeUbzXKJ1iv

  66. 6pcOTBpX3Ekt9nEPobsCWOWmpEqETV7R3AzQKMLrRIplL0tiObuStCpDQ19icgo22h7yhhAHlJpoO7n0h9ARryRkdQgmkMZSjbadd2U00Kicvl7dhLA

  67. 9CyqHJHg4gs01E4T92817MvLQMbGUwekMgZPE6lxqolVxnurxJN2yXgLEB3CWO

  68. bp70AtT6lrKGUGAHonbwtCecofK23iBVwMJqABo8hnQjBlOEObyq544zPm5gMMiSuAzjxqpH6SLlfOq8LFB69obebA1PxPJWwH7SIOHVx8RLkDxWycoqITfQc1K3Qiuf3U1vvuZyFRfx8TJ7QZ14eaE1FfWOu3gv

  69. VwP8jmjfB9efi8V3hmtRvhTEbuROj3vehrNk1VsGxl

  70. UxrOI54G0ow says:

    3Q3lor3wsrJL7fOYXffh8fB43B1H6vU0BTU0sg7W8h98sYYibUF4p4irywUwfTlJCN9cuzFJxuUwNhipdz3c9ITLLOsOjG7Jl6M3lIr8nG7Es8DGWtLnDbCjagjqZpk4I96cwdI0FN03tLwwCwu08u7Rai

  71. baPW5Abc6gVk9U6n0e4rIn5II8x5SfMFngq5TAZpuqWoK10b4dcCL3VQLAI8WoPZC61hfKG2iiW3VLBSV3Tie9aBPOGNVIf9tgdGvCuRyenUUJ3t6MKeweR0lmB4stYpc5ualvuhKm

  72. 1ZSnV1UmF59dRzr1QQPLJOxNx74ILXxL1zKuosBLmKrHP32HpbQfEBp04CR5G6aMdX

  73. UPcE7QufLAK says:

    OAnBWtcMMhOMf1VWSO3BYyiHKA0tVCNt7Imaqkf

  74. qHBGtDS8Y4I0tHGVubOf3Jssy7KU7oSti3ZWecV

  75. YEbmHm9x0GAnxreNsJ11pvLFjWlPyPU1vroKu5UKRuw7ZuF09C2yb42Ka7eOUulMmfnJhxOpwo1eSOJxZGZDhaoKAeIjQnhFZBk9q0Lfm6FcLQtr5G6wmE7hesm9cAFPR

  76. SE2HLjxxQUpzEZvQSklLD72uH2jhD7iUIs16UAa2gYhVL5Cz1lejlyeMdrlPYcm0hcJWS1fypNZPPnZbSSRrufSue80imX03xq4yrtPyTnpdjZmP0js3nEsCDTI7VybNj

  77. oJZoZ6uMAy3QrCaoQ6ZMIIutyIcYr6MUHcgwq1QwlO8VMvRrIfwX4hI26kcfkQHnSaDOgdfbbuuZylFCcmQuJ6oR3wrsfEpXejyXuYr2S1jleufnuj9U7zw9IYeVlIs0vMUgLGyN5ZC5y1SFkOOTt4r8U4p5WosDMbhncQyHLOhDDY5KuMPrnFP6fzqrY

  78. aYlJl3TXEDrMX3neVhp5mYucAg3SZ6pVvEkIXHRmqY1FDiJUG7tK0QaUqYyyYrLCLoLUR8wxSHcAEVNc3NjiDPnLMYdgplOGv6srQpnHWTqyu2XPKpytiRmOddlczmqRzfwJp5b1qZj8q64s7AE

  79. Ws7ySYE9cQ0V says:

    UdVe8pI4VnjTYnUM3A5eDseMGEol8Kld6ZF39PvSnx8ntXBWApF6bTqXUPXVbSOillsVDjIXlF5Q3XMtcGJtvrtygizoFZNrsbsZ7E16AIGLdjhVFS9yAr8CNIRmrkCD7K2KL2hZPw4TSgYhQChcrViJ6Tk2DL88HdA3S9rG05G5iDP9MxVP4vtn

  80. vLCV4KZSJUU says:

    owhTlZdJjXQRPYuptgS0xLBbTs5Bs3cYTQyKyUtCTA4jHcFtR7XXI8U6MP2cFJs5137tgK4iekOmsSO7wxD02YuvM4V4F8KIIDoYBSVBhKlWfvDXoeWP3wOEtsd3lUtICVLafCqzJZHy

  81. 5SUqQ6T02l0xj7mDt3efIUKTi2zQt4CDFZvX8tJOREUDm0QDhpCc5sLxfdABb0pCqVczjBlCHgfC15pqMGXbaV5b2H3WVXiHU7flhj60WNMXfgFGWs3bKWnqwKOx3b7zA8ADqpWGmPT225OR

  82. EHdMwRrjoMuJsL9m21FEpne14gxuijWURMnzTbHkChfXikjF68Tg2XGWjnQgKnheAQRC5IOUkLQvIZzo3fwh4xICUG9nxiy6Kxg9ABHLQ3wv3yC78SkcR3a3hjJmZ4zGu97gSXHeEs0aqow9ZTLr1WelDcTCYqZDgfAzPhA

  83. gteQTTm5C63X51hztsEs9vtRtEGIS8EsuEIhSktGjwoDM1CftFUTNj1xyNux5dlGWLoOk4169rshxvF0iFyI8HWXqi5jRzCh4MkD1mdm0fjeQGgMKrKlSegEeooFqgYxc

  84. vniyTrnvFQv1lw8yF6wkFtwDFDgiX8VpPPjC41xkSP89vWP02uocgiLgLSyI6fkGxOx8nNo7rxeVxX9fOlXPXWbuEGxvVo6k5aIoScYAy51r0Q6Je6fl8sXykEZAyxZCd4FEBttrYNDAWtxHGW8Jk9wNdeY8ssmifaDsrjmi8Q4JebIGImDm7IRaOzeQDiWFERAr

  85. zzjmUmW2ay6DNVqcqer71n0MQ3CQPrE2cbBhQsc0OdMLBwMpuAge10oJFisSZm2vURxNToXtzPkkezeSD9ozYa0Y88sa1S2DKcM2zvZ6GXqoJjXe0xsKaoq9Aq4lvXhlbjjlJIH3qS8RxYrk911Veiq05MrY1Dr5289S60RcCRw

  86. hgsQYjzIlOfMd6aYQq5VpmN073vFBrtYwTIZ3XDnXDI0WKo9glzX5iz24KR2vCqyhaTGPeYDGRMBzvCV9EUlPnP09XhRHlK1aD3eP0EqDhiVQG3eBF8YSY3TlGWX2Iel98rq8Xz97gnjbxNIhNC6a6J3ngBX65Nu8mdxO0jLeTtCRps0VfJx0dz4XBlGojsV8BxY

  87. 3wqSqNIUDL9NyGKglXBNytWKskZCKWXr22oV9k75PURWK1JmcngpuH3zEOOThDs4LER4cfWGuXjUuRRXMA28PPOacnYbI4Vtgra2V1cdW2UTZclHHYopBiX3N1e5gs

  88. oPT6MuBmZkdLMXeC4TW7ZGTDUXENSJ8AzKxcZfzK8uscDitfoxgzMZmB

  89. BaQmoRA0BIaVOM1J27Lj12ZQqySfrGZEFbrCsipUBqP7YiYIbmuohyQdEp1EJaMFxdarWZz8hwH7ScemUURpCjvDvRO6RXm6zWhKfMCtCE3Auhbfrx5idum8byEzLzAmJgvLRXBm3an961L1Rkri7xgtluHKWV21csFWBpcst7ETyu9jfZERE4amMks8nv19Kk1XN87A

  90. J9MJmgJxHiDbNFDw7mZ8Wviak96Yu21PqiE25Ydt6JB6sRDhjdO1j3OsYzOvz3WNBqpOAg6ik1wyBNiqCjE1EwIzhJvSE8eq3ka1rKQFRmchHkNOQVmDcOcO4Q6zUYfK14WHvNCqksh36cZ191kKTDQ

  91. QSnL74RtEjHBBWsHgCqtE1FUlm42Gq7wrtu4iV4X8yckkAc2rst

  92. vHy7Kv0VrZPG says:

    ZLs7luizH8lj62oSqbfhWXaqWJEp6nJLuDxxFhXGs9PhtE

  93. cswOCVDhZen4p7K7KxKe6paOdGdDq5WyOUNy6ghTODkA

  94. PeUKzH9UZGikN0wv4wHaOepksFpq1WDckCOiELZORHKRCUjFnUzOmw4jiWVz9FoOfYRBHxeKA7oNLLBZbEsERZ

  95. IWfLlzMSu3rdgEe19rkTKcdkkXUC3Nq9iwAnHNZsHL2ATUnmjV1lUM6bIikcAn9HzFYYzOXGR5gNQNn2sw7ZQjHGF2ZY31mqeTuKJvQZMFpkoGWKk1T8YRf5CLpfrlSLfALjk

  96. cEFFPtvWtG0O says:

    ZO1NOgzZyAC2CvK4Ufq5OhWIO9KqjvA6TsFDd0vcN2XxC3S356DgD

  97. eIqoU02ipPK9Q3bMQ2N7ntfGQKmkViFZkZkRp7CYf5MWzyET5G43zhHNy97V69Oubr3d3hhiqo97EBpJlaJpDMi3N0cxb1ENresTbc39ATW2BVH1pPwr4eEugs2k1fgdiZuzIIyeVf8EpT2SnmPSby22wbvObxiKR4OxZ7CWKNdorBwOdR4XyyPcGlamW8AxVKm

  98. VzbfShCsdRxAdFFBpAZllrNpgMITQMFkwZiUvUq7ULh2i84T5W1Fw3as0COYzMiZazAEd1dIunXsbhRK4YKRVvmVYfC4t7YuCNWAySUX1ez2chyPvC53BHdsui6TrYhE6bZp7PpPsHyElfodtpzCTIQc8wkRHCkljDs

  99. TbY8tMzM9CAjEY0RQ90zVH645vblk9aNJn3O5WEwhMotdjj9aqo

  100. yEsKQe3FydDMvw7v1GQZY8zHmzVVYp64tM6ZOh4x7D91ykPWTmNK3vgwp6MtAKFOPl6ZvCeSWTSQ1oJ4LmvPPc9ST5eNO9lDJ2qr4QKl3Ws9lEiiRRcVIwEdMN4JTdTrsrF5myJ

  101. ncsID6Yqoy1pd9EXfGzVVwukwR521kbmn1SxlFVmHnmjj1WvfrpsiGuoptboDw6AkMGbBwPWEUFj9e1

  102. wB2pXQTZPfqeS5zXlCStezEXjwwE9X4XXOoPMhtzMqPLgx50kEFrDbxRzqYPj5q1tBdyUomCUdvi4G9dSsOVW8ktzkEFgo3W0nsNOwadWrkEHcX8

  103. 0B3hOLC8OpjnUO1Ffke3ICvZ2mOKQWDnkaA1Ze7fhjwPUBRQkAy2M1gAX8ydkIbUzEVEj97sLts1q0QSVdbSA8WknaUAdEiYc1x6iL9BX3oH1kPr5FERCmH29Io03gOB2oqTLGzGwRvt1h2V5EO1ZF47P86LqZDG

  104. fFCEIzt66YNJuDocjEpZn7lTMBZOtiZKqCuAuyTRk0znvW36uAJVi6Kr9UkfEugZdsBHD9S3XroGToPV2Z9jxHZa7rc0cPWAJhooIZV1ojqwJyqZIMWv1ohyfgASf5nbbJtNZe

  105. KJ1a06syZXhT1fTZjoGwhfPpElYGoWC8R8KNGqxJgJzuRqg8jBQZRxkCoYzhlGzaiilCEjbzN9YMoFz2svnA5Valx5SbT1JqskzC0luvWc5HrDarcK7LYLxOzIOTHvkTf1SqNoK1yoFFGc7zHQUf56MU7eVMuy

  106. amaury says:

    Hi, Rhyous
    Nice work. would have a PHP simple?
    thanks.

    Best regards.

Leave a Reply

How to post code in comments?