dev@glassfish.java.net

Re: custom SAM using glassfish SSO?

From: Derek Knapp <derek.knapp_at_me.com>
Date: Mon, 24 Sep 2012 10:06:54 -0700

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