


The authorization support provided by Wicket is built around the concept of authorization strategy which is represented by interface _IAuthorizationStrategy_ (in package _org.apache.wicket.authorization_):

[source,java]
----
public interface IAuthorizationStrategy
{
  //interface methods 
 <T extends IRequestableComponent> boolean isInstantiationAuthorized(Class<T> componentClass);
 boolean isActionAuthorized(Component component, Action action);
 
 //default authorization strategy that allows everything
 public static final IAuthorizationStrategy ALLOW_ALL = new IAuthorizationStrategy()
 {
  @Override
  public <T extends IRequestableComponent> boolean isInstantiationAuthorized(final Class<T> c)
  {
    return true;
  }
  @Override
  public boolean isActionAuthorized(Component c, Action action)
  {
    return true;
  }
 };
}
----

This interface defines two methods:

* isInstantiationAuthorized checks if user is allowed to instantiate a given component.
* isActionAuthorized checks if user is authorized to perform a given action on a component's instance. The standard actions checked by this method are defined into class Action and are Action.ENABLE and Action.RENDER.

Inside _IAuthorizationStrategy_ we can also find a default implementation of the interface (called ALLOW_ALL) that allows everyone to instantiate every component and perform every possible action on it. This is the default strategy adopted by class _Application_.

To change the authorization strategy in use we must register the desired implementation into security settings (class _SecuritySettings_) during initialization phase with method setAuthorization Strategy:

[source,java]
----
  //Application class code... 
  @Override
  public void init()
  {
    super.init();
    getSecuritySettings().
	setAuthorizationStrategy(myAuthorizationStrategy);
  }	
//...
----

If we want to combine the action of two or more authorization strategies we can chain them with strategy _CompoundAuthorizationStrategy_ which implements composite pattern for authorization strategies.

Most of the times we won't need to implement an _IAuthorizationStrategy_ from scratch as Wicket already comes with a set of built-in strategies. In the next paragraphs we will see some of these strategies that can be used to implement an effective and flexible security policy.

=== SimplePageAuthorizationStrategy

Abstract class SimplePageAuthorizationStrategy (in package _org.apache.wicket.authorization.strategies.page_) is a strategy that checks user authorizations calling abstract method _isAuthorized_ only for those pages that are subclasses of a given supertype. If _isAuthorized_ returns false, the user is redirected to the sign in page specified as second constructor parameter:

[source,java]
----
SimplePageAuthorizationStrategy authorizationStrategy = new SimplePageAuthorizationStrategy( 
                                                  PageClassToCheck.class, SignInPage.class)
{
  protected boolean isAuthorized()
  {		                
    //Authentication code...
  }
};
----

By default _SimplePageAuthorizationStrategy_ checks for permissions only on pages. If we want to change this behavior and check also other kinds of components, we must override method _isActionAuthorized_ and implement our custom logic inside it.

=== Role-based strategies

At the end of <<security.adoc#_authentication,paragraph 22.1>> we have introduced AbstractAuthenticatedWebSession's method getRoles which is provided to support role-based authorization returning the set of roles granted to the current user.

