New Posts New Posts RSS Feed: Upgraded to 6.1.7 from 6.1.4 issues migrating multi-domain Authentication code
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Upgraded to 6.1.7 from 6.1.4 issues migrating multi-domain Authentication code

 Post Reply Post Reply
Author
katit View Drop Down
Senior Member
Senior Member


Joined: 09-Sep-2011
Posts: 146
Post Options Post Options   Quote katit Quote  Post ReplyReply Direct Link To This Post Topic: Upgraded to 6.1.7 from 6.1.4 issues migrating multi-domain Authentication code
    Posted: 13-Jul-2012 at 2:53pm
Originally posted by DenisK

Hi katit,

Basically, since it's singleton (static) it's a big no-no in multi-tenant application like mine(on server side).......

Yes, the Authenticator is not supposed to be used on the server. Instead, you are given a specialized logged in server side EntityManager that you can use.

 

Yes, when code called from SL. In my case it's probably rare use case. I have REST services and need to reuse same database/model. So I just use IB model for that and this is server-only and I need to authenticate on each call. I solved it by obtaining AuthenticationContext and passing it to EntityManager instance on creation.



Edited by katit - 13-Jul-2012 at 2:55pm
Back to Top
DenisK View Drop Down
IdeaBlade
IdeaBlade


Joined: 25-Aug-2010
Posts: 715
Post Options Post Options   Quote DenisK Quote  Post ReplyReply Direct Link To This Post Posted: 13-Jul-2012 at 12:01pm
Hi katit,

Basically, since it's singleton (static) it's a big no-no in multi-tenant application like mine(on server side).......

Yes, the Authenticator is not supposed to be used on the server. Instead, you are given a specialized logged in server side EntityManager that you can use.

Thank you for your feedback on the documentation. We will review and update it as appropriate.

While solution works - DataSourceExtension is case-sensitive.

Yes, this is a bug. It is supposed to be case insensitive. Thank you for reporting it. I'll file a bug report.


Edited by DenisK - 13-Jul-2012 at 12:09pm
Back to Top
katit View Drop Down
Senior Member
Senior Member


Joined: 09-Sep-2011
Posts: 146
Post Options Post Options   Quote katit Quote  Post ReplyReply Direct Link To This Post Posted: 13-Jul-2012 at 5:46am
Found another issue related to original post. While solution works - DataSourceExtension is case-sensitive.
If I have 2 customers logging into same account and one types "Demo" and another types "demo" I get same exception:
Unable to initialize EntityManager
DataSourceExtension cannot be overriden on the server
So, some place on server it does match strings and in other place doesn't.
If I have 2 sessions logging in into different accounts like "demo" and "demo2" everything works. It only gives errors when users login to the same extension with differen case letters in account ID
 
I understand that core issue here is that we end up with URL like this:
/EntityServer_demo.svc/sl
 
So, while both users directed to the same endpoint - extention on your server stored AND case-sensitive. Then I get error.
 
Right now I fixed this issue so AccountId I pass is lower-cased


Edited by katit - 13-Jul-2012 at 6:04am
Back to Top
katit View Drop Down
Senior Member
Senior Member


Joined: 09-Sep-2011
Posts: 146
Post Options Post Options   Quote katit Quote  Post ReplyReply Direct Link To This Post Posted: 12-Jul-2012 at 9:54pm
Denis,
 
Please update your documentation with explanation about DefaultAuthenticationContext
I got pretty lucky, noticed issue right after rolling out update.
 
Basically, since it's singleton (static) it's a big no-no in multi-tenant application like mine(on server side). My bad also for not realizing it but basically I had different customers potentially crossing databases.
 


Edited by katit - 13-Jul-2012 at 5:58am
Back to Top
katit View Drop Down
Senior Member
Senior Member


