Results 1 to 9 of 9

Thread: securityContext.getAuthentication() is null in a Thread

  1. #1
    Join Date
    Jun 2006
    Posts
    9

    Default securityContext.getAuthentication() is null in a Thread

    Hi there,

    In our webapp, we have something like this

    SomeServiceClass {
    private Executor taskExecutor; // gets set in a private method for now, but will be injected by spring xml later on.
    doSomething() {
    taskExecutor.execute( new Runnable() {
    public void run() {
    doNotify(some_final_string);
    }
    });
    }

    doNotify(final String xyz) {
    SecurityContext securityContext = SecurityContextHolder.getContext();

    // this always returns null in asynch mode but works in non-asynch mode.
    securityContext.getAuthentication() ;

    }
    }

    any idea why securityContext.getAuthentication() always returns null?

    2nd question.

    we've a PortalLogoutHandler class that implements Spring LogoutHandler
    in public void logout( HttpServletRequest request, HttpServletResponse response, Authentication authentication ), we need to do something with authentication, but it's null by the time logout is called. Is there a preLogout() we can use ? another way to ask the question, if we need to do something with the authentication object prior to its being nullified, how can we achieve that?

    thanks

  2. #2
    Join Date
    Dec 2008
    Location
    New York City
    Posts
    135

    Default

    SecurityContextHolder runs off thread local. You're starting a new thread when you go asynch.

  3. #3

    Default

    So what's the solution?

    I am having the same issue. We have several cron jobs set up through Spring that are failing because we can't authenticate in this situation.

  4. #4
    Join Date
    Dec 2008
    Location
    New York City
    Posts
    135

    Default

    Section 5.2.1 in touches on this topic at http://static.springsource.org/sprin...-overview.html .

    But I would check to see that you have to do this. I'm having trouble thinking of a usecase where I would need access to a currently authenticated user to trigger a cron task.

  5. #5

    Default

    Quote Originally Posted by arthomps View Post
    Section 5.2.1 in touches on this topic at http://static.springsource.org/sprin...-overview.html .

    But I would check to see that you have to do this. I'm having trouble thinking of a usecase where I would need access to a currently authenticated user to trigger a cron task.
    So here's my scenario....

    A cron job is set to clean up orphaned documents. To retrieve a list of documents I need to query our database for a list of the documents. We have an AOP pointcut setup to check the Authentication object of the user prior to executing the DB query through Hibernate. In this case the user is our "server" user or in other words the account which is running our web app. In this case the Authentication object is null and therefor the cron job never gets performed because we can't authenticate our server user. We have to authenticate against a propietary user database and cannot add this server user. But the server does have a Server PKI which could possible be used but I am not sure how to handle this.

    Is there a good way to handle this or any other suggestions?

  6. #6
    Join Date
    Dec 2008
    Location
    New York City
    Posts
    135

    Default

    did you try the link i provided? SecurityContextHolder.MODE_INHERITABLETHREADLOCAL sounds like what you're looking for.

  7. #7

    Default securityContext.getAuthentication() is null in a Thread

    Got it. I will try that. Thanks!

  8. #8

    Default

    Unfortunately SecurityContextHolder.MODE_INHERITABLETHREADLOCAL didn't work. I found this note which may explain why:

    "Note however, that you cannot share security context among sibling threads (e.g. in a thread pool). This method only works for child threads that are spawned by a thread that already contains a populated SecurityContext."

    I guess since the server process is spawning this thread it is a "sibling" thread. I guess I am going to resort to reading in the server certificate and using it to populate an Auth object and then perform the work. I would rather have set this up through Spring but it doesn't seem like anybody knows how to do this.

  9. #9
    Join Date
    Jan 2008
    Posts
    1,833

    Default

    You could create a Runnable that sets the Authentication or SecurityContext to use one that is injected and then delegate to the Runnable you actually want. Something like...

    Code:
    public class SpringSecurityRunnableWrapper implements Runnable {
      private SecurityContext context;
      private Runnable delegate;
     
      public SpringSecurityRunnableWrapper(SecurityContext context, Runnable delegate) {
        this.context = context;
        this.delegate = delegate;
      }
    
      public void run() {    
        try {
          SecurityContextHolder.setContext(context);
          delegate.run();
        } finally {
          SecurityContextHolder.clear();
        }
    }
    Then to call it you would do something like:

    Code:
    Runnable worker = new MyCustomRunnableThatNeedsSecurity();
    SecurityContext context = new SecurityContextImpl();
    context.setAuthentication(new UsernamePasswordAuthenticationToken("username","password",AuthorityUtils.createAuthorityList("ROLE_USER"));
    Runnable securedWorker = new SpringSecurityRunnableWrapper(context, worker);
    taskExecutor.execute(securedWorker);
    Of Course you don't really need SpringSecurityRunnableWrapper since you could manage the SecurityContext inside of MyCustomRunnableThatNeedsSecurity directly, but it makes this more reusable and separates concerns.
    Rob Winch
    Twitter @rob_winch
    Spring Security Lead
    Spring by Pivotal

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •