GWT & Spring Security

1,560 views
Skip to first unread message

dhoffer

unread,
Jun 12, 2012, 8:47:47 PM6/12/12
to Google Web Toolkit
I'd like to get feedback on the best way to secure GWT apps with
Spring Security. I read several existing blogs about this online but
they are all (that I have found) quite old at this point.
Specifically what's the best way with GWT 2.4 and Spring Security
3.1? Or is there a better way other than Spring Security?

Joseph Lust

unread,
Jun 13, 2012, 11:26:10 AM6/13/12
to google-we...@googlegroups.com
I'm sure other folks' examples will differ, but we did the following:

  1. Entitlements set as an Enum like enum UserEntitlement { VIEW_HOME, VIEW_ITEM, ADD_ITEM, DELETE_ITEM }
  2. On user login,  UserEntitlement[] fetch sent from backend to client
  3. Restricted UI elements are enabled based on the entitlements found in (2)
  4. When RPC's are done, Spring Method level security used to confirm that the user has the proper entitlement to run that method

Basically the nice part is just using the annotations to secure remote methods and the concomitant alteration of the UI based on the user entitlements.

I did not mention using Spring to restrict access to files since GWT pushes the entire compiled application to the client first. Because of this, there really are not pages to protect, just RPC's with method level security, in case someone spoofs their entitlements on the client side.


Sincerely,
Joseph

Juan Pablo Gardella

unread,
Jun 13, 2012, 11:32:57 AM6/13/12
to google-we...@googlegroups.com
Thanks Joseph for sharing your experiences.

I have a question regards this, for example you have a button that is enabled to ADD_ITEM. Do you extends GWT compents for show for some 'actions' or make some if statements?

Is a simple question, but is nice to know how deal with this. The extend of component is more concise but we need to customize N components for example and the other way make the code complex to mantain.

Thanks

2012/6/13 Joseph Lust <lifeo...@gmail.com>

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-web-toolkit/-/PZHZgoV_A84J.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.

Joseph Lust

unread,
Jun 13, 2012, 5:56:18 PM6/13/12
to google-we...@googlegroups.com
Jaun,

Our application is nearly 100% custom components. We did not use many of the default GWT widgets. We also used UiBinder for everything and thus most screens are a bundle of widgets stitched together with UiBinder.

If there was a custom panel/button/widget, it would have a setUserEntitlement() method. Then in the .ui.xml you can have
<someNameSpace: myCustomWidget  userEntitlement = {ADD_ITEM} />

Now those components will check for their entitlement on load from a globally available UserEntitlements[] that was loaded at application startup and enable themselves if authorized. A nice thing about this is all the entitlements are just enums in the UiBinder so you get compile time checking of that too, and no entitlements hardcoded in Java files.

Of course users can hack the UI, so there is also a backend method level check for RPC's.


Sincerely,
Joseph

Juan Pablo Gardella

unread,
Jun 13, 2012, 6:00:05 PM6/13/12
to google-we...@googlegroups.com
Thanks Joseph for sharing your experiences on this!! You are really helpful at the group

Juan

2012/6/13 Joseph Lust <lifeo...@gmail.com>


Sincerely,
Joseph

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.

dhoffer

unread,
Jun 14, 2012, 10:04:57 PM6/14/12
to Google Web Toolkit
Joseph,

How do you handle Spring's 'remember me', session management and auto
login/logout? I'm curious how you setup your use of Spring. Could
you post your configuration? I assume you don't use Spring's auto-
config, etc?

Thanks,
-Dave

On Jun 13, 3:56 pm, Joseph Lust <lifeofl...@gmail.com> wrote:
> Jaun,
>
> Our application is nearly 100% custom components. We did not use many of
> the default GWT widgets. We also used UiBinder for everything and thus most
> screens are a bundle of widgets stitched together with UiBinder.
>
> If there was a custom panel/button/widget, it would have a
> setUserEntitlement() method. Then in the .ui.xml you can have
> <someNameSpace: myCustomWidget  userEntitlement = {ADD_ITEM} />
>
> Now those components will check for their entitlement on load from a
> globally available *UserEntitlements[] *that was loaded at application

Jordi P.S.

unread,
Jun 15, 2012, 3:18:29 PM6/15/12
to google-we...@googlegroups.com
I have a login JSP that uses the remember me feature.so I have my login under Spring Security.

I have method security enabled in the RPC layer. All my RPCs extend a base class and then I used annotations on the methods to check for the permissions.

Here the RPC Base Servlet class:  http://pastebin.com/Z6mj4pZi 

Joseph Lust

unread,
Jun 16, 2012, 2:18:19 PM6/16/12
to google-we...@googlegroups.com
Dave,

Since it is an enterprise application, authentication is handled by a SSO service which hands off to our application, so there is no "remember me" functionality. The less work your application has to do the better, just like using Gmail/fb auth on a website.

Here is the redacted and comment Spring Security config:

Note that this is just a standard Spring Security config, but that the custom preauthoization filter is where the magic happens. That is where you'd do the lookup of your users to get entitlements and then store those in their session. These are what the Spring Method level security will check against. Checkout the famously verbose Spring Documentation on this. Basically you just extend some of their interfaces and classes per the instructions and you should be off to the races.

Sincerely,
Joseph
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:p="http://www.springframework.org/schema/p"
             xsi:schemaLocation=
                     "http://www.springframework.org/schema/beans
                      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                      http://www.springframework.org/schema/security
                      http://www.springframework.org/schema/security/spring-security-3.0.xsd">

    <!-- Setup Spring Security -->
    <http auto-config="false" entry-point-ref="entryPoint" access-denied-page="/unprotected/sso_Error.jsp">
        <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/> <!-- These resources are protected -->
        <custom-filter position="PRE_AUTH_FILTER" ref="preAuthProcessingFilter"/>
    </http>

	<!-- Users get this on auth failure -->
    <beans:bean id="entryPoint"
        class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>

	<!-- Authorization filter does user authorization -->
    <beans:bean id="preAuthProcessingFilter"
    class="com.foo.custom.PreAuthenticationFilter">
        <beans:property name="authenticationManager" ref="authenticationManager"/>
    </beans:bean>
    
    <authentication-manager alias="authenticationManager">
        <authentication-provider ref="preAuthAuthProvider"/>
    </authentication-manager>

	<!-- Custom preAuthAuthProvider -->
    <beans:bean id="preAuthAuthProvider"
    class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
        <beans:property name="preAuthenticatedUserDetailsService" >
        	<beans:bean id="preAuthenticationUserDetailsService"
            class="com.foo.custom.UserDetailsService" />
        </beans:property>
    </beans:bean>

dhoffer

unread,
Jun 17, 2012, 8:27:47 PM6/17/12
to Google Web Toolkit
Could you also post your autowired beans setSecuredDecisionManager &
setSecurityMetadataSource?

Also since I just have plain GWT app (no JSP) can I assume that I
don't need the handleRequest() method?  I assume the security work is
done in onAfterRequestDeserialized()?

Thanks,
-Dave

dhoffer

unread,
Jun 17, 2012, 8:42:43 PM6/17/12
to Google Web Toolkit
Hi Joseph,

Thanks so much for your help. I'm having trouble getting this to
work. In my case the methods on PreAuthenticationFilter &
CustomUserDetailsService are never called.

Here is my code/config:
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/
beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">

<!-- Setup Spring Security -->
<http auto-config="false" entry-point-ref="entryPoint" access-
denied-page="/unprotected/sso_Error.jsp">
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>
<!-- These resources are protected -->
<custom-filter position="PRE_AUTH_FILTER"
ref="preAuthProcessingFilter"/>
</http>

<!-- Users get this on auth failure -->
<beans:bean id="entryPoint"

class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/
>

<!-- Authorization filter does user authorization -->
<beans:bean id="preAuthProcessingFilter"

class="com.qsd.callcenterquestionnaire.server.security.auth.PreAuthenticationFilter">
<beans:property name="authenticationManager"
ref="authenticationManager"/>
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="preAuthAuthProvider"/>
</authentication-manager>

<!-- Custom preAuthAuthProvider -->
<beans:bean id="preAuthAuthProvider"

class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService">
<beans:bean id="preAuthenticationUserDetailsService"

class="com.qsd.callcenterquestionnaire.server.security.auth.CustomUserDetailsService"/
>
</beans:property>
</beans:bean>

<global-method-security secured-annotations="enabled"/>
</beans:beans>

public class CustomUserDetailsService implements
AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken>
{
public CustomUserDetailsService() {
}

@Override
public UserDetails loadUserDetails(final
PreAuthenticatedAuthenticationToken username) throws
UsernameNotFoundException {
return new UserDetails() {
@Override
public Collection<? extends GrantedAuthority>
getAuthorities() {
final ArrayList<GrantedAuthority> grantedAuthorities =
new ArrayList<GrantedAuthority>();
grantedAuthorities.add(new
SimpleGrantedAuthority("ROLE_USER"));
return grantedAuthorities;
}

@Override
public String getPassword() {
return (String)username.getCredentials();
}

@Override
public String getUsername() {
return (String)username.getPrincipal();
}

@Override
public boolean isAccountNonExpired() {
return true;
}

@Override
public boolean isAccountNonLocked() {
return true;
}

@Override
public boolean isCredentialsNonExpired() {
return true;
}

@Override
public boolean isEnabled() {
return true;
}
};
}
}


public class PreAuthenticationFilter extends
AbstractPreAuthenticatedProcessingFilter {
public PreAuthenticationFilter() {
}

@Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest
request) {
return "dave";
}

@Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest
request) {
return "password";
}
}

I assume then that RPC methods are secured via
@Secured({"ROLE_USER","ROLE_ADMIN"})? Also I assume these have to be
Spring managed beans, I've not used Spring with GWT before, how do you
tell GWT to use Spring to create these services?

Any help is greatly appreciated.

Thanks,
-Dave

On Jun 16, 12:18 pm, Joseph Lust <lifeofl...@gmail.com> wrote:
> Dave,
>
> Since it is an enterprise application, authentication is handled by a SSO
> service which hands off to our application, so there is no "remember me"
> functionality. The less work your application has to do the better, just
> like using Gmail/fb auth on a website.
>
> Here is the redacted and comment Spring Security config:
>
> Note that this is just a standard Spring Security config, but that the
> custom preauthoization filter is where the magic happens. That is where
> you'd do the lookup of your users to get entitlements and then store those
> in their session. These are what the Spring Method level security will
> check against. Checkout the famously verbose Spring Documentation on this<http://static.springsource.org/spring-security/site/docs/3.0.x/refere...>. Basically you
> just extend some of their interfaces and classes per the instructions and
> you should be off to the races.
>
> Sincerely,
> Joseph
>
> <?xml version="1.0" encoding="UTF-8"?><beans:beans xmlns="http://www.springframework.org/schema/security"
>              xmlns:beans="http://www.springframework.org/schema/beans"
>              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>              xmlns:p="http://www.springframework.org/schema/p"
>              xsi:schemaLocation=
>                      "http://www.springframework.org/schema/beans                     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd                     http://www.springframework.org/schema/security                     http://www.springframework.org/schema/security/spring-security-3.0.xsd">
>
>     <!-- Setup Spring Security -->
>     <http auto-config="false" entry-point-ref="entryPoint" access-denied-page="/unprotected/sso_Error.jsp">
>         <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/> <!-- These resources are protected -->
>         <custom-filter position="PRE_AUTH_FILTER" ref="preAuthProcessingFilter"/>
>     </http>
>
>         <!-- Users get this on auth failure -->
>     <beans:bean id="entryPoint"
>         class="org.springframework.security.web.authentication.Http403ForbiddenEntr yPoint"/>

Jordi Planadecursach

unread,
Jun 22, 2012, 6:09:30 AM6/22/12
to Google Web Toolkit
Hello,

Indeed you don't need the 2 autowired services. I use them since I
have my own decisionManager. You can use a standard one, for example
the role based. This means no autowireds neither
"onAfterRequestDeserialized". If you don't play with sessions you
don't need the workaround fix inide "handleRequest". Nevertheless
"handleRequest" is compulsory because is the one that bridges the HTTP
GET/POST to the RPC handler.

I recommend you the following article:
http://blog.maxmatveev.com/2010/04/spring-managed-gwt-remote-service.html

Hope it has been helpful.

Jordi.

dhoffer

unread,
Jun 22, 2012, 5:13:48 PM6/22/12
to Google Web Toolkit
Jordi,

Yes the link you provided was excellent, with that I have spring
managed beans that are RPC services.

However I'm having trouble understanding how to add Spring Security to
that. Ideally I'd love to see that example expanded to show how to
add users, assign users role(s) & secure RPC methods.

For instance with your RemoteServiceImpl class I have been adding the
methods you had in your BaseRemoteRPCService class you put in
pastebin...but methods like onAfterRequestDeserialized(RPCRequest)
never get called. However if I add @Secured({"ROLE_USER"}) to your
TestServiceImpl service method it does fail because of authentication
(as expected)...but I don't know where that failure is coming from and
how to manage it.

I think I'm close but not quite understanding how to get the security
part to work properly.

-Dave

On Jun 22, 4:09 am, Jordi Planadecursach <planad...@gmail.com> wrote:
> Hello,
>
> Indeed you don't need the 2 autowired services. I use them since I
> have my own decisionManager. You can use a standard one, for example
> the role based. This means no autowireds neither
> "onAfterRequestDeserialized". If you don't play with sessions you
> don't need the workaround fix inide "handleRequest". Nevertheless
> "handleRequest" is compulsory because is the one that bridges the HTTP
> GET/POST to the RPC handler.
>
> I recommend you the following article:http://blog.maxmatveev.com/2010/04/spring-managed-gwt-remote-service....

Joseph Lust

unread,
Jun 23, 2012, 10:19:33 AM6/23/12
to google-we...@googlegroups.com
David,

My apologies for not getting back to you. I've been thinking about the correct answer. You describe the issue of the error being thrown if the user does not have the proper role. In our implementation that was considered sufficient, since it prevented the user from accessing a remote method they should not.

If you want to fail gracefully, you can redirect that method security exception to another page using your web.xml.
<!-- web.xml -->
<error-page>
    <exception-type>org.springframework.security.access.AccessDeniedException</exception-type>
    <location>yourMethodAccessDenied.jsp</location>
</error-page>

There are other ways in Spring to cleanly map these exceptions as detailed here. This would work well if you're using JSON or REST.

However, if you're using GWT-RPC, then I'm not sure how to make a clean response using the same RPC serializer that the client side GWT is expecting to hear back from. You would probably need to access more of the GWT-RPC internals to achieve that.


Sincerely,
Joseph
Reply all
Reply to author
Forward
0 new messages