Joined: 09-Sep-2011
Posts: 146
Post Options Post Options   Quote katit Quote  Post ReplyReply Direct Link To This Post Posted: 09-Jul-2012 at 2:45pm
If on the client you create an EntityManager with an existing AuthenticationContext, but on the server that session info/user has been removed from the session map due to this inactivity, DevForce will just login again with the encrypted credentials stored in the AuthenticationContext.
 
This is exactly what I needed to know. Thanks!
Back to Top
DenisK View Drop Down
IdeaBlade
IdeaBlade


Joined: 25-Aug-2010
Posts: 715
Post Options Post Options   Quote DenisK Quote  Post ReplyReply Direct Link To This Post Posted: 09-Jul-2012 at 1:21pm
I assume you meant SessionKey instead of SessionId. Session in this context is the session in which an EntityManager is connected to an EntityServer. It is not a "true" session and again, should not be confused with an ASP.NET session. Session in DevForce is all internal and managed by DevForce.

AuthenticationContext represents such session as well as information about the logged in user. An AuthenticationContext never expires and thus, from the client's perspective, a session never expires as well. 

A session info is removed on the server after a period of inactivity as mentioned above. If on the client you create an EntityManager with an existing AuthenticationContext, but on the server that session info/user has been removed from the session map due to this inactivity, DevForce will just login again with the encrypted credentials stored in the AuthenticationContext.

So in effect, the client doesn't see a session info has been removed and in fact, see that nothing has expired.
Back to Top
katit View Drop Down
Senior Member
Senior Member


Joined: 09-Sep-2011
Posts: 146
Post Options Post Options   Quote katit Quote  Post ReplyReply Direct Link To This Post Posted: 06-Jul-2012 at 12:59pm
Ok, last question :)
You mentioned that there is no expiration on AuthenticationContext.
 
Is there any connection between Session and AuthenticationContext? I see SessionId property. If session expired and I'm creating EntityManager on a client which uses this session - what happens? I'm trying to understand how this will work because it is very hard to test..
 
 
Back to Top
DenisK View Drop Down
IdeaBlade
IdeaBlade


Joined: 25-Aug-2010
Posts: 715
Post Options Post Options   Quote DenisK Quote  Post ReplyReply Direct Link To This Post Posted: 06-Jul-2012 at 12:52pm
The EntityManager will get garbage collected when it's out of scope. 

The session information will get cleaned up after a period specified in userSessionTimeout in your config file.  http://drc.ideablade.com/xwiki/bin/view/Documentation/deploy-configuration#HServerSettingselement

Note that when I mentioned session info, it's not ASP.NET session info but rather DevForce's own Session Map. The memory consumption here is relatively low and shouldn't cause memory leak.

So to answer your question above, you don't need to call logout every time you're done processing call as EntityManager gets garbage collected and relatively small session info footprints will be cleaned up after a period of inactivity.

Hope this explains it.


Edited by DenisK - 09-Jul-2012 at 1:25pm
Back to Top
katit View Drop Down
Senior Member
Senior Member


Joined: 09-Sep-2011
Posts: 146
Post Options Post Options   Quote katit Quote  Post ReplyReply Direct Link To This Post Posted: 05-Jul-2012 at 3:30pm
Ok, so for #4 I have some concerns.
 
In Silverlight I don't really care  - clients don't login as much and I can't really control logout because they can just close browser.
 
But I use same EntityManagers for WCF services and there is ton's of calls. I create instance of EntityManager per call. Does it mean that I have to call logout every time after I'm done processing call? I wonder if I can get memory leak by leaving it as it is.
 
Tecnically, after WCF done processing call - EntityManager get's disposed. What about session info?
Back to Top
DenisK View Drop Down
IdeaBlade
IdeaBlade


Joined: 25-Aug-2010
Posts: 715
Post Options Post Options   Quote DenisK Quote  Post ReplyReply Direct Link To This Post Posted: 05-Jul-2012 at 2:55pm
Hi katit,

1. Yes, that's correct. It is one of the 2 ways you can set DefaultAuthenticationContext. See http://drc.ideablade.com/xwiki/bin/view/Documentation/authentication-details-client#HSinglesign-on2Fsign-off for more details.

