Print Page | Close Window

Refresh and login

Printed From: IdeaBlade
Category: Cocktail
Forum Name: Community Forum
Forum Discription: A professional application framework using Caliburn.Micro and DevForce
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=3479
Printed Date: 28-Mar-2024 at 5:38am


Topic: Refresh and login
Posted By: pponzano
Subject: Refresh and login
Date Posted: 05-Jun-2012 at 1:04am
Hello,
I've got a silverlight 5 application that at the startsup shows a loginform (similar to the TempHire application),authentication works fine and children are happy :D

I've got a small problem that's when the user press F5 the browser refresh and it asks me again to login... I've tried to check at the refresh if the Principal is logged in but it's false... how can I handle this scenario?

Thanks

Paolo

On my Shell view I do

  protected override void OnViewLoaded(object view)
        {
            base.OnViewLoaded(view);

            if (!userService.IsLoggedIn) //<- always false
            {
                PerformLogin().ToSequentialResult().Execute();
            }
        }

Thanks



Replies:
Posted By: mgood
Date Posted: 05-Jun-2012 at 1:28am
Hitting F5 loads a fresh instance of the Silverlight plug-in. It's like opening a complete new browser. You are refreshing the browser page. If you want to keep the user logged in, you have to store the SessionKey in a cookie and when your application starts you look for the cookie and try to login automatically using the SessionKey, if the login fails then you ask the user for their username/password. The SessionKey can be obtained from the AuthenticationContext on the AuthenticationService. Unfortunately, the AuthenticationService doesn't yet have a LoginAsync method that takes a SessionKey instead of a credential. So far the need hasn't come up. You'll have to subclass the AuthenticationService and add a LoginAsync(Guid) method and use the LoginAsync(Guid) overload on the DevForce Authenticator to login using the SessionKey.


Posted By: pponzano
Date Posted: 05-Jun-2012 at 1:44am
Hello Marcel,
so I've do to something like

public class myAuthenticationService : AuthenticationService, IUserService

  {

      #region IUserService Members

 

      bool IUserService.IsLoggedIn

      {

          get { return Principal != null; }

      }

 

      public IFUser CurrentUser

      {

          get { return Principal as IFUser; }

      }

 

      #endregion

 

      protected System.Collections.Generic.IEnumerable<IdeaBlade.EntityModel.INotifyCompleted> LoginAsync(Guid sessionKey)

      {

        //todo add authentication

 

          return null;

      }

 

 

  }


Since the default will call the OperationResult LoginAsync(ILoginCredential credential, Action onSuccess = null, Action<Exception> onFail = null);


need I to create a wrapping class that implements ILoginCredential and pass it to the server or at this post the whole authentication is on client? (I match my cookie session with the provided one)?


Thanks





Posted By: mgood
Date Posted: 05-Jun-2012 at 2:06am
Actually, I just realized that you can't login using a session key from Silverlight, so this just got a lot more complicated. The easiest thing to do at this point is to store the user's encrypted credentials in a cookie, so you can log them in automatically.


Posted By: pponzano
Date Posted: 05-Jun-2012 at 2:23am
supposed I store the cookie at the login what have I to check for showing/not the login form?


Posted By: mgood
Date Posted: 05-Jun-2012 at 8:37am
You check if you can find the cookie, if so, you decrypt the credentials and attempt a direct login using those credentials. If the login fails, you display the login form to ask the user to login manually.


Posted By: pponzano
Date Posted: 05-Jun-2012 at 11:31pm
Excuse me Marcel if I bother you... ok for the solution you've proposed to me, but looking at my code I used the FormsAuthenticationLoginCredential class as LoginCredential...thinking that passing true as isPersistent parameter would store the cookie as well... just a question do you think it's possible to implement such a functionality in next version of ideablade? To internally create a cookie in SL application?

Thanks

Update1 : with the approach you've suggested to me I re-do the authentication silently ... isn't possible to have this at server level (I can only see a login an extension of IEntityLoginManager)? and if the cookie is set to not login again?

Thanks



Posted By: mgood
Date Posted: 06-Jun-2012 at 10:54am
Are you using ASP.NET security? You didn't mention that. FormsAuthenticationLoginCredential works in conjunction with ASP.NET security. If you have ASP.NET security configured, DevForce will leave authentication of the user to ASP.NET. In this case you wouldn't have your own IEntityLoginManager on the server, unless you want to customize the login further. ASP.NET security will set a cookie. With the IsPersistence flag you'll tell ASP.NET if you want the cookie to be persistent or temporary.
 
