Saturday, October 4, 2014

Android

For the last three months I've had a chance to play around with Android. As usual, I'd like to share what I've learnt so far. This link contains an Android project and its supporting projects. I also include a pdf as supprting documentation. I hope this is useful for anybody who wants to learn Android.


Sunday, June 15, 2014

JAAS Revisited (Using Database and Tomcat)

I have wrote a blog post about JAAS application using database on this post. Now we will expand it by writing those knowledge for a web application. First of all we will see our database structure. Since we will use the same database structure as previous post, there is no need to repeat it here. Also, we will use the same data but the application name and login module in table APP_CONFIGURATION. Below is the script to insert data to table APP_CONFIGURATION.


As we can see, instead of using DBLoginModule as previous post, we have a new login module class, TomcatLoginModule. Below is the code of our TomcatLoginModule.


As shown above, TomcatLoginModule extends DBLoginModule and overrides its commit() and logout() methods. This is done since we will introduce a new principal, RolePrincipal. We will visit the RolePrincipal class later and explain why we need this. In the code above, we add "admin" RolePrincipal to a user that has SysAdminPrincipal principal or "user" RolePrincipal to a user that has UserPrincipal principal. In the logout() method, we simply remove the RolePrincipal that was assigned.

Next we will visit the web.xml file. In this file, we define a servlet named StartupServlet to initialize JAAS configuration and policy as shown below:


Since its load-on-startup value is positive, which is set to zero, it is loaded by servlet container when the application is deployed. The servlet container executes servlet's init() method when it is deployed just once for the servlet lifetime; and since there is only one instance for each servlet on the container, it is save to put JAAS configuration initialization in the init() method. Below is our code to configure JAAS on StartupServlet.


In the code above, we set JAAS configuration, populate permissions, set JAAS policy, and set the security manager. We already see the JAAS configuration and policy in previous post so we won't repeat them again here. Next we will see how to populate permissions.


In the code above we have a static variable permissionMap which is used to save mapping of principal class and its permissions. It is populated from table PERMISSION and PRINCIPAL_PERMISSION. The static permissionMap is then used to get permissions based on principal class name in DBPolicy as shown below.



Let's go back to the web.xml to see how security is implemented to protect pages. In this simple web application we have two roles, admin role and user role. Each role has access to its own pages. Below is the folder structure where those pages are placed in Eclipse project.


All admin pages are put inside admins folder while all ordinary user pages are put inside customers folder. Other JSP files are self-descriptive. Below is the web.xml file that contains security configuration.


First, we have login configuration. We configure it to use html form based configuration and JAAS realm which we will configure later on Tomcat. We also set the login and login error page.


Next we set up the security constraint and security role. We have two roles, admin role and user role. All pages under admins folder can only be accessed by admin role while all pages under customers folder can only be accessed by user role.


We also set the welcome page to be index.jsp for web context, admins, and customers. If a user accesses a page that is not intended for him/her, for example if a user that has user role tries to access admin page, security error code 403 access denied is thrown by security manager. We will forward the user to the access-denied.jsp.



As we can see from the flow above, index.jsp is our entry point and from there we can go to admin page, user page, or logout page. If a user clicks the link to go to admin page, the security manager will check if he/she has already logged in. If yes, it will check if he/she has admin role. If he/she doesn't have admin role, he/she will be redirected to access-denied.jsp. If he/she has not logged in, he/she will be redirected to login.jsp. If the login process fails, he/she will be redirected to login-error.jsp. If he/she has logged in as admin, he/she will be redirected to admin page. The same logic applies to user role as well. Below are the jsp files involved in these scenario.








The login.jsp is the user interface we need to gather credentials. We have a form with action value j_security_check. We also have two textfields to input username and password. The textfields must be named j_username and j_password. Those names are mandatory if we want to take advantage of JAAS.

As mentioned before, we configure JAAS to use html form and JAAS realm. We have seen the html form on login.jsp, so now it's time to see the JAAS realm configuration on Tomcat as explained below.


Above is the default Tomcat configuration on its server.xml which is located in its conf folder.