2. There's really no right or wrong answer here on whether to use single sign on/off via DefaultAuthenticationContext. We provide the ability to control this via the EntityManager.Options.UseDefaultAuthenticationContext flag and let developers decide what's best for their applications.

3. No, there's no expiration for AuthenticationContext.

4. Calling Logout will free up session information being stored. If you have a need to do this then yes, in general you should call Logout.
Back to Top
katit View Drop Down
Senior Member
Senior Member


Joined: 09-Sep-2011
Posts: 146
Post Options Post Options   Quote katit Quote  Post ReplyReply Direct Link To This Post Posted: 05-Jul-2012 at 12:09pm
I changed client code to look like this:
 
Authenticator.Instance.LoginAsync(
credentials,
new LoginOptions(credentials.Domain),
loginOperation =>
{
    if (loginOperation.CompletedSuccessfully
        && loginOperation.AuthenticationContext.LoginState == LoginState.LoggedIn)
    {
        Authenticator.Instance.DefaultAuthenticationContext = loginOperation.AuthenticationContext;
        this.OnLoginSuccessfull();
    }
    else if (loginOperation.HasError)
    {
        loginOperation.MarkErrorAsHandled();
        this.OnLoginError(loginOperation.Error, true);
    }
});
 
When I need new EntityManager I do it like so:
 
var manager = new MyManager(true, credentials.Domain)
 
Questions:
 
1. Is that correct to manually assign DefaultAuthenticationContext upon logon?
2. Is that correct to create EntityManager relying on DefaultAuthenticationContext? It seems to work.
3. Should I do anything in addition? Is there expiration for AuthenticationContext? If my Silverlight users keep app open whole day, how should I handle this?
4. Should I call Logout at all? In Silverlight - I just block application, is there any good reason why I should logout?
 
 
Back to Top
katit View Drop Down
Senior Member
Senior Member


Joined: 09-Sep-2011
Posts: 146
Post Options Post Options   Quote katit Quote  Post ReplyReply Direct Link To This Post Posted: 03-Jul-2012 at 7:25pm
Weird. It's working like this :)
 
So, that is working. Now I have question about role of DefaultAuthenticationContext
 
Right now on every view in Silverlight App I'm getting new copy of EntityManager like this:
 
public EntityManager GetCleanApplicationEntityManager()
{
    var manager = new MyApplicationEntities(this.applicationEntityManager)
    {
        DefaultQueryStrategy = QueryStrategy.DataSourceOnly
    };
    manager.VerifierEngine.DefaultVerifierOptions.ShouldTreatEmptyStringAsNull = false;
    return manager;
}
 
Basically, I keep my authenticated EntityManager and create new clean instances to pass around.
Should I change the way I create it with a new DefaultAuthenticationContext?
If so, how? There is something about expiration in 20 minutes? How should I handle it?
Back to Top
DenisK View Drop Down
IdeaBlade
IdeaBlade


Joined: 25-Aug-2010
Posts: 715
Post Options Post Options   Quote DenisK Quote  Post ReplyReply Direct Link To This Post Posted: 03-Jul-2012 at 6:48pm
Hi Katit;

Could you try the following instead?

var context = Authenticator.Instance.Login(credentials, new LoginOptions(accountId));
var applicationManager = new MyApplicationEntities(entityManager, true, accountId);
Back to Top
katit View Drop Down
Senior Member
Senior Member


Joined: 09-Sep-2011
Posts: 146
Post Options Post Options   Quote katit Quote  Post ReplyReply Direct Link To This Post Posted: 03-Jul-2012 at 10:29am
I also tried to play with new Authenticator and do it like this - pass my accountId(aka dataSourceExtension) via Authenticator
 
var context = Authenticator.Instance.Login(credentials, new LoginOptions(accountId));
 
Then I modified code to NOT specifically say which dataSourceExtension will be userd
 
var applicationManager = new MyApplicationEntities(entityManager, true);
 
