By the way, the idea (suggested by Dan) to have WSS4J not doing UsernameToken processing still works with the proposed patch. But I'd rather have a NoopProcessor added to CXF and registered with WSS4J when needed to delegate the processing of token/actions to interceptors like UsernameTokenInterceptor...
thanks, Sergey On Mon, Apr 19, 2010 at 1:46 PM, Sergey Beryozkin <sberyoz...@gmail.com>wrote: > Hi > > I've added an initial patch for addressing a policy-first case, see [1]. > It's a patch because it depends on another one I submitted to WSS4J [2]. > Both patches need more work (tests, etc) but I'd just like to initiate a > discussion/review. > > The idea behind [1] is quite similar to the one used in supporting a > java-first case, where a custom interceptor extends an > AbstractWSS4JSecurityContextPr > oviding interceptor. But is is much simpler in [1] where > UsernameTokenProcessor may be optionally extended and its createSubject > method be overridden. Provided [2] gets applied then a subclass will just > have a property set disabling the (WSS4J) validation of passwords and will > do its own validation in createSubject method. > > This is really all what will be needed in simple cases, where a > DefaultSecurityContext will do, but optionally, createSecurityContext can > be overridden too. > > A user would need to set a bus property > "org.apache.cxf.ws.security.usernametoken.interceptor" referincing a custom > interceptor which will indicate to the WSSecurityPolicyLoader that a custom > UsernameTokenProcessor subclass will need to be loaded. > > Similar approach can be employed for handling other types of tokens. > > cheers, Sergey > > [1] https://issues.apache.org/jira/browse/CXF-2754 > [2] https://issues.apache.org/jira/browse/WSS-229 > > > On Mon, Apr 19, 2010 at 1:43 PM, Sergey Beryozkin <sberyoz...@gmail.com>wrote: > >> Just realized I did not CC tp dev when replying to Dan the other day : >> >> Hi Dan >> >> >> On Fri, Apr 9, 2010 at 2:50 PM, Daniel Kulp <dk...@apache.org> wrote: >> >>> >>> My main "concern" with the implementation of this is that it's done as a >>> direct subclass of the WSS4JInInterceptor and thus not really usable by >>> the >>> policy based endpoints as those interceptors subclass WSS4JInInterceptor >>> as >>> well. >>> >>> I think the better approach may be to add a flag to wss4j (I can help >>> commit >>> changes there if needed) to have it not do any UserName token processing >>> at >>> all. (aside: this may be doable without changes to wss4j by >>> registering our >>> own "do nothing processor") Then, have another interceptor that runs >>> after >>> the WSS4JInInterceptor that would actually handle the UsernameToken and >>> verify >>> anything it needs and such. >>> >> >> This sounds like a very good idea, I agree the proposed approach won't do >> for the cases where policies drive the >> creation of interceptors. >> >> Having said that, I think the abstract utility interceptor extending >> WSS4JInInterceptor >> may still be used in cases where users start from manually configuring >> jaxws endpoints. In these cases they'd need to >> list up to 3 interceptors (the one which extends >> AbstractWSS4JSecuriyContextInterceptor, the authorizing interceptor if the >> authorization is needed plus may be a SAAJ one) but otherwise, when say a >> clear text password has been encrypted, they'd still need to specify >> WSS4JInInterceptor (with a flag disabling UsernameToken checks) plus >> UsernameTokenInterceptor, etc. >> >> At the moment AbstractWSS4JSecuriyContextInterceptor is a bit complicated >> due to the fact it blocks the WSS4J digest checks and thus also creates a >> security engine per every request, but it all will be gone in due time... >> >> >>> >>> To be honest, I WANT to do this for the Policy based stuff anyway. >>> There is >>> currently some duplicated code between the PolicyBasedWSS4JIinInterceptor >>> and >>> the new UsernameTokenInterceptor that could be eliminated by having the >>> PolicyBasedWSS4JIinInterceptor not do UsernameTokens at all and delegate >>> that >>> completely to the UsernameTokenInterceptor. >>> >> >> What I will do is I will experiment with the test you added (thanks :-)) >> and see how UsernameTokenInterceptor can be refactored >> so that a subclass can get an easy access to password, nonce, etc. I think >> I will need to come up with a contextual property so that a custom >> UsernameTokenInterceptor can be installed if needed. Or may be >> UsernameTokenInterceptor can store the details in a message to be later >> retrieved and processed for creating SecurityContext - but I'm not sure >> about it just yet. >> >> >>> >>> Basically, it would be good if the WSS4JIn* stuff just handled the >>> encryption/signature stuff and then let the authorization validations >>> stuff to >>> later interceptors. That would include things like key validation >>> checking >>> and stuff as well. Probably SAML token validation as well. >>> >>> >> sounds good >> >> cheers, Sergey >> >> On Fri, Apr 9, 2010 at 2:50 PM, Daniel Kulp <dk...@apache.org> wrote: >> >>> >>> My main "concern" with the implementation of this is that it's done as a >>> direct subclass of the WSS4JInInterceptor and thus not really usable by >>> the >>> policy based endpoints as those interceptors subclass WSS4JInInterceptor >>> as >>> well. >>> >>> I think the better approach may be to add a flag to wss4j (I can help >>> commit >>> changes there if needed) to have it not do any UserName token processing >>> at >>> all. (aside: this may be doable without changes to wss4j by >>> registering our >>> own "do nothing processor") Then, have another interceptor that runs >>> after >>> the WSS4JInInterceptor that would actually handle the UsernameToken and >>> verify >>> anything it needs and such. >>> >>> To be honest, I WANT to do this for the Policy based stuff anyway. >>> There is >>> currently some duplicated code between the PolicyBasedWSS4JIinInterceptor >>> and >>> the new UsernameTokenInterceptor that could be eliminated by having the >>> PolicyBasedWSS4JIinInterceptor not do UsernameTokens at all and delegate >>> that >>> completely to the UsernameTokenInterceptor. >>> >>> Basically, it would be good if the WSS4JIn* stuff just handled the >>> encryption/signature stuff and then let the authorization validations >>> stuff to >>> later interceptors. That would include things like key validation >>> checking >>> and stuff as well. Probably SAML token validation as well. >>> >>> Dan >>> >>> >>> On Thursday 08 April 2010 12:09:24 pm Sergey Beryozkin wrote: >>> > Hi David >>> > >>> > thanks for the comments... >>> > >>> > On Wed, Apr 7, 2010 at 9:41 PM, David Valeri <dval...@apache.org> >>> wrote: >>> > > Sergey, >>> > > >>> > > I think this type of functionality would be very useful to a number >>> of >>> > > folks. I have built two similar capabilities for clients very >>> recently >>> > > using CXF and Spring Security. Based on the code provided below, I >>> have >>> > > several points that I would like to see addressed in a solution. >>> > > >>> > > 1) Architecture to support more than just UsernameTokens. I have >>> worked >>> > > with systems that need to authenticate a user using UsernameTokens, >>> > > BinarySecurityTokens, SAML Assertions, and a combination of more than >>> one >>> > > of >>> > > these at a time. >>> > >>> > Supporting UsernameTokens is the initial requirement. At the moment I >>> do >>> > not even know how BinarySecurityTokens or SAML Assertions are >>> > processed/validated in CXF or WSS4J. >>> > >>> > > For the most part, WSS4J simply validates the structural >>> > > details of security. That is, signature validity, trust chaining of >>> > > digital >>> > > certificates, etc. As Glen pointed out with his reference to >>> > > https://issues.apache.org/jira/browse/WSS-183, WSS4J sometimes >>> performs >>> > > its >>> > > own password checking (authentication). Unfortunately, WSS4J doesn't >>> > > provide hooks for authenticating other forms of credentials that I >>> have >>> > > listed above (I don't consider trust to be equivalent to >>> authentication). >>> > > It would be best if the authentication interface supported multiple >>> > > credential types and allowed for authentication to be performed in a >>> > > single location in the same manner every time (not sometimes in the >>> > > WSS4J callback and sometimes in another interceptor for non-UT based >>> > > credentials). >>> > >>> > Makes sense. Assuming it is WSS4J which validates (the structure of) >>> > BinarySecurityTokens then >>> AbstractWSS4JSecurityContextProvidingInterceptor >>> > can also implement a processor for BinarySecurityTokens and delegate to >>> > subclass to authenticate and setup a subject. Some extra methods will >>> need >>> > to be added, to be optionally overridden. >>> > >>> > If it is not only WSS4J which is involved then perhaps another option >>> is to >>> > store (from WSS4J callback handler, etc) relevant details such username >>> > token details, etc to be acted upon by other interceptors. >>> > >>> > > That >>> > > last bit there means disabling WSS4J's password authentication since >>> it >>> > > gets >>> > > in the way of doing it later in our own interceptor. >>> > >>> > AbstractWSS4JSecurityContextProvidingInterceptor does it now by >>> > implementing a simplified UsernameTokenProcessor >>> > >>> > > 2) Allow for end-user flexibility in choosing the credentials they >>> want >>> > > to authenticate. For instance, each user is going to have their own >>> > > security profiles and authentication requirements. For instance, a >>> > > message contains a UT for a portal user and a digital signature from >>> the >>> > > portal (I know using >>> > > a SAML Assertion would be better here, but people still do it this >>> way). >>> > > Each organization will have different requirements as to which >>> > > credentials get authenticated and what needs to end up in the >>> security >>> > > context. >>> > >>> > I suppose AbstractWSS4JSecurityContextProvidingInterceptor subclasses >>> > should be able to do it, for username tokens and other tokens later on. >>> > >>> > > 3) Decouple the authentication interface from WSS4J. What is passed >>> in >>> > > needs to be abstracted enough that it can work with other WS-Security >>> > > libraries as well. >>> > >>> > the only WSS4J class which is leaked at the moment is >>> WSSecurityException. >>> > Perhaps we can come up later on with a different more generic approach >>> > which does not depend on WSS4J at all. As Dan indicated, in some cases >>> > WSS4JInInterceptor is not even used, so that case will need to be >>> > addressed. Experimenting wuth binary tokens might help with identifying >>> > another solution. >>> > >>> > > 4) It would be nice to be able to perform authorization using >>> something >>> > > like >>> > > Spring Security at the service operation level. With a POJO or >>> JAX-WS >>> > > based >>> > > service, one can just use Spring Security's method interceptor to >>> provide >>> > > such security; however, in situations where one only has a WSDL based >>> > > service or a provider style service, a method interceptor can't be >>> used. >>> > > >>> > > It >>> > > >>> > > would be nice to provide a hook into Spring Security to allow >>> end-users >>> > > to specify role based authorization policy based on a combination of >>> > > interface, >>> > > instance, and operation names. It seems like your >>> > > AbstractAuthorizingInterceptor and SimpleAuthorizingInterceptor are >>> > > looking in this direction, but I think it would be best if we can >>> stand >>> > > on the shoulders of the Spring Security giant as much as possible so >>> > > that we can take advantage of their rich authorization manager, >>> voter, >>> > > XML >>> > > configuration >>> > > capabilities. >>> > >>> > Not sure what to say here yet. But I think non-Spring users should be >>> taken >>> > care of too. Or when simpler cases are dealt with then perhaps there's >>> no >>> > need to bring in Spring security. Perhaps the utility authorization >>> > interceptors should just not be used when Spring Security is preferred >>> ? >>> > >>> > > 5) Try not to leave the ServiceMix CXF-BC out in the cold. The >>> CXF-BC >>> > > currently has a limited capability to select the credentials to >>> > > authenticate >>> > > and would benefit from 1 and 2 above. The CXF-BC ultimately >>> delegates >>> > > authentication to the JBI container through a ServiceMix components >>> > > authentication service abstraction of JAAS. Whatever solution we >>> have >>> > > for 1 >>> > > and 2 would help out the component if the ServiceMix authentication >>> > > service abstraction could be wired up in lieu of whatever we provide >>> out >>> > > of the box. >>> > >>> > I'm not planning to contribute to ServiceMix. I agree though that an >>> ideal >>> > solution will meet multiple requirements >>> > >>> > thanks, Sergey >>> > >>> > > -----Original Message----- >>> > > From: Sergey Beryozkin [mailto:sberyoz...@gmail.com] >>> > > Sent: Wednesday, April 07, 2010 10:11 AM >>> > > To: dev@cxf.apache.org >>> > > Subject: Using WS-Security UsernameToken to authenticate users and >>> > > populate SecurityContexts >>> > > >>> > > Hi >>> > > >>> > > I've been looking recently at extending the CXF WS-Security component >>> > > such that a current UsernameToken could be used by custom >>> interceptors >>> > > to authenticate a user with the external security systems and, if >>> > > possible, provide enough information for CXF to populate a >>> > > SecurityContext [1] to be used later on for >>> > > authorization decisions. >>> > > >>> > > Here is the approach I've taken so far. >>> > > A custom interceptor extends >>> > > AbstractWSS4JSecurityContextProvidingInterceptor [2] and the only >>> method >>> > > it overrides is >>> > > >>> > > abstract Subject createSubject(String name, String password, boolean >>> > > isDigest, >>> > > >>> > > String nonce, >>> > > String created) throws >>> > > >>> > > WSSecurityException; >>> > > >>> > > >>> > > For example, see [3]. >>> > > >>> > > The idea here is that a custom interceptor interfaces whichever way >>> it >>> > > needs >>> > > to with the external system and populates a Subject following this >>> simple >>> > > rule : first Subject principal is the current user (identified by a >>> > > 'name' argument), followed by one or more Groups this user is a >>> member >>> > > of. AbstractWSS4JSecurityContextProvidingInterceptor will use this >>> > > Subject to provide a functional SecurityContext instance. >>> > > >>> > > This is the first part, next is how to utilize a SecurityContext and >>> get >>> > > the >>> > > expected roles associated one way or the other with a current method >>> to >>> > > be invoked. There's a number of usual options available here, perhaps >>> > > even SpringSecurity can be used now that SecurityContext is >>> available, >>> > > or application code or other custom CXF interceptor can check the >>> known >>> > > roles against SecurityContext. >>> > > >>> > > I've also added AbstractAuthorizingInInterceptor interceptor which >>> custom >>> > > interceptors can override and return a list of expected roles given a >>> > > (service) Method to be invoked upon, AbstractAuthorizingInInterceptor >>> > > will then ask available SecurityContext to match the roles; one >>> concrete >>> > > implementation is SimpleAuthorizingInterceptor[5], it can be injected >>> > > with a >>> > > method specific or class (applying to all methods) roles. Another >>> > > implementation which I will likely add later on will be injected with >>> a >>> > > name >>> > > of annotation such as RolesAlloved and it will introspect a method >>> and >>> > > its class. >>> > > >>> > > Note that I haven't looked into the case when a policy runtimes adds >>> the >>> > > interceptors yet (as opposed to interceptors being configured form >>> > > Spring/programmatically). I think an optional contextual property >>> will >>> > > need to be setup in such cases for users be able to indicate that say >>> an >>> > > interceptor such as [3] has to be used as opposed to >>> WSS4JInInterceptor, >>> > > etc. >>> > > >>> > > I'm going to validate this approach with JBoss CXF. If you have any >>> > > comments >>> > > then please let me know. >>> > > >>> > > I think we may have a simpler alternative eventually to the way >>> > > authorization decisions are made. [1]-[3] is specific to ws-security, >>> but >>> > > [4]-[5] is not >>> > > >>> > > cheers, Sergey >>> > > >>> > > [1] https://issues.apache.org/jira/browse/CXF-2754 >>> > > [2] >>> > > >>> > > >>> http://svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/main/java/or >>> > > g/a >>> > > >>> > > >>> pache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingIntercep >>> > > tor< >>> http://svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/main/jav >>> > > >>> a/org/a%0Apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidi >>> > > ngInterceptor> .java >>> > > [3] >>> > > >>> > > >>> http://svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/test/java/or >>> > > g/a >>> > > >>> pache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java<http:/ >>> > > / >>> svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/test/java/org/a%0A >>> > > pache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java> >>> [4] >>> > > >>> > > >>> http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apach >>> > > e/c >>> > > xf/interceptor/security/AbstractAuthorizingInInterceptor.java< >>> http://svn >>> > > . >>> apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/c%0Axf/i >>> > > nterceptor/security/AbstractAuthorizingInInterceptor.java> [5] >>> > > >>> > > >>> http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apach >>> > > e/c >>> > > xf/interceptor/security/SimpleAuthorizingInterceptor.java< >>> http://svn.apa >>> > > >>> che.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/c%0Axf/inter >>> > > ceptor/security/SimpleAuthorizingInterceptor.java> >>> >>> -- >>> Daniel Kulp >>> dk...@apache.org >>> http://dankulp.com/blog >>> >> >> >