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.get
> 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