Ladislav, as the founder and manager at Seges Ltd., is heavily interested in open-source community trying to spread knowledge about Java technologies, especially Google Web Toolkit. Participating in several open-source projects and organizing local meetups and discussions he believes in broader collaboration and increasing code quality among local and also abroad developers. Ladislav has posted 8 posts at DZone. View Full User Profile

Securing GWT Clients With AcrIS

08.10.2010
| 8391 views |
  • submit to reddit

Let’s face it fellow developers, our applications tend to grow. And especially with new features and fancy features. And some of them are supposed to be hidden, unless the users are privileged to see its beauty. And to have privileged users you need a fancy login screen with various user roles behind. And as you already know Google Web Toolkit is the right choice to develop your application... but there is no support for securing (it is better to say - hiding) your dialogs, panels, features from curious but unprivileged users. So don’t lose the attention and let me show you how to do it using acris-security.

And what would you say about this piece of code?

public class CustomerPanel extends SecuredComposite {
...

@Secured(Grants.SECURITY_MANAGEMENT)
protected TextBox securityID;

...
}

Would you expect that it will show a pretty neat text box only to those who have the privilege to see and manage sensitive information about a customer? Yes! This will do the thing. And it will also differentiate the permission to just see (but not change) the text box and to actually change the value. But one step at a time...

Common lifecycle of a “secured” web

Let’s assume the following lifecycle of our example web application that presents a user with a login panel.

secured web lifecycle

If the user is allowed to access the restricted area represented by a “secured” form, it will display it and applies authorities to the fields of the form. After the user fills the fields and saves the values he will log out. In case the user is not allowed, an informative page will pop-up and if the web is available for public access it can offer a registration form.

The aim of acris-security is to:

  • Provide access to user services and offer couple of default implementations (currently Spring Security)
  • Allow developers to implement client-side security using annotations and also have full programmatic control
  • Be open to various extensions (own concepts of user relations to authorities, user services, ways of defining security constraints on components,...)

Client security

Enough of theory, let’s jump into an example. For the purpose of this article I will use the showcase available for acris-security. The showcase uses security annotations and also GWT’s UIBinder. The first and one of the most interesting panels is the CustomerPanel with fields ready to be secured:

public class CustomerPanel extends SecuredComposite {
interface CustomerViewUiBinder extends UiBinder<Widget, CustomerPanel> {}

private static CustomerViewUiBinder uiBinder = GWT.create(CustomerViewUiBinder.class);

@UiField
@Secured(value = Grants.SECURITY_MANAGEMENT, permission = Permission.CREATE)
protected TextBox name;

@UiField
@Secured(Grants.SECURITY_MANAGEMENT)
protected TextBox securityID;

public CustomerPanel() {
initWidget(uiBinder.createAndBindUi(this));
}
}

As you can see @UiField and @Secured (from the package sk.seges.acris.security.client.annotations) are not fighting against each other and live in perfect harmony. Also you can note a constant in Grants interface. A grant is a friendly representation of the authority describing what for it is. And an authority is a string token representing "what the user is allowed to do". Authorities are stored per user in a storage (database, file,...) or are “computed” e.g. from a user’s role (or using your own design of relations between users and authorities). A grant isn’t a sufficient description of what exact representation a component is. There must be an information about permission specifying what the user can actually do with the component secured by the grant. The authority wraps the grant and the permission into one string representation.

So if you annotate a component with Grants.SECURITY_MANAGEMENT (string “security_management”) you implicitly say that if the user has authority::

  • ROLE_security_management_VIEW - he is allowed to just see but not change the value of the component
  • ROLE_security_management_EDIT - he is allowed to put a value in there

And of course you can override this behaviour as in the case of “name” text box where the CREATE permission is required. More about the theory and vocabulary is available in the Concept section.

acris-security is in symbiosis with Spring Security and if you are already using Spring Security’s authorities you can reuse them on the client side directly. You just need to strip the “ROLE_” prefix and be conformant with the grant/permission stuff.

Fields are annotated, let’s instantiate the panel:

CustomerPanel customerPanel = GWT.create(CustomerPanel.class);
customerPanel.setClientSession(clientSession);
container.add(customerPanel);

Because acris-security (and also UiBinder in this case) uses deferred binding we have to use GWT.create call to correctly instantiate the panel. You might notice the middle line setting a client session. The client session (usually single for the application or part of the application’s context) actually holds the inforamtion about user and its session/conversation. There (apart of other possible values) is stored the user object with authorities and a session ID. After successful log-in the session is filled with the information and by injecting the session to the panel it will be able to compose correct representation based on available authorities.

Every panel willing to be secured must implement ISecuredObject interface. If you are extending GWT’s Composite it might be handy to use SecuredComposite and don’t bother with implementing required methods.

Log me in please...

Alright, we have secured the panel but now we need to log a user in somehow. To separate client and server side and to allow also different implementations there is IUserService interface available negotiating user’s credentials with an authentication and authorization service. This can be for example Spring Security authentication manager with a chain of providers (LDAP, CAS, database,...).

There is a default user service integrated with Spring Service called... UserService. Of course you can use your own/already existing implementation but it has to extend IUserService interface.

final IUserServiceAsync userService = GWT.create(IUserService.class);
SessionServiceDefTarget endpoint = (SessionServiceDefTarget) userService;
endpoint.setServiceEntryPoint("showcase-service/userService");
endpoint.setSession(clientSession);

User service is standard GWT RPC service. Calling login method and filling client session will prepare everything relevant for further securing the panel:

userService.login(new UserPasswordLoginToken(username.getText(), password.getText(), null),
new AsyncCallback<ClientSession>() {
@Override
public void onSuccess(ClientSession result) {
// copy the information about user and session
// so secured components can rely on it
clientSession.setSessionId(result.getSessionId());
clientSession.setUser(result.getUser());
loggedInCmd.execute();
}

@Override
public void onFailure(Throwable caught) {
GWT.log("Login failure", caught);
}
});

The actual placing of the panel is deferred to the loggedInCmd.execute(); call where a new panel is instantiated and put to the parent container.

Conclusion

This was a simple example showing how you can quickly enable your application with security using AcrIS. Its focus is on the integration of client and server and to easily control security on the client sidein a variety of ways. What it does not do is to focus on the server side security as such because that is solved by frameworks of your choice (like Spring Security does). It only bridges your server side choice with the GWT client.

We just scratched the surface about what acris-security is capable of and next time we will take a look at runtime security, how to reapply security constraints after re-logging as different user and maybe more.

Published at DZone with permission of its author, Ladislav Gažo.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)