dev@glassfish.java.net

Re: custom SAM using glassfish SSO?

From: Derek Knapp <derek.knapp_at_me.com>
Date: Thu, 27 Sep 2012 22:06:20 -0700

I have pretty much given up on using the Glassfish build in SSO ability.. so I was considering the following alternative.. anyone see any issues with it?

Creating a Singleton EJB with a remote interface. Then in my SAM, I can simply call the EJB, pass it my custom principal in exchange for a UUID which I can add to a cookie... Then in the second app, just exchange the UUID for my custom principal...


Derek

On Sep 24, 2012, at 10:06 AM, Derek Knapp <derek.knapp_at_me.com> wrote:

> Thanks. This makes sense.
>
> My other issue is still causing me a pretty big problem tho :(
>
> It seems that if I have a security-constraint, then I can't rely on "com.sun.web.RealmAdapter.register", and must manually use CallerPrincipalCallback / GroupPrincipalCallback to set the principal and groups.
>
> Is there any way for me to retrieve the principal and group(s) from Glassfish?
>
>
> Your help is greatly appreciated!
>
>
> Derek
>
> On Sep 24, 2012, at 7:11 AM, JJ Snyder <j.j.snyder_at_oracle.com> wrote:
>
>> So I did a little test. You have to distinguish your producer from the built-in "producer" of the Principal. So this worked:
>>
>> // Producer
>> @Produces
>> @RequestScoped
>> @CustomPrincipalQualifier
>> public CustomPrincipalImpl getPrincipal() {
>> return new CustomPrincipalImpl();
>> }
>>
>> // Injection point
>> @Inject
>> @CustomPrincipalQualifier
>> private Principal principal;
>>
>> Because the producer produces CustomPrincipalImpl you can cast:
>> if ( principal instanceof CustomPrincipalImpl ) {
>> m_out.println( ( ( CustomPrincipalImpl) principal).foo() );
>> }
>>
>> Or you can kill the qualifier (from the producer too) and do an injection of:
>> @Inject
>> private CustomPrincipalImpl principal;
>>
>> // and no casting later is required.
>>
>> JJ
>>
>> On 09/22/2012 11:24 AM, Derek Knapp wrote:
>>> 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
>