With ASP.NET security enabled, you can silently login using null credential (LoginAsync(null)). In this case ASP.NET security will look for a cookie and if it finds it you'll be logged in and DevForce will grab the Principal from ASP.NET. If it doesn't find a cookie and you allow anonymous login you'll be logged in as Guest. In this case AuthenticationService.IsLoggedIn will return false, but AuthenticationService.Principal will return the Guest principal. This is because Principal.Identity.IsAuthenticated is false for a Guest user to indicate that you are not really authenticated. If you don't allow anonymous login, the login will fail if no cookie is found.
 
So, for your scenario if you were to go with the ASP.NET security approach, when your application starts you'll attempt to silently login using null credential. If you're successfully logged in at that point (AuthenticationService.IsLoggedIn=true) you are done. If not, you'll present the user with your login form and have them login manually.
 
Update1: Yes, you can essentially do something similar like ASP.NET security does if you are not using ASP.NET security. You can set a cookie in your LoginManager and then same as with ASP.NET, if the credential is null, your LoginManager would look for the cookie and log you in silently. Your LoginManager still needs to return a valid principal, so you must pack enough information into your cookie in order to create and return a proper principal with all the roles etc.
 
Click on the following link to find more information on how to use ASP.NET security with DevForce.
 
http://drc.ideablade.com/xwiki/bin/view/Documentation/security-aspnet - http://drc.ideablade.com/xwiki/bin/view/Documentation/security-aspnet


Posted By: pponzano
Date Posted: 07-Jun-2012 at 1:15am
Hello Marcel,
I've tried but with no luck........pressing F5 returns me false and Principal = null...here's my code
 
web.config
 
 <ideablade.configuration version="6.00" xmlns=" http://schemas.ideablade.com/2010/IdeaBladeConfig - http://schemas.ideablade.com/2010/IdeaBladeConfig ">
    <logging logFile="log\DebugLog.xml"/>
    <objectServer>
      <serverSettings allowAnonymousLogin="false" useAspNetSecurityServices="true"/>
    </objectServer>
  </ideablade.configuration>
  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
  </system.serviceModel>
  <system.web>
    <roleManager enabled="true"/>
    <authentication mode="Forms">
      <forms name=".myClient_ASPXAUTH" domain="myApp">
       
      </forms>
    </authentication>
 
ShellViewModel :
 

private IEnumerable<IResult> PerformLogin()

  {

      IAuthenticationService authenticationService = IoC.Get<IAuthenticationService>();

 

      OperationResult operation;

 

      bool isLogged = false;

      yield return (operation = authenticationService.LoginAsync(null)).ContinueOnError();

      try

      {

          isLogged = authenticationService.IsLoggedIn;

      }

      catch (Exception ex)

      {

          isLogged = false;

      }

 

      if (!isLogged)

          yield return loginFactory.CreatePart();

      ActivateItem(dashboardManagerViewModel);

  }

 
my LoginCredential :
 

[DataContract]

  public class myLoginCredential : FormsAuthenticationLoginCredential, IKnownType

  {

      public myLoginCredential(string username, string password, string domain = "") : base(username, password, domain,true)        { }

 

 

   [OMITTED]

  }

 
and finally my loginmanager
 

