4 Replies Latest reply on Jan 27, 2012 9:04 AM by Marek Posolda

    Either STSClient.issueTokenOnBehalfOf is broken or I don't have something configured correctly.

    Ted Foye Newbie

      Here is my setup.  I an using Picketlink 2.0.1.  I have an SP and IDP using form login, which seem to work properly.  The SP redirects to the IDP which authenticates the user and calls the STS to issue a token (with roles as attributes in the assertion).  The IDP redirects back to the SP passing back the principal name and the SAML assertion.  This is where it starts to get muddy.

       

       

      It seems like the token the SP has at this point should only be used for SSO.  Is this correct?  My though was the SP should get another token so that services (SOAP using CXF) downstream  can use that token for authorization.  I tried to use STSClient.issueTokenOnBehalfOf in a custom login module that extended STSIssuingLoginModule.  Since the user is already authenticated at this point I was trying to allow a trust between the SP and STS to happen by the SP using a sts-client.properties config file. My custom login module would then try to issue a token, the second one in my case, by issuing one on behalf of the authenticated user.  When I call STSClient.issueTokenOnBehalfOf a WSTrustException is thrown with the message "PL00102: Processing Exception:creating source from request: PL00092: Null Value:Id on the UsernameToken".

       

       

      Should the token the IDP gets from the STS be used for SSO only?

      What is the proper way to configure an SP to have a token issued?

       

      Ted

        • 1. Re: Either STSClient.issueTokenOnBehalfOf is broken or I don't have something configured correctly.
          dlaprade Newbie

          I am having a similar issue, and after some digging into the source code this is what I found:

           

          STSClient:


            private RequestSecurityToken setOnBehalfOf(Principal principal, RequestSecurityToken request)

            {

               if (principal != null)

                  request.setOnBehalfOf(WSTrustUtil.createOnBehalfOfWithUsername(principal.getName(), null));

               return request;

            }


           


          WSTrustUtil:


            public static OnBehalfOfType createOnBehalfOfWithUsername(String username, String id)

            {

               AttributedString attrString = new AttributedString();

               attrString.setValue(username);

               UsernameTokenType usernameToken = new UsernameTokenType();

               usernameToken.setId(id);

               usernameToken.setUsername(attrString);

               // create the OnBehalfOfType and set the UsernameTokenType.

               OnBehalfOfType onBehalfOf = new OnBehalfOfType();

               onBehalfOf.add(usernameToken);

               return onBehalfOf;

            }


           

          The STSClient calls WSTrustRequestWriter.write, which calls WSSecurityWriter.write


            public void write(UsernameTokenType usernameToken) throws ProcessingException

            {

               StaxUtil.writeStartElement(writer, WSSE_PREFIX, USERNAME_TOKEN, WSSE_NS);

               StaxUtil.writeNameSpace(writer, WSSE_PREFIX, WSSE_NS);


               String id = usernameToken.getId();

               if (StringUtil.isNullOrEmpty(id))

                  throw new ProcessingException(ErrorCodes.NULL_VALUE + "Id on the UsernameToken");

                   ...

                   ...

                   ...

                  

          Since STSClient passed null in the call to WSTrustUtil.createOnBehalfOfWithUsername, the usernameToken ID is null, causing  WSSecurityWriter.write to throw a ProcessingException(ErrorCodes.NULL_VALUE + "Id on the UsernameToken");

           


          I can not seem to figure out how to get around this issue, can anyone help?


          • 2. Re: Either STSClient.issueTokenOnBehalfOf is broken or I don't have something configured correctly.
            Ted Foye Newbie

            dlaprade,

             

            Your digging led me to a solution.

             

            I created a custom login module that extends STSIssuingLoginModule.

             

                @Override

                public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {

                    super.initialize(subject, callbackHandler, sharedState, options);

                   

                    endpointURI = (String) options.get(ENDPOINT_OPTION);

                    if (endpointURI == null) {

                        endpointURI = (String) options.get(ENDPOINT_ADDRESS); //base class

                    }

                    tokenType = (String) options.get(TOKEN_TYPE_OPTION);

                    if (tokenType == null) {

                        tokenType = SAMLUtil.SAML2_TOKEN_TYPE;

                    }

                }

             

             

                @Override

                public Element invokeSTS(STSClient stsClient) throws WSTrustException {

                    SimpleGroup principal = new SimpleGroup(ServiceProviderSAMLContext.getUserName());

                    return stsClient.issueTokenOnBehalfOf(endpointURI, tokenType, principal);

                }

             

             

            I also modified STSClient changing setOnBehalfOf to

             

                private RequestSecurityToken setOnBehalfOf(Principal principal, RequestSecurityToken request) {

                    if (principal != null) {

                        request.setOnBehalfOf(WSTrustUtil.createOnBehalfOfWithUsername(principal.getName(), UUID.randomUUID().toString()));

                    }

                    return request;

                }

             

            A user who is authenticated through the SSO system (SP and IDP) can now have a token issued to him.  Through login module configuration a user that the STS trusts requests a token for the authenticated user.  The token comes back with the authenticated user for the NameID though he has the trusted STS user's roles.  I can remove the roles through STS configuration and get them by other means downstream.

             

             

            This leads to a couple more questions.

             

            Is the change I made to STSClient valid?

            Does it make sense (and is it secure) for the SP to issue a token for an authenticated user using another set of credentials?

             

             

            Ted

            • 3. Re: Either STSClient.issueTokenOnBehalfOf is broken or I don't have something configured correctly.
              dlaprade Newbie

              Ted,

               

              I found a class:

               

                   WSTrustClient

               

              that contains a method:

               

                   issueTokenOnBehalfOf()

               

              that does what you are trying to do when calling the:

               

                   WSTrustUtil.createOnBehalfOfWithUsername() :

               

              by defaulting the ID:

               

                   request.setOnBehalfOf(WSTrustUtil.createOnBehalfOfWithUsername(principal.getName(), "ID"));

               

              I am not sure what the difference between the two classes: WSTrustClient and STSClient....

              • 4. Re: Either STSClient.issueTokenOnBehalfOf is broken or I don't have something configured correctly.
                Marek Posolda Expert

                Hi,

                 

                the part with

                 

                {code}

                STSClient:


                  private RequestSecurityToken setOnBehalfOf(Principal principal, RequestSecurityToken request)

                  {

                     if (principal != null)

                        request.setOnBehalfOf(WSTrustUtil.createOnBehalfOfWithUsername(principal.getName(), null));

                     return request;

                  }

                {code}

                 

                is obviously a bug, which causes that STSClient.issueTokenOnBehalfOf always ends with exception . I created a JIRA for it and it's fixed in latest Picketlink federation trunk. You can check JIRA https://issues.jboss.org/browse/PLFED-260 .

                 

                Thanks for pointing out this!

                Marek