In Wicket roles are simple strings like “BASIC_USER” or “ADMIN” (they don't need to be capitalized) and they are handled with class _org.apache.wicket.authroles.authorization.strategies.role.Roles_. This class extends standard HashSet collection adding some functionalities to check whether the set contains one or more roles. Class _Roles_ already defines roles Roles.USER and Roles.ADMIN.

The session class in the following example returns a custom “SIGNED_IN” role for every authenticated user and it adds an Roles.ADMIN role if username is equal to superuser:

[source,java]
----
class BasicAuthenticationRolesSession extends AuthenticatedWebSession {
	private String userName;
	
	public BasicAuthenticationRolesSession(Request request) {
		super(request);		
	}

	@Override
	public boolean authenticate(String username, String password) {
		boolean authResult= false;
		
		authResult = //some authentication logic...
		
		if(authResult)
			userName = username;
		
		return authResult;
	}

	@Override
	public Roles getRoles() {
		Roles resultRoles = new Roles();
		
		if(isSignedIn())
			resultRoles.add("SIGNED_IN");
		
		if(userName.equals("superuser"))
			resultRoles.add(Roles.ADMIN);
		
		return resultRoles;
	}
}
----

Roles can be adopted to apply security restrictions on our pages and components. This can be done  using one of the two built-in authorization strategies that extend super class _AbstractRoleAuthorizationStrategyWicket_: _MetaDataRoleAuthorizationStrategy_ and _AnnotationsRoleAuthorizationStrategy_

The difference between these two strategies is that _MetaDataRoleAuthorizationStrategy_ handles role-based authorizations with Wicket metadata while _AnnotationsRoleAuthorizationStrategy_ uses Java annotations.

NOTE: Application class _AuthenticatedWebApplication_ already sets _MetaDataRoleAuthorizationStrategy_ and _AnnotationsRoleAuthorizationStrategy_ as its own authorization strategies (it uses a compound strategy as we will see in <<security.adoc#_authorizations,paragraph 22.2>>).

The code that we will see in the next examples is for illustrative purpose only. If our application class inherits from _AuthenticatedWebApplication_ we won't need to configure anything to use these two strategies.

==== Using roles with metadata

Strategy _MetaDataRoleAuthorizationStrategy_ uses application and components metadata to implement role-based authorizations. The class defines a set of static methods authorize that can be used to specify which roles are allowed to instantiate a component and which roles can perform a given action on a component.

The following code snippet reports both application and session classes from project _MetaDataRolesStrategyExample_ and illustrates how to use _MetaDataRoleAuthorizationStrategy_ to allow access to a given page (AdminOnlyPage) only to ADMIN role:

*Application class:*

[source,java]
----
public class WicketApplication extends AuthenticatedWebApplication{    		
   @Override
   public Class<? extends WebPage> getHomePage(){
      return HomePage.class;
   }
   
   @Override
   protected Class<? extends AbstractAuthenticatedWebSession> getWebSessionClass() {
      return BasicAuthenticationSession.class;
   }

   @Override
   protected Class<? extends WebPage> getSignInPageClass() {
      return SignInPage.class;
   }
   
   @Override
   public void init(){   
      getSecuritySettings().setAuthorizationStrategy(new MetaDataRoleAuthorizationStrategy(this));
      MetaDataRoleAuthorizationStrategy.authorize(AdminOnlyPage.class, Roles.ADMIN);
   }
}
----

*Session class:*

[source,java]
----
public class BasicAuthenticationSession extends AuthenticatedWebSession {

   private String username;

   public BasicAuthenticationSession(Request request) {
      super(request);      
   }

   @Override
   public boolean authenticate(String username, String password) {
      //user is authenticated if username and password are equal
     boolean authResult = username.equals(password);
      
      if(authResult)
         this.username = username;
      
      return authResult;
   }

   public Roles getRoles() {
      Roles resultRoles = new Roles();
      //if user is signed in add the relative role
      if(isSignedIn())
         resultRoles.add("SIGNED_IN");
      //if username is equal to 'superuser' add the ADMIN role
      if(username!= null && username.equals("superuser"))
         resultRoles.add(Roles.ADMIN);
      
      return resultRoles;
   }
   
   @Override
   public void signOut() {
      super.signOut();
      username = null;
   }
}
----

The code that instantiates _MetaDataRoleAuthorizationStrategy_ and set it as application's strategy is inside application class method init. 

Any subclass of _AbstractRoleAuthorizationStrategyWicket_ needs an implementation of interface _IRoleCheckingStrategy_ to be instantiated. For this purpose in the code above we used the application class itself because its base class _AuthenticatedWebApplication_ already implements interface _IRoleCheckingStrategy_. By default _AuthenticatedWebApplication_ checks for authorizations using the roles returned by the current _AbstractAuthenticatedWebSession_. As final step inside init we grant the access to page _AdminOnlyPage_ to ADMIN role calling method authorize.

The code from session class has three interesting methods. The first is authenticate which considers as valid credentials every pair of username and password having the same value. The second notable method is getRoles which returns role SIGNED_IN if user is authenticated and it adds role ADMIN if username is equal to superuser. Finally, we have method signOut which has been overridden in order to clean the username field used internally to generate roles.

Now if we run the project and we try to access to _AdminOnlyPage_ from the home page without having the ADMIN role, we will be redirected to the default access-denied page used by Wicket:

image::../img/authorization-access-denied.png[]

The access-denied page can be customized using method _setAccessDeniedPage(Class<? extends Page>)_ of setting class _ApplicationSettings_:

[source,java]
----
   //Application class code...
   @Override
   public void init(){   
      getApplicationSettings().setAccessDeniedPage(
			MyCustomAccessDeniedPage.class); 
   }
----

Just like custom “Page expired” page (see <<versioningCaching.adoc#_stateful_pages,chapter 8.2.5>>), also custom “Access denied” page must be bookmarkable.

==== Using roles with annotations

Strategy _AnnotationsRoleAuthorizationStrategy_ relies on two built-in annotations to handle role-based authorizations. These annotations are _AuthorizeInstantiation_ and _AuthorizeAction_. As their names suggest the first annotation specifies which roles are allowed to instantiate the annotated component while the second must be used to indicate which roles are allowed to perform a specific action on the annotated component.

In the following example we use annotations to make a page accessible only to signed-in users and to enable it only if user has the ADMIN role:

[source,java]
----
@AuthorizeInstantiation("SIGNED_IN")
@AuthorizeAction(action = "ENABLE", roles = {"ADMIN"})
public class MyPage extends WebPage {
   //Page class code...
}
----

Remember that when a component is not enabled, user can render it but he can neither click on its links nor interact with its forms.

Example project _AnnotationsRolesStrategyExample_ is a revisited version of _MetaDataRolesStrategyExample_ where we use _AnnotationsRoleAuthorizationStrategy_ as authorization strategy. To ensure that page _AdminOnlyPage_ is accessible only to ADMIN role we have used the following annotation:

[source,java]
----
@AuthorizeInstantiation("ADMIN")
public class AdminOnlyPage extends WebPage {
    //Page class code...
}
----

=== Catching an unauthorized component instantiation

Interface IUnauthorizedComponentInstantiationListener (in package _org.apache.wicket.authorization_) is provided to give the chance to handle the case in which a user tries to instantiate a component without having the permissions to do it. The method defined inside this interface is _onUnauthorizedInstantiation(Component)_ and it is executed whenever a user attempts to execute an unauthorized instantiation.

This listener must be registered into application's security settings with method _setUnauthorizedComponentInstantiationListener_ defined by setting class _SecuritySettings_. In the following code snippet we register a listener that redirect user to a warning page if he tries to do a not-allowed instantiation:

[source,java]
----
public class WicketApplication extends AuthenticatedWebApplication{   
     //Application code...
     @Override
     public void init(){    
        getSecuritySettings().setUnauthorizedComponentInstantiationListener(
			new IUnauthorizedComponentInstantiationListener() {
			
	    @Override
	    public void onUnauthorizedInstantiation(Component component) {
	        component.setResponsePage(AuthWarningPage.class);
	    }
        });
     }
}
----

In addition to interface _IRoleCheckingStrategy_, class _AuthenticatedWebApplication_ implements also _IUnauthorizedComponentInstantiationListener_ and registers itself as listener for unauthorized instantiations.

By default _AuthenticatedWebApplication_ redirects users to sign-in page if they are not signed-in and they try to instantiate a restricted component. Otherwise, if users are already signed in but they are not allowed to instantiate a given component, an _UnauthorizedInstantiationException_ will be thrown.

=== Strategy RoleAuthorizationStrategy

Class _RoleAuthorizationStrategy_ is a compound strategy that combines both _MetaDataRoleAuthorizationStrategy_ and _AnnotationsRoleAuthorizationStrategy_.

This is the strategy used internally by _AuthenticatedWebApplication_.

