JAAS Module

JAAS - Important Concepts

  • Subject

    The agent that is going to be authenticated.

  • Principal

    Represents an identity of the agent. They can be thought of as attributes. One agents may have many principals. Permissions are given to principals.

  • Credential

    Security-related attributes, which may be represented by any class, and are either private or public.

  • LoginContext

    Provides the basic methods used to authenticate subjects and a way to develop an application independent of the underlying authentication technology.

  • LoginModule

    Implements an authentication technology.

  • CallbackHandler

    A LoginModule uses the CallbackHandler both to gather input from users (like username and password) and to supply information to users.

  • Configuration file

    Contains which LoginModules and whether they are "required, "requisite", "sufficient" or optional. Options are also specified.

  • Policy

    Reads the permissions from the policy file.

  • Permission

    A permission has a type, a name and possibly actions and are given to code or principals in the policy file.

  • SecurityManager

    Provides the permission checks. Note that you own Permissions are not checked automatically, but you have to add this in your application:

    	SecurityManager sm = System.getSecurityManager()
    	if(sm!=0){
       		sm.checkPermission(new MyPermission(name));
    	}

  • Policy file

    Here you store the permissions. It does not have to be a file, you may want to store the permissions in a database.

Classes and Packages

  • no.feide.mellon.jaas.loginmodules

    The only LoginModule is the MoriaLoginModule, which uses no.feide.mellon.v2_1.Moria for authentication.

  • no.feide.mellon.jaas.principals

    The main Principal implementation is the MoriaPrincipal. To enable use of wildcards two other principal-types is implemented as well, EntitlementPrincipal and ScopedAffiliationPrincipal.

  • no.feide.mellon.jaas.callbackhandlers

    It contains two callbackHandlers, CommandlineCallbackHandler that prompts the user for username and password and PassiveCallbackHandler.

  • no.feide.mellon.jaas.loginutility

    The Login class and the MoriaAction class will hide the use of JAAS completely from the application.

  • no.feide.mellon.jaas.application

    It contains one class Demo, a small sample application.

How to run it

This is how you run the code:

	java	-Djava.security.auth.login.config==jaas.config \
		-Djava.security.auth.manager \
		-Djava.security.policy==jaas.policy \
		Login \
		Demo \
		[args]

This means you run the Login class and that the application that is going to use JAAS, Demo, is the first argument. The next arguments are arguments for the main method in Demo.

Double "=", "==", means that this is the only configuration- and policy-file that is to be considered. Note that you will have to write or modify jaas.config and jaas.policy. Examples are provided below.

jaas.config

	no.feide.mellon.jaas.application.Demo{
		no.feide.mellon.jaas.loginmodules.MoriaLoginModule required 
		debug=true 
		endpoint="http://localhost:8080/moria/v2_1/Authentication" 
		service_username="demo_service" 
		service_password="demo_service";
	};

jaas.policy

	//This is only an example. It cannot be used without modifications.

	//"standard" properties that can be read by anyone
	grant { 
		permission java.util.PropertyPermission "java.version", "read";
		permission java.util.PropertyPermission "java.vendor", "read";
		permission java.util.PropertyPermission "java.vendor.url", "read";
		permission java.util.PropertyPermission "java.class.version", "read";
		permission java.util.PropertyPermission "os.name", "read";
		permission java.util.PropertyPermission "os.version", "read";
		permission java.util.PropertyPermission "os.arch", "read";
		permission java.util.PropertyPermission "file.separator", "read";
		permission java.util.PropertyPermission "path.separator", "read";
		permission java.util.PropertyPermission "line.separator", "read";

		permission java.util.PropertyPermission "java.specification.version", "read";
		permission java.util.PropertyPermission "java.specification.vendor", "read";
		permission java.util.PropertyPermission "java.specification.name", "read";

		permission java.util.PropertyPermission "java.vm.specification.version", "read";
		permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
		permission java.util.PropertyPermission "java.vm.specification.name", "read";
		permission java.util.PropertyPermission "java.vm.version", "read";
		permission java.util.PropertyPermission "java.vm.vendor", "read";
		permission java.util.PropertyPermission "java.vm.name", "read";
	};

	grant codebase "file:D:/Feide/-"{
		permission java.security.AllPermission;
	};

	grant codebase "file:D:/JavaLibraries/-"{
		permission java.security.AllPermission;
	};

	grant codebase "file:D:/win/eclipse/workspace/JAAS/-"{
		permission javax.security.auth.AuthPermission "createLoginContext";
		permission javax.security.auth.AuthPermission "modifyPrincipals";
		permission javax.security.auth.AuthPermission "modifyPublicCredentials";
		permission javax.security.auth.AuthPermission "modifyPrivateCredentials";
		permission javax.security.auth.AuthPermission "doAsPrivileged";
	
		permission java.util.PropertyPermission "axis.xml.reuseParsers", "read";
		permission java.util.PropertyPermission "axis.attachments.implementation", "read";
		permission java.util.PropertyPermission "java.protocol.handler.pkgs", "read, write";
		permission java.util.PropertyPermission "axis.byteBuffer.cacheIncrement", "read";
		permission java.util.PropertyPermission "axis.byteBuffer.residentMaxSize", "read";
		permission java.util.PropertyPermission "axis.byteBuffer.workBufferSize", "read";
		permission java.util.PropertyPermission "axis.byteBuffer.backing", "read";
		permission java.util.PropertyPermission "axis.doAutoTypes", "read";
		permission java.util.PropertyPermission "http.nonProxyHosts", "read";
		permission java.util.PropertyPermission "http.proxyUser", "read";
		permission java.util.PropertyPermission "http.proxyHost", "read";
	
		permission java.net.SocketPermission "localhost", "resolve";
		permission java.net.SocketPermission "127.0.0.1:8080", "connect,resolve";
	
		permission java.io.FilePermission "D:\\JavaLibraries\\axis-bin-1_2_1\\axis-1_2_1\\lib\\-", "read";
		permission java.io.FilePermission "D:\\win\\eclipse\\workspace\\Moria\\-", "read";
		permission java.io.FilePermission "D:\\win\\eclipse\\workspace\\JAAS\\-", "read,write";
	};

	grant Principal jaas.principals.MoriaPrincipal "eduPersonEntitlement:urn:mace:feide.no:gullgraverskolen.no:forsteklondike"{
		permission java.util.PropertyPermission "user.home", "read";
	};

	grant Principal jaas.principals.EntitlementPrincipal "*:*:*:gullgraverskolen.no:*"{
		permission java.util.PropertyPermission "java.home", "read";
	}; 

