Announcement Announcement Module
Collapse
No announcement yet.
Fundamentally different types of user logging on - how to allow? Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Fundamentally different types of user logging on - how to allow?

    Hello,

    My web application has the notion of agents and clients. Clients "belong" to an agent (and only one agent). Agents are the main users of the application as far as I am concerned and logon "normally". Clients will login via a special URL that is specific to the agent and may contain logos, etc for that agent.

    There are separate database tables for AGENT and CLIENT, both with username and password:

    Code:
    CREATE TABLE AGENT
    (
        AGENT_ID        INT NOT NULL AUTO_INCREMENT,
        USERNAME        VARCHAR(20) NOT NULL,
        PASSWORD        VARCHAR(32) NOT NULL,
        PRIMARY KEY(AGENT_ID),
        UNIQUE KEY `USERNAME` (`USERNAME`),
    );
    
    CREATE TABLE CLIENT
    (
        CLIENT_ID 	    INT NOT NULL AUTO_INCREMENT,
        USERNAME        VARCHAR(20) NOT NULL,
        PASSWORD        VARCHAR(32) NOT NULL,
        PRIMARY KEY(CLIENT_ID),
        UNIQUE KEY `USERNAME` (`USERNAME`)
    );
    Note that the agent's username is unique across all agents and the client's username is unique across all clients. This allows the possibility of a client to have the same username as an agent, and why not?

    I have the authentication/authorisation for agents all nicely working. Now I want to do the same for clients. This is where I'm not exactly sure how to proceed!

    My UserDetailsService implementation has the agentDAO dependency injected. The loadUserByUsername() asks the agentDAO to find by username. I could add the clientDAO in here also and call clientDAO.findByUsername() if (and only if) the agentDAO lookup failed. This doesn't seem right though because if the client has the same username as an agent, the agent will be found first.

    The other way I thought about doing it was to have one database table to store the username/password for agents and clients. This would mean usernames have to be unique for both fundamental types of users but that's perhaps not a major issue. It would also mean some strange linking in the database to link back from the USERNAME_PASSWORD table to the AGENT or CLIENT table. It seems far better to have the credentials in the respective AGENT or CLIENT tables.

    Perhaps this could be solved with multiple authentication providers or user details services?

    Please help!

    Thanks,

    PUK

  • #2
    You really need an additional parameter (based on the login-mechanism in the webapp) to determine whether it is a client or an agent who is logging in. If they login through different URLs then that shouldn't be a problem. At that point, the problem becomes the same as the FAQ:

    http://static.springsource.org/sprin...a-login-fields

    From your AuthenticationProvider, you can choose which DAO to delegate to based on the client/agent parameter.

    Comment


    • #3
      Thank you for the immediate response. Much appreciated. I will look into the method you suggest and let you know if I have any issues implementing.

      Comment


      • #4
        My first attempt at doing this contained a flaw that I don't know how to iron out.

        I subclassed authenticationProcessingFilter and overrode the obtainUsername() method to prefix with agent:

        Code:
        public class CustomAuthenticationProcessingFilter extends AuthenticationProcessingFilter {
        
            @Override
            protected String obtainUsername(HttpServletRequest request) {
                String username = super.obtainUsername(request);
                return "agent:" + username;
            }
        
        }
        The prefix is detected in my UserDetailsService implementation and I know the type of user.

        The problem is that if I fail to authenticate correctly, the login form is shown again but then I see the prefix on the username.

        I will look at the other suggestion of creating a different authentication token class but wondered if you might be able to suggest a way to iron out that wrinkle above?

        Thanks,

        PUK

        Comment


        • #5
          Either don't write the username back to the form, or strip the prefix from it.

          Comment


          • #6
            Originally posted by Luke Taylor View Post
            Either don't write the username back to the form, or strip the prefix from it.
            How silly of me. I had got confuddled and thought that Spring was presenting the information in the login form. Can now see my JSP is filling it in using:

            Code:
            session.getAttribute(AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY)
            I'm off to strip...

            Thanks,

            PUK

            Comment


            • #7
              I've just retested the Remember Me feature and that's now causing a problem. It's calling my UserDetailsService's loadUserByUsername() method with the bare username so there's no way to distinguish the type of user and therefore no way to pick the right DAO to authenticate with.

              Is this trivial to overcome?

              PUK

              Comment


              • #8
                Perhaps I'm being too hasty/silly again: Looking at this from another angle - I presume I just need to keep the prefix in the UserDetails object... I'l give that a go and report back.

                Comment


                • #9
                  That worked fine. Apologies for the last bit of noise.

                  Comment


                  • #10
                    I had another problem with this which I managed to resolve myself after a couple of debugging sessions within Spring Security. I'd like to share it as the problem was caused (in a roundabout fashion!) by me following some advice from the Spring Security FAQ (as linked to earlier in this thread).

                    When logging in and selecting Remember Me, closing browser, loading browser again, I would not get logged back in again automatically. The HTTP monitor showed the populated remember me cookie being sent to server but there was a remember me cookie being returned which had an empty value!

                    Turned out it was down to the use of colon ':' separator between the user type and the username. e.g: "agent:PUK_999". AbstractRememberMeServices.autoLogin() decoded the cookie to get one more token that expected, because colon is also the delimiter used to separate tokens within the cookie value.

                    I'm now using semi-colon and all's well.

                    Thanks,

                    PUK

                    Comment

                    Working...
                    X