So, this time I did not override it, "magic" entityManager already had proper extension. Still, I'm getting same exception:
 
Unable to initialize EntityManager
DataSourceExtension cannot be overriden on the server

              
I also tried to say that server is Local - no luck :(
 
var context = Authenticator.Instance.Login(credentials, new LoginOptions(accountId, null, EntityServiceOption.UseLocalService));

               


Edited by katit - 03-Jul-2012 at 10:32am
Back to Top
katit View Drop Down
Senior Member
Senior Member


Joined: 09-Sep-2011
Posts: 146
Post Options Post Options   Quote katit Quote  Post ReplyReply Direct Link To This Post Posted: 03-Jul-2012 at 9:30am
I have application where user log's in to his own "Account" each account effectively separate database.
 
I pass AccountId as domain when authenticating.
 
Here is problem I'm trying to solve on a server. I'm using EM on both Silverlight client and WCF server.
On server I have code like this:
 
var credentials = new FormsAuthenticationLoginCredential(userName, password, accountId, false);
var context = Authenticator.Instance.Login(credentials);
 
Note I migrated to use Authenticator. On this call it transfers to IEntityLoginManager which looks like this:
 
public class LoginManager : IEntityLoginManager
    {
        private EntityManager entityManager;
        public LoginManager()
        {
        }
        [Import]
        public IMembershipService MembershipService { get; set; }
        public IPrincipal Login(ILoginCredential credential, EntityManager manager)
        {
            this.entityManager = manager;
            if (credential == null) throw new LoginException(LoginExceptionType.NoCredentials, "Credentials required");
            return this.CredentialAuthentication(credential);
        }
        public void Logout(IPrincipal principal, EntityManager manager)
        {
            FormsAuthentication.SignOut();
        }
        private IPrincipal CredentialAuthentication(ILoginCredential credential)
        {
            var isAuthenticated = this.MembershipService.ValidateUser(this.entityManager, credential.Domain, credential.UserName, credential.Password);
...
        }
    }

              
Problem comes in when I call
this.MembershipService.ValidateUser(this.entityManager, credential.Domain, credential.UserName, credential.Password);
 
This is my code and I do need to access application database there (remember database is resolved by Key)
Code of this method:
 
public bool ValidateUser(EntityManager entityManager, string accountId, string userName, string password)
{
    var passwordFromDatabase = string.Empty;
    var passwordSalt = string.Empty;
    int? failedPasswordAttemptCount = 0;
    int? failedSecurityAnswerAttemptCount = 0;
    bool? isActive = false;
    DateTime? lastActivityDate = DateTime.Now;
    int? retVal = 0;
    try
    {
        var applicationManager = new MyApplicationEntities(entityManager, true, accountId);
        applicationManager.MEMGetUserPassword(
            userName,
            true,
            ref passwordFromDatabase,
            ref passwordSalt,
            ref failedPasswordAttemptCount,
            ref failedSecurityAnswerAttemptCount,
            ref isActive,
            ref lastActivityDate,
            ref retVal);
        var encodedPasswd = EncodeWithSalt(password, passwordSalt);
        var isPasswordCorrect = passwordFromDatabase.Equals(encodedPasswd);
        if (isPasswordCorrect && failedPasswordAttemptCount == 0 && failedSecurityAnswerAttemptCount == 0)
        {
            return true;
        }
        return isPasswordCorrect;
    }
    catch (Exception ex)
    {
        this.LoggerService.Log(accountId, ex, Category.Exception, Priority.Medium);
        return false;
    }
}
 
Before it was working, because this "magic" EntityManager was already authenticated to anything and this line worked:
var applicationManager = new MyApplicationEntities(entityManager, true, accountId);
 
Now I get exception
Unable to initialize EntityManager
DataSourceExtension cannot be overriden on the server
 
So, how do I authenticate using only 1 model without resorting to use plain ADO? I have data extention, I have SourceKeyResolver which does what I need. I had it working before. How do I make it work with new authentication?
 
 
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down