The Tomcat configuration above is added automatically when we deploy our web app on Tomcat from Eclipse. The docBase and path properties point to our project name on Eclipse which is usually also our war file name and context name. The source property is internally used by Eclipse.


Then we need to add JAAS realm as shown above. The className property refers to internal Tomcat JAAS realm implementation. The appName refers to our package/application name in database. The roleClassNames is a class that is used by JAAS realm to decide what role that a user is assigned as configured on security constraint part of web.xml. We will see the RolePrincipal class later. useContextClassLoader is used to tell Tomcat that the RolePrincipal class should be loaded from context classpath, that is from /JAASWeb.

Below is the RolePrincipal class. It has the same structure as other principal classes. The name variable is set by TomcatLoginModule.commit() method and it has value either admin or user.


Once we have done with authentication, we can start authorization process. Unfortunately, we can't get the logging in Subject from authentication process that was done by JAAS realm before. We can overcome this by repeating the authentication process in a servlet Filter. Let's see how this is done below:


First, we declare two filters in the web.xml, Authentication-Filter and Authorization-Filter. The first is used to repeat the authentication process until we get the Subject. The second is used to simulate authorization process by checking the Subject privilege against an input file. We will visit them one by one.


For Authentication-Filter we create AuthenticationFilter class and pass "ted" as its app-name parameter. Our AuthenticationFilter class implements servlet's Filter interface. In the init() method we get the app-name parameter from web.xml. In the doFilter() method we get username and query his/her password from database. If the authentication process success, we put the Subject in to a session attribute "loggedInSubject".


For Authorization-Filter we create AuthorizationFilter class. In the code above we test the Subject against an input file.

Below is the folder structure of our project:


Running this project on Tomcat produces the following results:








Thursday, June 5, 2014

JAAS Revisited (Using Database)

On this post, we have tried simple JAAS application. It uses declarative configuration and permission files. Instead of writing those informations on text files, now we will take advantage of database. JAAS provides us classes we can extend to gather those informations. For this simple application, we will use PostgreSQL database. Below is SQL script to create tables and insert default data.



APP_CONFIGURATION holds configuration data that we used to write on configuration file. Column APP_NAME is used to save package/application name. LOGIN_MODULE_CLASS is used to save login module class name. CONTROL_FLAG is used to save login module control flag (REQUIRED, OPTIONAL, SUFFICIENT, REQUISITE).



Table PERMISSION has information about permissions. It holds permission class name, permission name, and its actions.



PRINCIPAL_PERMISSION maps principals and permissions. In this table we save the principal class and its corresponding permission classes.



PRINCIPAL_DB_USER is used to save mapping between users and principals. In this class we save the username and its corresponding principal classes.



DB_USER holds information about user. In this table we are only interested in saving username and password.

Next we will see how configuration is implemented using Configuration class and table APP_CONFIGURATION. To get configuration information from database, we need to create a class DBConfiguration that extends JAAS Configuration class as shown below. In this class, we override method getAppConfigurationEntry where we can query the table APP_CONFIGURATION and construct an array of AppConfigurationEntry. Below is the code on how to get a list of configuration information from the table.


In the method getAppConfigurationEntry above we query the table, iterate the result set, and for each configuration we create an object of AppConfigurationEntry. As the result, we put all the AppConfigurationEntry objects inside a list and return it. So how to load this configuration? This is done by this line of code:


In the code above, we make the DBConfiguration as singleton and inside its init method we set the login configuration to be our DBConfiguration singleton object. The last method to visit in DBConfiguration class is shown below:


Method resolveControlFlag above is called within our getAppConfigurationEntry before.

Next we will see how permission is implemented using Policy class and PERMISSION & PRINCIPAL_PERMISSION tables. We need to create our own DBPolicy class that extends JAAS Policy class to get permission information from those two tables. Below is the code to do this:



In the codes above we create DBPolicy class that extends JAAS Policy class. We override two overloaded getPermissions methods there. Method getPermissions(CodeSource) returns a list of permission for running some codes. This is equivalent to giving permissions to all as shown in policy file below:


In method getPermissions(ProtectionDomain), we give permissions to a principal if one exists. This is equivalent to giving permission as shown in policy file below:


Below is the code that fetch permission data from PERMISSION table by its principal. For each result set, we create a Permission object and add it to a list. Then we return the list of Permission.


Next is the code in the main method where we initialize configuration, policy, and security manager.


First, we call DBConfiguration.init() that will set JAAS configuration. Then we create DBPolicy instance and set JAAS policy to be our DBPolicy object. After that we try to test user's access to a file, input.txt. We will see this later.









In our APP_CONFIGURATION table, we insert DBLoginModule as our login module class. Next we will see this class. Since it implements LoginModule, we need to implement its methods.

  1. initialize(): this is the first method called when we authenticate a user. We can initialize our class variables here. initialize() has 4 arguments on its method header and three of them are useful for us. First is Subject, it is the Subject that is being logged in. Then CallbackHandler, it is an object that is responsible for gathering credentials (username & password). Last is a Map of options that we don't currently use. Our DBLoginModule's initialize() method above initialized our private variables Subject and CallbackHandler for future usage.
  2. login(): this method is used to gather and validate username and password. If the validation succeeds, it returns true. Otherwise we should throw LoginException. In the login() method, we declared two callback objects, NameCallback and PasswordCallback. They are used to gather username and password credentials through callbackHandler.handle(callbacks) method. After getting the credentials, we simply validated them by comparing input password and user's password from database. If the validation succeed, we returns true, otherwise we throw a FailedLoginException. Note that we didn't return false if the validation fails. If it returns true, then commit() method is called; but if it throws LoginException, then abort() method is called instead. Returning false (Boolean.FALSE) will not make the abort() method called.
  3. commit(): this method is called if login() method returns true. We can put principles to a Subject here. In our commit() method, we added principles to Subject since he/she has successfully logged in. We get the principals from table PRINCIPAL_DB_USER by passing the username.
  4. abort(): this method is called if login() method throws LoginException. We can remove all credentials (username, password) here. In this method we cleaned up all credentials.
  5. logout(): this method is called if we logout from JAAS. When a user logout, we clean up all credentials and remove all principals that were assigned when he/she logged in.
Next we will see the principal classes. In table PRINCIPAL_DB_USER and PRINCIPAL_PERMISSION we insert two principals, SysAdminPrincipal and UserPrincipal.



As we can see, all principals implements Principal interface. It has one method that returns its name. It is the name that is set on commit() method of DBLoginModule class. The name is set to be username since we get the principals by username. Once we get the principal, we can query the permissions by principal class name which is done by our DBPolicy class before.

Next we will see callback handler class, SimpleCallbackHandler.


Our SimpleCallbackHandler above implements CallbackHandler. We need to implement handle() method. In the handle() method we iterate callbacks array that was sent by DBLoginModule.login() method as we did before. During iteration, we populate NameCallback with username and PasswordCallback with password. Now one thing missing is how we get the username and password credentials to be sent to this DBLoginModule. This is where LoginContext plays its role which we will see soon.

In main method, we have set configuration and policy. Now we can authenticate and check user's authorization. Below is complete code of main class.



To authenticate a user, first we create SimpleCallbackHandler object and pass the username and password. Then we create LoginContext object by passing package/application name from table APP_CONFIGURATION and the SimpleCallbackHandler object. LoginContext.login() is used to log the user in by passing control to the DBLoginModule. If the authentication succeeds, we can obtain the Subject. If fails, LoginException is thrown.

Now that the user is authenticated, we can start checking if a user is authorized to do some action. We have granted permissions for users in database before. These permissions will be used to check user authorization. Subject.doAsPrivileged is the method we need. In the code above we test if a user is allowed to read file input.txt. If he/she is allowed, it simply returns. Otherwise, it throws SecurityException.

Below is the result from running the code:


From the result we can see that the Subject "user" and "sysadmin" authentication succeeds. The "user" is not allowed to access the input.txt file since we didn't grant any permission to it while "sysadmin" can.

Below is the project structure:


 

©2009 Stay the Same | by TNB