The configuration file jaas.config and the policy file jaas.policy can be specified in the java.policy and java.security files located in the directory lib/security/ in the java runtime folder. The security Manager can be constructed in the Login class (before the LoginContext is created). This is done like this:

	System.setSecurityManager(new SecurityManager())

How it works - Authentication

The no.feide.mellon.jaas.loginutility.Login class initiates a LoginContext and calls the LoginContexts login method. The name in the loginconfiguration, jaas.config, is the same as the name of the application that is going to use this JAAS-module and the CallbakHandler used is the no.feide.mellon.jaas.calbackhandlers.CommandlineCallbackHandler.

You get three login attempts (specified in the Login class).

The only LoginModule used is no.feid.mellon.jaas.loginmodules.MoriaLoginModule, and it is required as specified in jaas.config. When the LoginContexts login method is called the LoginContext initiates the MoriaLoginModule and calls its login method.

The MoriaLoginModule uses the given CallbackHandler to ask for username and password. The login method in MoriaLoginModule calls the MoriaLoginModules validate method which constructs a no.feide.mellon.v2_1.Moria object and calls its directNonInteractiveAuthentication method. The username and password is checked and the attributes specified in the MoriaLoginModules static variable ATTRIBUTE_NAMES are returned. For each of the Attributes returned a new no.feide.mellon.jaas.principals.MoriaPrincipal is constructed. The commit method in MoriaLoginModule saves this principals in the Subject object returned to the LoginContext if the login and commit method of the MoriaLoginModule both return true.

The Login class retrieves the Subject from the LoginContext and tries to run the no.feide.mellon.jaas.loginutility.MoriaAction as this subject. The MoriaAction starts the application, Demo. This means that the application is run as the authenticated subject.

How it works - Authorization

When run with the default SecurityManager, all the standard permissions will be checked. The application is run as the subject, so what the application can do is restricted by the subject's permissions. The permission are granted to principals and/or code and specified in jaas.policy. You can read more about policy files here: "Default Policy Implementation and Policy File Syntax" I have used the default Policy implementation, com.sun.security.auth.PolicyFile. This means I have used the standard described in the link above to write the jaas.policy file.

During login attributes are stored as MoriaPrincipals in the authenticated subject. The string representation of a MoriaPrincipal is "attributeName:attributeValue". This is used in the policy file. MoriaPrincipals cannot contain wildcards. To enable use of wildcards in the policy file for specific attributes, new principal types that extend MoriaPrincipal and implements the com.sun.security.auth.PrincipalComparator are implemented. These principals are EntitlementPrincipal and ScopedAffiliationPrincipal and they are only used in the policy file.

You can use EntitlementPrincipal when you want to use wildcards in the attribute value of eduPersonEntitlement. The eduPersonEntitlement values have this format: a:b:c:d, where the number of ":" may vary. You can replace any of the parts a,b,c etc. with a wildcard. The parts a,b,c etc. cannot contain any ":". For to values to mach, the number of ":" must be the same.

You can use ScopedAffiliationPrincipal if you want to use wildcards in the attribute value of eduPersonScopedAffiliation. The eduPersonScopedAffiliation values have this format: "affiliation@securityDomain". The affiliation can be replaced by a wildcard, but the security domain cannot.

How to use it

To use this module for your own application, you might have to change the Login class. When the LoginContext is created you can choose another CallbackHandler. And you can change/remove the part where you get three login attempts.

You have to change which FEIDE attributes you want to retrieve when you authenticate against Moria. They are specified in the MoriaLoginModule, but you might want to put in in a configuration file.

You might also need another CallbackHandler and additional special Principals.

If you do not want to follow the policy file standard, but want to use xml or something else, you can make your own. Then you will have to implement a new Policy class extending the com.sun.security.auth.PolicyFile class or implementing the javax.security.auth.Policy interface.

If you need any custom permissions, you have to implement them exteding java.security.BasicPermission or java.security.Permission.

The jaas.config file and jaas.policy need to be written.