dev@glassfish.java.net

Re: custom SAM using glassfish SSO?

From: Derek Knapp <derek.knapp_at_me.com>
Date: Sat, 22 Sep 2012 08:24:05 -0700

Thanks for the tip, I will keep this in mind, and look forward to hearing any other suggestions the weld people may have.


I am having one more problem with my SAM, which is related to SSO. In app #1, where the user logs in, everything is working properly. But in app #2, I can't get my security-constraint to work properly.

I have a non-secured jsp page that simply prints out the principal, and true/false in the user is in the "users" role, and that is working properly (in both apps).. the problem when I add in a security-constraint, requiring the "users" role.. I just get a blank page returned.

In my SAM, I am simply returning SUCCESS if I see that the user principal is not null (was set by glassfish SSO).

        if (requestPolicy.isMandatory())
        {
            log.info(request.getUserPrincipal()); // both of these return what I would expect
            log.info(request.isUserInRole("users"));

            if (request.getUserPrincipal() == null)
            {
                try
                {
                    log.info("redircting");
                    response.sendRedirect("https://login.example.com");
                    return AuthStatus.SEND_SUCCESS;
                }
                catch (IOException e1)
                {
                    log.error("error redirecting to login", e1);
                }
            }

            return AuthStatus.SUCCESS;
        }

If I add in the following code before returning SUCCESS everything works properly.. but I don't really have any way to do this unless I can some how get my custom principal back.. I tried to use the Principal from request.getUserPrincipal, but that means I loose my custom principal, because request.getUserPrincipal returns a class com.sun.enterprise.security.web.integration.WebPrincipal. Everything also works if I remove my SAM from app #2, but then I don't get redirected to my login page properly (which I could solve using a filter, but that doesn't seem like the right solution).

I don't know if this makes sense, so please let me know if it doesn't

            try
            {
                handler.handle(new Callback[]{
                    new CallerPrincipalCallback(clientSubject, new FreeMarketerUser("test", "test")),
                    new GroupPrincipalCallback(clientSubject, new String[] {"cn=users,ou=Groups,dc=example,dc=com"})
                });
            }
            catch (Exception e)
            {
                log.error("error in callback", e);
            }






On Sep 22, 2012, at 4:56 AM, JJ Snyder <j.j.snyder_at_oracle.com> wrote:

> Be very careful...The injection of the object depends on the scope of the object being injected. So if you're doing this on a servlet make sure you annotate the producer with @RequestScoped. Weld will still build a proxy but this time you will be able to cast the proxy to the type returned by the producer. So if your producer is:
>
> @Produces
> @RequestScoped
> public MyCustomPrincipal getCustomPrincipal() { return howeverYouGetTheCustomPrincipal; }
>
> And your injection point is:
> @Inject
> Principal principal;
>
> private void someMethod() {
> // this cast works because the weld proxy is typed to the return type of the producer
> MyCustomPrincipal mcp = (MyCustomPrincipal) principal;
>
> // you could also inject like this and then you wouldn't have to cast
> // @Inject
> // MyCustomPrincipal principal;
>
> }
>
>
> I will ask the weld people if they have any other suggestions.
>
> JJ
>
>
> On 09/21/2012 10:46 PM, Derek Knapp wrote:
>> I have tried casting, and it does not work.
>>
>> I was able to look up the SessionContext, and call getCallerPrincipal which returned my custom principal.. I will likely wrap this logic, and add a @Produces annotation so I can directly @Inject my custom principal. if anyone has a better way to get my custom principal, please let me know.
>>
>>
>> Derek
>>
>> On Sep 21, 2012, at 7:20 AM, JJ Snyder<j.j.snyder_at_oracle.com> wrote:
>>
>>> Derek,
>>> Weld, the CDI container, creates a proxy (org.jboss.weld.security.Principal) to the current caller principal (your custom principal). The proxy is always injected so that it can delegate the method calls to the current caller principal. I have not tried it and I doubt it will work but you might be able to cast to your custom type.
>>>
>>> JJ
>>>
>>> On 09/21/2012 04:44 AM, Derek Knapp wrote:
>>>> Is it possible to @Inject my custom principal in to an ejb?
>>>>
>>>> It seems that when I inject a principal using,
>>>>
>>>> @Inject
>>>> private Principal principal;
>>>>
>>>> it returns a org.jboss.weld.security.Principal, which seems to wrap my custom principal (I say this because the toString method uses my custom principal's toString)
>>>>
>>>> Normally this wouldn't matter, but I actually have some custom data I was hoping to access.
>>>>
>>>>
>>>> Derek
>>>>
>>>> On Sep 17, 2012, at 11:27 AM, Ron Monzillo<ron.monzillo_at_oracle.com> wrote:
>>>>
>>>>> On 9/17/12 10:38 AM, Derek Knapp wrote:
>>>>>> Is there any way for my custom SAM to use glassfish's build in SSO abilities?
>>>>>>
>>>>>> If not, anyone have any experience doing SSO across multiple applications with a custom SAM?
>>>>> Derek,
>>>>>
>>>>>
>>>>> Yes, by using a proprietary extension to the Servlet Profile of JASPIC, a SAM can tell the Glassfish
>>>>> Servlet container to "register" an authentication session.
>>>>>
>>>>> From validateRequest, and after having used the container callback handler to
>>>>> set the caller identity, the SAM would return the following key value pair in the MessageInfo (map)
>>>>>
>>>>> key = "com.sun.web.RealmAdapter.register"
>>>>> value = "true"
>>>>>
>>>>> Then when the SAM returns to the container, with return value AuthStatus.SUCCESS,
>>>>> the container will bind the request to a container authentication session.
>>>>>
>>>>> Ron