0

We've got an Angular admin site up on an Azure VM. The API is build out using ServiceStack, and we've got a problem where when we login and say "Remember Me", our users aren't getting remembered.

Here's our AppHost plugin bit.

Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[]
    {
        // it seems as though order matters here. If these are reversed, CredentialsAuth doesn't work.
        new CustomCredentialsAuthProvider(container),
        new CustomBasicAuthProvider(container)
    })
    {
        HtmlRedirect = "~/login.html"
    });

And in Angular we initialize our credentials

    $scope.credentials = {
        userName: '',
        password: '',
        rememberMe: false
    };
    $scope.login = function (credentials) {

        if (!$scope.signinForm.$valid) {
            $scope.submitted = true;
            toaster.pop(nullFieldAlert);
            return;
        }

        authService.save(credentials,

            // Success
            function (data) {
                $rootScope.authenticated = true;
                history.back();
            },

            // Failure
            function (e) {
                handleErrors(e);
            });
    };

and then when the user logs in, they have the option to change rememberMe = true;

Unfortunately our session expires within minutes (and sometimes seconds) with or without rememberMe being set.

What magic do we need to do in order to get sessions to last > 3 minutes on Azure, and get RememberMe working?

Chase Florell
  • 46,378
  • 57
  • 186
  • 376

1 Answers1

2

Sessions Timing Out

Your concern is that your sessions are expiring prematurely. This is something that you should test independently of AngularJS, because as I note below, I suspect the problem is AngularJS related.

You should directly authenticate with your ServiceStack Api from your browser: You can do this by navigating to:

<your-api-url>/Auth?UserName=username&Password=password&x-http-method-override=POST

Replacing username and password as appropriate. That should get you a valid session.

Then you should confirm that you have a valid session by checking for the ss-id cookie in your browsers Developer Console.

Make some requests for data to your secure service with this session, determine how long you can access this data for before the session expires. I suspect that direct interaction in this way doesn't fail, and rather your issue is caused when you use AngularJS.

Loosing $rootScope.authenticated state

I may be spitballing here because people build their AngularJS application in many different and exciting ways, and this is my interpretation of the partial code you have provided.

I think this issue may be to do with how you recording your client side authentication state using AngularJS, rather than a ServiceStack issue.

When your AuthService sends the credentials to ServiceStack for authentication, it will do so using Angular's $http Service. ServiceStack will reply with a valid session cookie, given that your credentials were valid. This session cookie will be sent by Angular for any of the requests that follow.

// Success
function (data) {
    $rootScope.authenticated = true;
    history.back(); // $rootScope on the other page won't be set when you go back
}

However it looks like you are determining authentication state based on the variable authenticated in your $rootScope. So once you successfully authenticate you set that variable. But the problem is you are loosing this state, by navigating to the previous page using history.back(), because this isn't within the scope of login.html, the $rootScope value you set no longer exists. So if you rely on this to determine if you are logged in, it won't work.

What you need to do is restore your $rootScope.authenticated value when the application is started. See my previous answer on this issue, which discusses how to keep track of the session.

Application Pool Recycling

If it transpires your sessions are expiring prematurely, after testing, and you are using In-Memory caching in ServiceStack (default), be aware that if the ApplicationPool of your service is recycled by the IIS host then the cache data will also be destroyed. But for this to be happening frequently is unusual.

You could log out in your Application_Start event in global.aspx to note the frequency of recycling.

This answer of mine here touches on the recycling of the application pool.

I hope this helps.

Community
  • 1
  • 1
Scott
  • 21,211
  • 8
  • 65
  • 72
  • would it work to call `$rootScope.$apply();` before the `history.back();`? Our login page is a partial template in the grand scope of the app. – Chase Florell Apr 03 '14 at 20:56
  • So what is the url of the login view you present to your user, i.e. is it a state of the application `#/Login` or is it `/login.html`? When you use `history.back()` do you remain on the same page but simply transition state? Did you confirm the session isn't expiring prematurely by accessing the service directly? – Scott Apr 03 '14 at 21:18
  • and I'm also definitely getting 401's in the console. – Chase Florell Apr 03 '14 at 21:31
  • I am getting the same - how did you fix this? My sessions are definitely prematurely expiring. it's kind of like an hour or 2 rather than the default 14 days. – t316 May 09 '14 at 10:37
  • @t316 If you have followed the advise in my answer and you are still having problems, then please create your own question details the specific issues of your problem and your setup, and it may be possible to resolve your issue. – Scott May 09 '14 at 10:52