Announcement Announcement Module
No announcement yet.
Accessing Spring context inside a JAAS login module Page Title Module
Move Remove Collapse
This topic is closed
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Accessing Spring context inside a JAAS login module

    I've written a JAAS login module that uses our proprietary LDAP (with very specific role configuration). We're still evaluating whether to use JNDI or straight LDAP access through the netscape LDAP libraries, so I have 2 implementations. In order to configure which service to use and what the LDAP connection parameters are, I would like to set this in the Spring configuration. (Another advantage: avoid the use of singleton implementation). However, since I don't have access to the ServletContext, nor is my LoginModule set by spring (it is configured by JAAS), how can I access the Spring context ?


  • #2
    I don't know how to do it without a ServletContext or wiring it from Spring in the first place, but the way we approach the problem with a JBoss login module is as follows:

        public void initialize(Subject subject, CallbackHandler callbackHandler,
            Map sharedState, Map options) {
            super.initialize(subject, callbackHandler, sharedState, options);
            this.key = (String) options.get("key");
            if ((key == null) || "".equals(key)) {
                throw new IllegalArgumentException("key must be defined");
            String appContextLocation = (String) options.get("appContextLocation");
            if ((appContextLocation == null) || "".equals(appContextLocation)) {
                throw new IllegalArgumentException(
                    "appContextLocation must be defined");
            if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) {
                throw new IllegalArgumentException("Cannot locate "
                    + appContextLocation);
            ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(appContextLocation);


    • #3
      This doesn't seem to work. I'm able to get the application context location out of the JAAS login configuration, but I get the error java.lang.IllegalArgumentException: Cannot locate '/WEB-INF/config/spring/applicationContext.xml'. The file located in the above path, however it is not in the WEB-INF/classes directory where the Resin classloader is lookin for.

      I saw that you had similar code for the ResinAcegiAuthenticator, so I'm starting to think my resin configuration is wrong ?


      • #4
        Could I ask why you're using JAAS in the first place? We have an LDAP implementation in the sandbox, or you can use your own (as you probably will need to given your specific LDAP needs) and implement PasswordAuthenticationDao.

        If you need JAAS for EJB I'd understand, but if it's for a pureplay Spring WAR, it's better not to add to the complexity.

        Correct configuration details for the Resin adapter are provided in the Acegi Security reference guide.


        • #5
          I definitely agree JAAS gives extra complexity, but I'm afraid JAAS login is a requirement for the application As for the Resin configuration, I did look in the Acegi security reference guide, where you acknoledge that each webapplication can have the security application context in the WEB-INF directory. I've tried with putting everything in a war file instead of using the eclipse plugin of resin, but it still doesn't work, even if I put the configuration files outside the war file (in the classes dir of resin), it doesn't work.

          I guess I'll have to fallback on a singleton implementation of the service, and have the service created by spring.


          • #6
            Outside of the ideas you guys are talking about now, should I consider checking to see if the LoginContext is an instanceof ApplicationContextAware?

            For example...
                public Authentication authenticate(Authentication auth)
                        throws AuthenticationException {
                    if (auth instanceof UsernamePasswordAuthenticationToken) {
                        UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) auth;
                        try {
                            //Create the LoginContext object, and pass our InternallCallbackHandler
                            LoginContext lc = new LoginContext(loginContextName,
                                    new InternalCallbackHandler(auth));
                            if (lc instanceof ApplicationContextAware) {
                                ((ApplicationContextAware) lc).setApplicationContext(context);


            • #7

              The LoginContext is a JAAS class while the LoginModule is a custom class. You can't access the LoginModule from within the LoginContext, all the interesting methods and members of LoginModule are set to privite (so you can't override them). Even the callback handler is wrapped by a delegate class, so in the LoginModule you can't cast the callback handler to the class you've passed to JAAS (to pass the context trough), nor do you have a getter to get the wrapped callback handler.

              I ended up setting a static field applicationContext of my login module in an overriden version of the JaasAuthenticationProvider. Not a very nice solution indeed.

              Cheers, Stefaan.


              • #8
                Wow, I'm sorry. I'm a boob sometimes. I meant to do all of that with the LoginModule lol...