Hi Colm, Yes, I confirm that the custom Validator is returning both a transformed token and a principal. As you said, the custom principal is not passed to the ClaimsHandler. However, if I set a custom transformed token, I am able to affect the resulting NameID value.
Many thanks for looking into this! Filip -----Original Message----- From: Colm O hEigeartaigh [mailto:[email protected]] Sent: Thursday, January 30, 2014 12:46 PM To: [email protected] Subject: Re: (Fediz) STS - passing info from LoginModule to ClaimsHandler Hi Filip, Just as a sanity check, could you confirm that your custom Validator is returning both a transformed token via credential.getTransformedToken() and a principal via credential.getPrincipal()? Looking at the code, the UsernameTokenProcessor in WSS4J does not accept the returned principal from Credential.getPrincipal(), so I think this is the problem. I will fix this for the next release of WSS4J. Colm. On Tue, Jan 28, 2014 at 2:58 PM, Hoefer, Filip <[email protected]> wrote: > Hi Colm, > > Thank you for your hints. I have put the code in place as you > suggested. I set a custom Principal in my custom Validator via > credential.setPrincipal(). Even so, I still have the same results in > my > ClaimsHandler: > > Code: > parameters.getPrincipal(); > Returns: > org.apache.ws.security.SAMLTokenPrincipal > > Code: > MessageContext messageCtx = > parameters.getWebServiceContext().getMessageContext(); > SecurityContext secCtx = > (SecurityContext)messageCtx.get(SecurityContext.class.getName()); > secCtx.getUserPrincipal(); > Returns: > null > > > Best regards, > > Filip > > -----Original Message----- > From: Colm O hEigeartaigh [mailto:[email protected]] > Sent: Monday, January 27, 2014 5:10 PM > To: [email protected] > Subject: Re: (Fediz) STS - passing info from LoginModule to > ClaimsHandler > > Hi Filip, > > I believe there is a way of doing this without resorting to ThreadLocals. > In your custom Validator implementation, trying setting the custom > Principal you are creating on the returned Credential Object. WSS4J's > SAMLTokenProcessor, for example, has the following code: > > else if (credential.getPrincipal() != null) { > result.put(WSSecurityEngineResult.TAG_PRINCIPAL, > credential.getPrincipal()); > } > > This will result in the created Principal Object being set on the > security context, instead of the SAMLTokenPrincipal. You should be > able to access it in the ClaimsHandler with something like: > > MessageContext messageCtx = > parameters.getWebServiceContext().getMessageContext(); > SecurityContext secCtx = > (SecurityContext)messageCtx.get(SecurityContext.class.getName()); > secCtx.getUserPrincipal(); > > Colm. > > > > On Mon, Jan 27, 2014 at 2:55 PM, Hoefer, Filip <[email protected]> > wrote: > > > Hi, > > > > Unfortunately, the trick does not work for me. In my environment, > > even the STS validator sometimes runs in a different thread than the > ClaimsHandler. > > I will probably have to implement an own STS. Anyway, many thanks > > for your support, at least I have investigated all possible options. > > > > Best regards, > > > > Filip > > > > -----Original Message----- > > From: Andrei Shakirin [mailto:[email protected]] > > Sent: Friday, January 24, 2014 2:31 PM > > To: [email protected] > > Cc: Colm O hEigeartaigh > > Subject: RE: (Fediz) STS - passing info from LoginModule to > > ClaimsHandler > > > > > > Hi, > > > > I used ThreadLocal not in LoginModule itself, but in STS validator > > invoking JAAS for login: > > > > <bean id="validator" > > class="org.sopera.csg.tesbext.sts.jaas.JAASValidator"> > > <argument value="sts-ut" /> > > </bean> > > > > <jaxws:endpoint id="utSTS" implementor="#stsProvider" > > address="/SecurityTokenService/UT" > > wsdlLocation="wsdl/ws-trust-1.4-service.wsdl" > > xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512/" > > serviceName="wst:SecurityTokenService" > endpointName="wst:UT_Port"> > > <jaxws:properties> > > <entry key="ws-security.ut.validator" value-ref="validator" > /> > > </jaxws:properties> > > </jaxws:endpoint> > > > > public class JAASValidator implements Validator { ... > > @Override > > public Credential validate(Credential credential, RequestData > > data) throws WSSecurityException { > > UsernameToken userNameToken = credential.getUsernametoken(); > > validateUserNameToken(userNameToken); > > try { > > STSCallBackHandler callbackHandler = new > > STSCallBackHandler(userNameToken, null); > > LoginContext lc = new LoginContext(this.contextName, > > callbackHandler); > > lc.login(); > > Subject subject = lc.getSubject(); > > SecContext.setSubject(subject); ... > > } catch (LoginException e) { > > throw new WSSecurityException(e.getMessage(), e); > > } > > } > > > > The validator is always called in the same thread with ClaimsHandler > > , but not sure is this a solution for you. > > > > The clean way will be to extend CalimsHandler.retrieveClaimValues() > > with the security context subject argument and pass it through. > > > > @Colm: do you see more elegant way to proceed that? > > > > Regards, > > Andrei. > > > > > -----Original Message----- > > > From: Hoefer, Filip [mailto:[email protected]] > > > Sent: Freitag, 24. Januar 2014 12:56 > > > To: [email protected] > > > Subject: RE: (Fediz) STS - passing info from LoginModule to > > > ClaimsHandler > > > > > > Hello, > > > > > > Unfortunately, it appears that the LoginModule and the > > > ClaimsHandler sometimes each use a different thread to handle a single > > > request. > > > Therefore, a ThreadLocal variable does not reliably facilitate > > > state > > sharing. > > > > > > @Andrei: Did you get it running in your environment? > > > > > > @others: Any other ideas? > > > > > > Thank you > > > > > > Filip > > > > > > -----Original Message----- > > > From: Hoefer, Filip [mailto:[email protected]] > > > Sent: Wednesday, January 22, 2014 4:59 PM > > > To: [email protected] > > > Subject: RE: (Fediz) STS - passing info from LoginModule to > > > ClaimsHandler > > > > > > > > > Hi Andrei, > > > > > > Many thanks for your response! Your suggestion really appears to > > > be the only viable solution at this time. It also occurred to us > > > that we could use the subject Name to carry an internal ID from > > > LoginModule to ClaimsHandler and then rewrite it to an external ID > > > in > ClaimsHandler. > > > Unfortunately, rewriting the NameID value in ClaimsHandler has no > > > effect. So I think I will go ahead with your suggestion. > > > > > > Filip > > > > > > -----Original Message----- > > > From: Andrei Shakirin [mailto:[email protected]] > > > Sent: Wednesday, January 22, 2014 10:36 AM > > > To: [email protected] > > > Subject: RE: (Fediz) STS - passing info from LoginModule to > > > ClaimsHandler > > > > > > > > > Hi, > > > > > > Yep, I had the similar case in STS: custom claims handler should > > > validate user role received in RST as claim. > > > However user role is determined in LoginModule through JAAS > > > (invoked by ws-security.ut.validator validator). > > > Therefore it was necessary to pass Subject/Principle from the > > > LoginModule to ClaimHandler for validation. > > > > > > We did not find better solution as introducing custom > > > SecurityContext with > > > ThreadLocal: > > > > > > public final class SecContext { > > > static ThreadLocal<Subject> subject = new ThreadLocal<Subject>(); > > > private SecContext() { > > > } > > > public static void setSubject(Subject subject2) { > > > SecContext.subject.set(subject2); > > > } > > > public static Subject getSubject() { > > > return subject.get(); > > > } > > > } > > > > > > Validator: > > > LoginContext lc = new LoginContext(this.contextName, > > > callbackHandler); > > > lc.login(); > > > Subject subject = lc.getSubject(); > > > SecContext.setSubject(subject); > > > > > > Claim Handler: > > > Subject subject = SecContext.getSubject(); > > > Set<Principal> groups = subject.getPrincipals(); > > > List<String> roles = new ArrayList<String>(); > > > for (Principal group : groups) { > > > if > > > > > ("org.apache.karaf.jaas.boot.principal.RolePrincipal".equals(group.g > > et > > Class() > > > .getName())) { > > > roles.add(group.getName()); > > > } > > > } > > > ... > > > > > > I think it will be nice to provide a possibility to access all > > > custom Principles in ClaimsHandler - will think about that. > > > > > > Regards, > > > Andrei. > > > > > > > -----Original Message----- > > > > From: Hoefer, Filip [mailto:[email protected]] > > > > Sent: Dienstag, 21. Januar 2014 13:16 > > > > To: [email protected] > > > > Subject: (Fediz) STS - passing info from LoginModule to > > > > ClaimsHandler > > > > > > > > Hello, > > > > > > > > I am implementing a custom LoginModule and a custom > > > > ClaimsHandler for the Fediz STS. The custom classes are > > > > integrated into Fediz via config files, no problem. However, I > > > > do not know how to pass information from my LoginModule to my > > > > ClaimsHandler. I create a custom Principal (with custom > > > > claims) in the LoginModule based on authentication via an > > > > external security server. The problem is that the ClaimsHandler > > > > always only receives a SAMLTokenPrincipal which will not give me > > > > access to the custom claims. So far, do not see any alternative > > > > to accessing user account via the identifier from > > > > SAMLTokenPrincipal.getName(). > > > > But that only gives me access to the static user account, not to > > > > the transient state > > > created during login. > > > > > > > > Please let me know if I oversee something, any help is appreciated. > > > > > > > > Kind regards, > > > > > > > > Filip Hofer > > > > > > -- > Colm O hEigeartaigh > > Talend Community Coder > http://coders.talend.com > -- Colm O hEigeartaigh Talend Community Coder http://coders.talend.com
