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.
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>
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
FWvEsNzSgzIvNl6Z7fC2TQWrCRLET0WiV
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
OAnBWtcMMhOMf1VWSO3BYyiHKA0tVCNt7Imaqkf
qHBGtDS8Y4I0tHGVubOf3Jssy7KU7oSti3ZWecV
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
Hi, Rhyous
Nice work. would have a PHP simple?
thanks.
Best regards.