Login / Logout scenario in SPA

2 posts, 0 answers
  1. Jacques
    Jacques avatar
    3 posts
    Member since:
    Sep 2012

    Posted 24 Feb 2015 Link to this post

    I have a single page app built with KendoUI javascript framework from Telerik. The pages are loaded from a client router (samples and docs here) and javascript modules are added with RequireJS. I added some authentication mechanism based on the WIF Session Authentication Module (SAM) based on this article from Dominick Baier : http://leastprivilege.com/2012/02/09/replacing-asp-net-forms-authentication-with-wif-session-authentication-for-the-better/ It works very similar to the Forms authentication since I am just adding a authentication tag with a form url like this :

    <authentication mode="None">
        <forms loginUrl="~/#/Public/Accueil" timeout="90" slidingExpiration="true" requireSSL="true" />

    It works fine under a normal .NET MVC4 scenario, but doesn't quite work as well when in a SPA with javascript routing. The view is displayed when the user is not logged, but nothing happens when I click on "Log in" button because. Does anyone have a clue about what I should do to keep the sync between server and client whenever a redirection on the login page occurs on the server ?

    When you use a authentication tag and specify a form url, a 302 response is sent to the client every time a page that needs authorization is called without the auth cookie. The URL to wich the browser is redirected then is the one specified in the web.config under the authentication tag (like in my question it is "<base_url>/#/Public/Acceuil") and the url requested originaly requested is appended as parameter like this : "<base_url>/#/Public/Acceuil?RETURNURL=Private/Profile>". The browser then make a GET request to this new url and gets a 200 with the login view. That works just fine. The problem is that the client methods are in a separate js file that is normally loaded via the client Kendo Router using RequireJS :

    router-config.js :

    define(['jquery', 'lib/pubsub'],
    function ($, pubsub) {
    // Index
    var publicAccueil =
        url: "/Public/Accueil",
        activate: function () {
            var that = this;
            require(['app/Public/Accueil'], function () { renderView(that); });
        html: null
    // MDPOublie
    var publicMDPOublie =
        url: "/Public/MDPOublie",
        activate: function () {
            var that = this;
            require(['app/Public/MDPOublie'], function () { renderView(that); });
        html: null
    // Profil
    var privateProfile =
        url: "/Private/Profile",
        activate: function () {
            var that = this;
            require(['app/Private/Profile'], function () { renderView(that); });
        html: null
    var renderView = function(view, id, params) {
            $.publish("viewActivated", [ view, id, params ]);
    return {
            publicAccueil: publicAccueil,
            publicMDPOublie: publicMDPOublie,
            privateProfile: privateProfile,

    Then, in the router file, the route are registered to call the "activate" fonction defined in the config object "routeConfig.privateProfile" for the route, that's what loads the Accueil.js file located unde "app/Public/".

    router.js :

    ], function ($, kendo, routeConfig, Code52) {
    var router = new kendo.Router({
    routeMissing: function (e) { alert("Route not defined : " + e.url); },
    change: function (e) {
    //Default route
    router.route("/", function() {
    var cheminUrl = window.location.pathname;
    if (cheminUrl === "/") {
    router.route(routeConfig.publicAccueil.url, function () { routeConfig.publicAccueil.activate(); });
    router.route(routeConfig.publicMDPOublie.url, function () { routeConfig.publicMDPOublie.activate(); });
    router.route(routeConfig.privateProfile.url, function () { routeConfig.privateProfile.activate(); });
    $.subscribe("viewActivated", function (view, id, params) {
            //If the view is not in local cache, we load it from server
            if (view.html === null || view.html === "") {
                    url: view.url + (id !== undefined ? "/" + id : "")
                }).done(function (r) {
                    //Once loaded, we cache it
                    view.html = r.data;
                    //Render the view by injecting innerHtml property
                    //Event published just for each script to have a place to init
                    if (view.html !== "")
                        id !== undefined ? $.publish(view.url, [id, params]) : $.publish(view.url, [params]);
                .fail(function (jqXHR, textStatus) {
                    alert("Request failed: " + textStatus);
            } else { //If the view was already cached, we load thie cached version
                id !== undefined ? $.publish(view.url, [id, params]) : $.publish(view.url, [params]);

        return {
            router: router

    The other obvious problem here is when I disconnect by calling a Disconnect method. I just flush the auth cookie then, but all the "private" pages are still in cache, which means they'll be displayed if you hit the corresponding route.

    So, is there a sample or tutorial somewhere on how to manage this kind of "login / logout" scenarios ?

  2. Petyo
    Petyo avatar
    2437 posts

    Posted 26 Feb 2015 Link to this post

    Hi Jacques,

    the simplest thing you can do upon logout is to refresh the page, thus removing all sensitive data loaded. 

    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
Back to Top