Announcement Announcement Module
Collapse
No announcement yet.
ProviderNotFoundException wiring CXF's WSS4JInInterceptor with Spring Security. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • ProviderNotFoundException wiring CXF's WSS4JInInterceptor with Spring Security.

    Hi everybody.
    I' have a project using Spring and CXF (it is sort of a legacy code and I need some RPC style web services) using X509Certificates.
    It is all setup, and CXF's WSS4JInInterceptor takes care of encryption and validating the signature. Now I'm trying to wire it with spring security for authorization.

    What I'm really trying to do is to check if the principal in the X509 certif. has the proper granted role to access the particular URL it is trying to access.

    I have the basic security setup as indicated in the chapter 2 of the reference guide:

    Code:
    <http auto-config="true"> 
    		<intercept-url pattern="/warehouse*/**" access="ROLE_RETAILER"/>				
    	</http>	
    
    <authentication-manager alias="authenticationManager"/>
      	
      	<authentication-provider>
    		<user-service>
    			<user authorities="ROLE_WEBCLIENT" name="webclient" password="webclientpass"/>
    			<user authorities="ROLE_RETAILER" name="retailer" password="retailerpass"/>
    			<user authorities="ROLE_WAREHOUSE" name="warehouse" password="warehousepass"/>
    			<user authorities="ROLE_MANUFACTURER" name="manufacturer" password="manufacturerpass"/>
    		</user-service>
    	</authentication-provider>
    This is placed in a security configuration file wired in the web.xml and with the security namespace as default. It is correctly loaded by spring, no problems there.

    I followed the suggestions in CXF mailing list and placed a second interceptor (I named it "SecurityConnector") after the WSS4JInInterceptor, and there I already have the X509 certificate from the first interceptor to create an Authentication with, and the SecurityContextHolder to set the authentication into. I also wired spring security's authenticationManager into my SecurityConnector, just in case.

    In the "handleMessage" method of this interceptor I've got:

    Code:
    List<Object> results = (List<Object>)message.get(WSHandlerConstants.RECV_RESULTS);
    ...
    for (Iterator iter = results.iterator(); iter.hasNext();) {
        WSHandlerResult hr = (WSHandlerResult) iter.next();
    ...
        for (Iterator it = hr.getResults().iterator(); it.hasNext();) 
               {
                   WSSecurityEngineResult er = (WSSecurityEngineResult) it.next();
                   if (er != null && er.getCertificate() instanceof X509Certificate) 
                   {
                	   //X509Certificate cert = er.getCertificate();
                       //Authentication authentication = new X509AuthenticationToken(cert);
                	   Authentication authentication = new PreAuthenticatedAuthenticationToken(er.getPrincipal(), er.getCertificate());
                       //authentication.setAuthenticated(true);
                       authentication = authenticationManager.authenticate(authentication);
                       SecurityContextHolder.getContext().setAuthentication(authentication);         
                  }
               }
    So, here is where I got stuck.
    I've seen this WSS4J wiring with spring security where they use a UsernameToken and set it as the authentication in the security context. I was trying to do the same with the X509 certificates.
    The problem is that:
    A) From the certificate I can get the principal, but not the password, so I cannot create a UsernameToken.
    B) I cannot re-authenticate this X509Certificate against my in-memory user list, as I only get a ProviderNotFoundException (neither the X509AuthenticationToken nor the PreAuthenticatedAuthenticationToken are supported by the authentication-provider user-service list).
    C) Just setting one of those AuthenticationTokens into the security context is not working. It doesn't throw any exceptions, but it doesn't prevent the un-authorized principal from accessing the URLs. Again if I simply do this, the AuthenticationToken hasn't got the appropriate roles assigned to it, just the principal.
    D) I'm not even certain that this is supposed to work with the intercept-url access-control, or only with method-based access control.

    So, my questions would be which is the correct way to plug these two security mechanisms together?, how do I get from having the authenticated certificate (which I already got) to mapping that to a user and role in the list, and checking access rights based on that?.

    Thank you very much in advanced!.
    I really look forward to your answers.
    Regards,
    JP

  • #2
    Ok, my bad, it is quite clearly explained in chapter 16 of the security reference.

    I was able to feed my security context with a PreAuth.Token which is correctly validated against an InMemory UserDetailsService. The correct roles are granted to the user. My problem is now that the intercept-url access role requirements are not met (the service is called irrespective of the role). I guess it is because we are already down below the filter chain.

    Can someone illuminate me on this?. I am assuming that I'm only left with method security, am I right?, thanks again.
    Last edited by jpsilvagallino; Dec 28th, 2010, 06:55 AM.

    Comment


    • #3
      Can you test first if setting at the method level will be picked by Spring Security?

      Comment


      • #4
        I'll do that and get back.
        It may take me a little though, since I'll have to change things to use a facade for my jaxws endpoint (I'm using CXF and AOP and such endpoints don't get along well, I get an exception on WebServiceContext being null and that sort of things).

        Comment


        • #5
          Skram, not really sure if you are still going to read this, but yes, method security gets the credentials (I have other problems with it that I'm already asking at the forum, but access is denied to principals which don't are not granted the correct roles).

          Should intercept-url work?, or is is before in the interceptors chain?.
          Thanks again.

          Comment


          • #6
            I've just realized now what you're trying to do. You're basically trying to prevent access to your web service endpoint via Spring Security's intercept-url?

            I know Spring Security can be used for authenticating your web service consumers. But for intercepting the Spring-WS endpoint itself and applying role based on your Spring Security authentication--that I'm not sure of.

            I thought that's the purpose why we have UsernameTokens with WS-Security?

            You're trying to restrict access of your web service via Spring Security?

            Comment


            • #7
              I just tried it right now. I setup a Spring-WS with WSS4j-based WS-Security and delegated the authentication to Spring Security.

              Regardless of the roles I set in the Spring Security (ROLE_ADMIN, ROLE_YADA_YADA, ROLE_ETC), it doesn't affect your access to the web service.

              If the UsernameToken is incorrect, then you get blocked from the web service. But if it's correct you get full access. I set the intercept-url to the root and to the sub-root. Nothing changed.

              Also, I haven't read from the docs that you can prevent access to your web-service endpoints using intercept-url. I thought that's why we have WS-Security in the first place.

              By the way I'm using Spring WS 2.0.0 RC2 and Spring Security 3.0.5 / Spring Core 3.0.5. I just saw in the other thread that you're using an older version. But in any case if the new version doesn't support your use-case, then it's safe to assume the older version may not either
              Last edited by skram; Jan 4th, 2011, 10:04 AM.

              Comment


              • #8
                Thanks Skram.
                Well, I'm using X509 Tokens, so if the signer is in the keystore, is automatically authorized (a valid PreAuthenticatedToken is generated, then roles are assigned, etc.).

                Using url-interceptors and roles to filter access was just a mind wandering, I guess. A B plan, as problems were arising with method security. I guess I could use the WS Security credentials at interceptors to prevent access, but due to some of the purposes of the project, I rather have a declarative configuration. I will be needing method security anyhow, so I might as well have all authorization configuration in one place.

                Thank you very much for you time and help.
                Regards,
                JP

                Comment

                Working...
                X