public class myLoginManager : AspAuthenticatingLoginManager

 {

     public myLoginManager()

         : base()

     {

         membership.Provider.ApplicationName = "TMRApp";

         System.Web.Security.Roles.ApplicationName = "TMRApp";

 

         string a = System.Web.HttpContext.Current.Session.SessionID;

     }

     protected override bool ValidateUserCore(ILoginCredential credential)

     {

 

         bool res = base.ValidateUserCore(credential);

 

         return res;

 

 

 

     }

 

     protected override IIdentity CreateIdentityCore(string name, string authenticationType, bool isAuthenticated)

     {

         IIdentity identity = base.CreateIdentityCore(name, authenticationType, isAuthenticated);

 

         return identity;

     }

 

     protected override IPrincipal CreatePrincipalCore(IIdentity identity, System.Collections.Generic.IEnumerable<string> roles)

     {

         var user = new IFUser(identity, identity.Name);

 

         MembershipUser membershipUser = membership.GetUser(identity.Name);

 

         Guid userID = (Guid)membershipUser.ProviderUserKey;

 

         user.IDUtente = userID;

 

         return user;

     }

 

     protected override System.Collections.Generic.IEnumerable<string> GetRolesCore(ILoginCredential credential)

     {

         var roles = base.GetRolesCore(credential);

 

         return roles;

     }

 
Here's what I've in the .Web log
 
2012-06-07 10:08:04 IdeaBlade.EntityModel.Server.EntityServerErrorInterceptor:OnError Caught exception: LoginException: The current user is not authorized, and guest access is not allowed. ---> at IdeaBlade.EntityModel.Web.AspAuthenticatingLoginManager.GetCurrentPrincipal() at IdeaBlade.EntityModel.Web.AspAuthenticatingLoginManager.NonCredentialAuthentication() at IdeaBlade.EntityModel.Web.AspAuthenticatingLoginManager.Login(ILoginCredential credential, EntityManager entityManager) at IdeaBlade.EntityModel.Server.SessionManager.GetPrincipalFromCredential(ILoginCredential pCredential) at IdeaBlade.EntityModel.Server.SessionManager.GetPrincipalFromEncryptedCredential(SessionBundle sessionBundle) at IdeaBlade.EntityModel.Server.SessionManager.GetPrincipal(SessionBundle sessionBundle, Boolean loginIfNotInMap) at IdeaBlade.EntityModel.Server.SessionManager.Validate(SessionBundle sessionBundle, Boolean loginIfNotInMap) at IdeaBlade.EntityModel.Server.SessionManager.Login(ILoginCredential credential) at IdeaBlade.EntityModel.Server.EntityServer.Login(ILoginCredential credential) at SyncInvokeLogin(Object , Object[] , Object[] ) at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
What am I doing wrong?? I tought I would have the Principal valorizated...
Thanks


Posted By: mgood
Date Posted: 07-Jun-2012 at 11:06am
I'm gonna have to repro this on my end to see what's happening, but that's gonna take a while. I don't have much bandwith at the moment.


Posted By: mgood
Date Posted: 07-Jun-2012 at 4:58pm
I had somebody look at this. The issue appears to be your use of the domain attribute in the Forms element.
 
<forms name=".myClient_ASPXAUTH" domain="myApp">
The domain is the Cookie.Domain that sets the URI for which the Cookie is valid. Problem with that is if a subsequent request is not coming into that subdomain, which is most likely the case in your app, then the Cookie isn't visible to the server, because it's only valid in the myApp domain.
 
http://msdn.microsoft.com/en-us/library/system.net.cookie.domain%28v=VS.80%29.aspx - http://msdn.microsoft.com/en-us/library/system.net.cookie.domain(v=VS.80).aspx


Posted By: mgood
Date Posted: 07-Jun-2012 at 5:02pm

Sorry, hit post before I finished my thought.

Don't specify the domain attribute in the web.config and it should work.


Posted By: pponzano
Date Posted: 11-Jun-2012 at 11:42pm
Hello Marcel,
It worked! Thanks a lot!


Posted By: pponzano
Date Posted: 24-Jun-2012 at 11:50pm
Hello Marcel,
just a question...can I define somewhere the duration of the session cookie?I've an app that stays logged after 3 days!
Thanks


Posted By: mgood
Date Posted: 25-Jun-2012 at 10:08am
I don't remember from the top of my head if there's a way to tell ASP.NET how long an authentication cookie is valid. There probably is setting, but I would have to dig it up myself first.
 
In your case, though, don't you want a temporary cookie? It sounds like you have a persistent cookie. The browser clears all temporary cookies when you close it. Set the isPersistent flag to false and the cookie should expire as soon as you close the browser.


Posted By: pponzano
Date Posted: 26-Jun-2012 at 12:40am
Hello Marcel,
 
here's the solution!
 

<authentication mode="Forms">

    <forms name=".my_ASPXAUTH" timeout="2880">  

    </forms>

  </authentication>

 
Thanks again


Posted By: mgood
Date Posted: 26-Jun-2012 at 12:50am
Good to know. Thanks.



Print Page | Close Window