Access Keys:
Skip to content (Access Key - 0)

Knowledgebase


Part Four: Authentication


Table of Contents

Introduction


In order to access the Grid, every user must have an account and login to the Grid. Typically, users perform these steps by installing caGrid and using the GAARDS (security) user interface application. In this article, we will create a Grid Application that will synchronize with the Grid Trust Fabric and provide Grid registration and login capabilities. This solution allows your users to interact with the Grid without having to install the caGrid software separately on their machine.

Both account registration and authentication are supported by the Dorian grid service. In order for a user to register (create an account) with Dorian, first a registration form is submitted to Dorian. When Dorian receives the registration, the account is initially marked "inactive". To change the account status to "active", the registration must be approved. Currently, both the Community Training Grid Dorian and NCI Production Grid Dorian are configured to automatically approve accounts.

Please keep in mind that the auto-approve option may change in the future. Should the option change (i.e., to disable registration auto-approval), your Grid application that support account registration must inform the user that there will be a delay in logging in to the Grid while their registration is processed. You will need to contact the appropriate parties to request more information on the account registration process in order to provide your users with information regarding a timeline for account approval.

The caGrid distribution contains tools to perform the steps that we are implementing. You may find it useful to look at the documentation for tools that perform the functionality that we will implement in our client application. You can find more information about using the GAARDS Security UI at the following link: Users Guide.

Desired Application Functionality


Synchronize with the Grid Trust Fabric

Every computer that interacts with the Grid must synchronize with the grid trust fabric. After synchronization, your computer will have a list of trusted certificate authorities that are included in the target Grid. These certificate authorities are used to authenticate the credentials of hosts on the grid. An Ant build target is used to perform synchronization.

  1. Open a command prompt and change directory to your caGrid directory.
  2. Run the syncWithTrustFabric command.
> cd $CAGRID_HOME
> ant syncWithTrustFabric

Register a Grid Account

In order to register an account using the caGrid tools you will need to use the GAARDS-UI tool.

  1. Open GAARDS
    ant security
    
  2. In the UI menus, click Account Management->Local Accounts->Registration
  3. Complete the Registration form and click Apply.
  4. Your registration is automatically approved.

Logon to the Grid

Logging into the Grid is also supported in the GAARDS-UI tool.

  1. Open GAARDS
    ant security
    
  2. Click the Login button on the menu bar.
  3. In the resulting form you will have the option of selecting the default organization or other identity providers. This allows users from organizations their non-caGrid username and password to authenticate with caGrid.
  4. Provide your username and password, then click Login
  5. Upon success, you will be presented with a window presenting your grid identity.

Creating Client Functionality


Now, we will begin to implement the functionality that we just invoked using Ant tasks and the GAARDS UI.

Step 1: Synchronize with the Grid Trust Fabric

caGrid host computers, or nodes, operate upon an established trust relationship with each other via host credentials that have been signed by trusted credential authorities. This relationship, or trust fabric, is implemented through the use of Globus host certificates and the Grid Trust Service, which maintains a list of trusted certificate authorities for the grid.

Grid Nodes must periodically connect to the GTS host to obtain the GTS certificate authority credentials. These credentials will be used to establish trust of user accessing a grid service.

For applications, a programmatic approach to synchronize with the Trust Fabric is used.

The following JARs are used in a Grid application that synchronizes with the trust fabric:

Jar dependency Purpose
caGrid-core-1.3.jar Core functionality provided in the gov.nih.nci.cagrid.common package, such as exceptions, serializers and deserializers.
cog-jglobus-syncgts-patched-4.0.3.jar Core Globus functionality, specifically the Grid Security Infrastrufrure.
caGrid-ServiceSecurityProvider-client-1.3.jar
caGrid-ServiceSecurityProvider-common-1.3.jar
caGrid-ServiceSecurityProvider-service-1.3.jar
caGrid-ServiceSecurityProvider-stubs-1.3.jar
The caGrid ServiceSecurityClient
caGrid-gaards-core-1.3.jar Used for caGrid public key infrastructure certificates.
caGrid-gts-client-1.3.jar
caGrid-gts-common-1.3.jar
caGrid-gts-stubs-1.3.jar
Not directly used, required by SyncGTS.
caGrid-metadata-common-1.3.jar
caGrid-metadata-data-1.3.jar
caGrid-metadata-security-1.3.jar
Used to provide support for caGrid service metadata.
caGrid-opensaml-1.3.jar Used internally by the caGrid Dorian and the Authentication Services.
caGrid-syncgts-client-1.3.jar
caGrid-syncgts-common-1.3.jar
caGrid-syncgts-stubs-1.3.jar
Used to provide the client and methods needed to synchronize with the grid trust fabric.
Update Ivy Dependencies

  1. Update ivy.xml with dependencies by adding the following entries within the '<dependencies>' section. Note that some of these are base caGrid and Globus dependencies that have been placed here because your application will have to synchronize with the trust fabric.
    <!-- Sync Dependencies -->
    <dependency rev="${repository.version}" org="caGrid" name="core"    conf="default->default" />
    <dependency rev="${repository.version}" org="caGrid" name="gts"     conf="default->stubs,client" />
    <dependency rev="${repository.version}" org="caGrid" name="syncgts" conf="default->stubs,common"/>
    <dependency rev="syncgts-patched-4.0.3" org="globus" name="jcog"    conf="default->default"/>
    <dependency rev="${repository.version}" org="caGrid" name="service-security-provider" conf="default->client,service"/>
    <dependency rev="${repository.version}" org="caGrid" name="metadata" conf="default->*" />
    <dependency rev="${repository.version}" org="caGrid" name="gaards-core" conf="default->default" />
    
  2. Save the ivy.xml file.
  3. From the command line run ant all to retrieve the new jars. You will see the required jars being downloaded from http://software.cagrid.org.

Import Jars into the Project

  1. To add the newly obtained Jars into project properties, right-click on the caGridClient project in the Eclipse Package Explorer.
  2. Select the Properties entry at the bottom of the list.
  3. Select Java Build Path, then Libraries.
  4. Click Add Library... button.
  5. Select the library type User Library and click Next
  6. In the Add Library dialog, click the User Libraries... button.
  7. In the Preferences dialog, click the New... button.
  8. Provide the name lib for the new User Library, then click OK.
  9. Click Add Jars
  10. Navigate to the caGridClient/lib directory, select the newly added jar files and click Open to add them to the lib user library.
  11. In the Preferences dialog, click OK.
  12. In the Add Library dialog, click Finish.

Add Endorsed Jars into the Project

  1. Add the endorsed jars to the ext directory. These jars contain APIs defined through processes other than the Java Community Process.
  2. Locate the following Jars in your caGrid directory: repository/apache/xerces2-j/2.7.1 directory and copy them into the caGridClient/ext/dependencies/endorsed/jars directory.
    1. resolver.jar
    2. xercesImpl.jar
    3. xml-apis.java

Create the SyncGridTrust Class

  1. In the Eclipse Package Explorer right-click the src/org.cagrid.client package and select New->Class
  2. Set the class name as SyncGridTrust and click 'Finish'.
  3. Add imports
    import gov.nih.nci.cagrid.common.Utils;
    import gov.nih.nci.cagrid.syncgts.bean.SyncDescription;
    import gov.nih.nci.cagrid.syncgts.core.SyncGTS;
    
  4. Add the following methods that use SyncGTS to obtain the trusted CA certificates for the Grid.
    //From: http://cagrid.org/display/gts12/Programmatic+Approach
    //Purpose: obtain trusted CA certificates from Slave GTS service
    public static boolean synchronizeOnce(String  syncDescriptionFile)
    {
    	boolean success = false;
    	try
    	{
    		//Load Sync Description
    		String pathToSyncDescription = syncDescriptionFile;
            	SyncDescription description = (SyncDescription) Utils.deserializeDocument(pathToSyncDescription,SyncDescription.class);
    
    		//Sync with the Trust Fabric Once
    		SyncGTS.getInstance().syncOnce(description);
    		success = true;
    	}
    	catch (Exception e) {e.printStackTrace();}
    	return success;
    }
    
    //Purpose: obtain trusted CA certificates from Slave GTS service repeatedly
    private static boolean synchronizePeriodic(String syncDescriptionFile)
    {
    	boolean success = false;
    	try
    	{
    		//Load Sync Description
    		String pathToSyncDescription = syncDescriptionFile; //"conf/training/sync-description.xml";
    		SyncDescription description = (SyncDescription) Utils.deserializeDocument(pathToSyncDescription,SyncDescription.class);
    
    		//Sync with the Trust Fabric Once
    		SyncGTS.getInstance().syncAndResync(description, success);
    		success = true;
    	}
    	catch (Exception e) {e.printStackTrace();}
    	return success;
    }
    
  5. Save the file.

Update the GridClient Class

  1. Open GridClient.java and add a method to call the synchronizeOnce method.
    private void syncTrust ()
    {
    	System.out.println("Synchronize Once...");
    	SyncGridTrust.synchronizeOnce(this.props.getProperty(SYNC_DESCRIPTION));
    	System.out.println("Synchronize Complete.");
    }
    
  2. Within the for loop of the main method, add the call to the syncTrust method where we are evaluating the user input of the value 1.
    client.syncTrust();
    
  3. Build the project
    > cd GRID_CLIENT_HOME
    
    > ant all
    
  4. Verify that the build completed successfully.
  5. Fix any compile errors that are reported.

Step 2: Register a Grid Account

In order to register an account you will have to complete an application and submit it to Dorian. The Application class implements the application, we'll instantiate this object, provide the required data and submit the request.

Jar Files:
Jar dependency Purpose
caGrid-dorian-client-1.3.jar
caGrid-dorian-common-1.3.jar
caGrid-dorian-stubs-1.3.jar
Used to provide the caGrid security clients.
axis.jar Globus Jar used when interacting with interacting with caGrid services.
Update Ivy Dependencies

  1. Open ivy.xml and update the project dependencies by adding the following entries within the '<dependencies>' section.
       <!-- UserAction Dependencies -->
       <dependency rev="${repository.version}" org="caGrid" name="dorian" conf="default->client,stubs,common"/>
    
  2. Save the ivy.xml file.
  3. From the command line run ant all to retrieve the new jars.

Import Jars into the Project

  1. Right-click on the caGridClient project in the Eclipse Package Explorer.
  2. Select the Properties entry at the bottom of the list.
  3. Select Java Build Path, then Libraries.
  4. Select the lib entry and click the Edit button.
  5. Click User Libraries
  6. Click Add Jars
  7. Navigate to the newly added jars under caGridClient/lib and add them to the lib user library.

Import Required Globus Jars

  1. To add the Globus Jars to the project properties, right-click on the caGridClient project in the Eclipse Package Explorer.
  2. Select the Properties entry at the bottom of the list.
  3. Select Java Build Path, then Libraries.
  4. Select the Add External Jars... entry.
  5. Navigate to the Globus ws-core-4.0.3/lib directory that was installed by the caGrid installer.
  6. Select the Globus Jars files, listed above, and then click Open.
  7. Click OK to close the Properties dialog.

Create the UserActions Class

  1. Right-click org.cagrid.client and select New->Class
  2. Set the class name as UserActions and click Finish.
  3. Add imports
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.MalformedURLException;
    import java.rmi.RemoteException;
    
    import org.apache.axis.types.URI.MalformedURIException;
    import org.cagrid.gaards.dorian.client.DorianClient;
    import org.cagrid.gaards.dorian.idp.Application;
    import org.cagrid.gaards.dorian.idp.CountryCode;
    import org.cagrid.gaards.dorian.idp.StateCode;
    
  4. Add the member variable
    private String serviceUrl = null;
    
  5. Add the constructor method.
    public UserActions (String dorianUrl)  throws MalformedURLException, MalformedURIException, RemoteException{
    	this.serviceUrl = dorianUrl;
    }
    
  6. Add the registerUser method.
    // Register user against Dorian service
    public boolean registerUser () throws MalformedURIException, RemoteException {
    
    // Create a registraton application
    Application userApplication = new Application();
    
    // You should be getting values from your UI here
    userApplication.setUserId( UserInteraction.getUsername() );
    userApplication.setEmail( UserInteraction.getEmail() );
    userApplication.setPassword( UserInteraction.getPassword() );
    userApplication.setFirstName( UserInteraction.getFirstName() );
    userApplication.setLastName( UserInteraction.getLastName() );
    userApplication.setAddress( UserInteraction.getAddress() );
    userApplication.setAddress2( UserInteraction.getAddress2() );
    userApplication.setCity( UserInteraction.getCity() );
    userApplication.setState( StateCode.fromString(
    UserInteraction.getState() ) );
    userApplication.setCountry( CountryCode.fromString(
    UserInteraction.getCountry() ) );
    userApplication.setZipcode( UserInteraction.getZipCode() );
    userApplication.setPhoneNumber( UserInteraction.getPhoneNumber() );
    userApplication.setOrganization(
    UserInteraction.getOrganization());
    
    // request a local registration using the Dorian client
    DorianClient dorianClient = new DorianClient(this.serviceUrl);
    if ( dorianClient.doesLocalUserExist(userApplication.getUserId()) )
    {
    	System.out.println("User already registered: " + userApplication.getUserId() );
    	return false;
    }
    else {dorianClient.registerLocalUser(userApplication);}
    
    return true;
    }
    
  7. Save the file.

Update the GridClient Class

  1. Add import statements
    import java.net.MalformedURLException;
    import org.apache.axis.types.URI.MalformedURIException;
    import java.rmi.RemoteException;
    import gov.nih.nci.cagrid.common.security.ProxyUtil;
    
  2. Add constant for reading Dorian Service URL from properties file
    private static final String DEFAULT_DORIAN_SERVICE_URL_PROP = "default.dorian.service.url";
    
  3. Add a method to call the UserActions.registerUser method.
    	private void registerUser ()
    	{
    		try
    		{
    			UserActions userActions = new UserActions ( this.props.getProperty(DEFAULT_DORIAN_SERVICE_URL_PROP));
    			userActions.registerUser();
    		}
    		catch (MalformedURLException e) {e.printStackTrace();}
    		catch (MalformedURIException e) {e.printStackTrace();}
    		catch (RemoteException e) {e.printStackTrace();}
    	}
    
  4. Within the for loop of the main method, add the call to the registerUser method where we are evaluating the user input of the value 2.
    client.registerUser();
    
  5. Build the project
    > cd GRID_CLIENT_HOME
    
    > ant all
    
  6. Fix any compile errors that are reported.

Step 3: Login and Save Your Credential


Logging into the Grid is a multi-step process. The initial step is to obtain user credentials, typically username and password, and validate this information against the Dorian Identity Provider in order to obtain a SAML Assertion. This SAML Assertion and an integer, specifying the maximum number of hours that the grid credential is valid, are then submitted to the Dorian Identity Federation Service in order to obtain a Grid credential, or proxy, which can be used to access secure grid services.

When invoking Grid services you will need to determine if the services are secure or non-secure. caGrid client classes will typically provide usually two constructors. The constructor for invoking secure services will allow you to submit a grid credential.

For more information see:Logging onto the Grid

Edit the UserActions Class

  1. Open UserActions.java for editing.
  2. Add import statements to support user login.
    import gov.nih.nci.cagrid.opensaml.SAMLAssertion;
    import org.cagrid.gaards.authentication.BasicAuthentication;
    import org.cagrid.gaards.authentication.client.AuthenticationClient;
    import org.cagrid.gaards.dorian.client.GridUserClient;
    import org.cagrid.gaards.dorian.federation.CertificateLifetime;
    import org.cagrid.gaards.dorian.federation.TrustedIdentityProvider;
    import org.globus.gsi.GlobusCredential;
    import java.util.List;
    import java.util.ListIterator;
    
  3. Add the loginUser method.
    // Authenticate User using Dorian clients
    // From: http://www.cagrid.org/display/dorian13/Programmatically+Login+to+Dorian
    public GlobusCredential loginUser () throws Exception
    {
        String URL=null;
        GridUserClient gridClient;
    
        gridClient = new GridUserClient(this.serviceUrl);
        List<TrustedIdentityProvider> idps = gridClient.getTrustedIdentityProviders();
    
        ListIterator<TrustedIdentityProvider> idpIterator = idps.listIterator();
        int count=1;
        while (idpIterator.hasNext())
        {
            TrustedIdentityProvider idp = idpIterator.next();
            String url = idp.getAuthenticationServiceURL();
            String name = idp.getDisplayName();
            System.out.println(count++ +" : "+ name + ": AuthServiceUrl = " + url);
        }
        int idpID = UserInteraction.getIntegerFromUser("Select your credential provider", 1, (count-1));
        TrustedIdentityProvider idp = idps.get(idpID-1);
    
        URL=idp.getAuthenticationServiceURL();
        System.out.println("Authenticating using " + idp.getDisplayName());
    
        String userName = UserInteraction.getUsername();
        String userPass = UserInteraction.getPassword();
    
        // Create credential
        BasicAuthentication auth = new BasicAuthentication();
        auth.setUserId(userName);
        auth.setPassword(userPass);
    
        // Authenticate to the IdP (DorianIdP) using credential
        AuthenticationClient authClient = new AuthenticationClient(URL);
        SAMLAssertion saml = authClient.authenticate(auth);
    
        // Requested Grid Credential lifetime. Dorian defines the maximum as 12 hours.
        String message = "Enter credential lifetime in hours";
        int lifetimeHours = UserInteraction.getIntegerFromUser(message, 1, 12);
        CertificateLifetime lifetime = new CertificateLifetime();
        lifetime.setHours(lifetimeHours);
    
        // Request PKI/Grid Credential
        GridUserClient dorian = new GridUserClient(this.serviceUrl);
        GlobusCredential credential = dorian.requestUserCertificate(saml, lifetime);
    
        return credential;
    }
  4. Save the file.

Update the GridClient Class

  1. Open GridClient.java for editing.
  2. Add import statements
    import org.apache.axis.AxisFault;
    import org.apache.axis.types.URI.MalformedURIException;
    import org.globus.gsi.GlobusCredential;
    import gov.nih.nci.cagrid.common.security.ProxyUtil;
    
  3. Add constant for the user credential file
    private static final String DEFAULT_PROXY_FILENAME = "proxy.save.file";
    private GlobusCredential cred = null; 
    
  4. Add a method to call the UserActions.loginUser method.
    private void loginUser ()
    {
        System.out.println("Login to the Grid");
        try
        {
        	// if valid proxy exists, use it
            File proxy = new File(props.getProperty(DEFAULT_PROXY_FILENAME));
            if (proxy.exists())
            {
                GlobusCredential oldCred = ProxyUtil.loadProxy(props.getProperty(DEFAULT_PROXY_FILENAME));
                Long timeLeft = oldCred.getTimeLeft();
                if (timeLeft > 0)
                {
                    System.out.println("Using existing credential:\n"+ oldCred.toString());
                    this.cred = oldCred;
                    String msg="If you would like to use another credential press 1 otherwise press 0";
                    boolean end=true;
                    while(end)
                    {
                        int userInput = UserInteraction.getIntegerFromUser (msg, 0, 1);
                        if(userInput==0){return;}
                        else if(userInput!=1){end=true;}
                        else{end=false;}
                    }
                }
            }
            UserActions userActions = new UserActions(props.getProperty(DEFAULT_DORIAN_SERVICE_URL_PROP));
    
            this.cred = userActions.loginUser();
            System.out.println("Identity = " + cred.getIdentity());
    
            ProxyUtil.saveProxy(cred, props.getProperty(DEFAULT_PROXY_FILENAME));
        	System.out.println("User credential saved to  = " + props.getProperty(DEFAULT_PROXY_FILENAME));
        	System.out.println("Login complete.");
        }
        catch (AxisFault af) {System.out.println(af.getClass().getName() + ": " + af.getFaultString());}
        catch (Throwable e)
        {
        	System.out.println(e.getClass().getName() + ": " + e.toString());
        	e.printStackTrace();
        }
    }
    
  5. Within the for loop of the main method, add the call to the loginUser method where we are evaluating the user input of the value 3.
    client.loginUser();
    
  6. Save the file.

Build the application

  1. Build the project
    > cd GRID_CLIENT_HOME
    
    > ant all
    
  2. Fix any compilation errors.

Step 4: Test the Client


The Ant build file includes a target for running the client. It will create a classpath from the jars included by Ivy.

  1. Open a command prompt.
  2. Change directory to your caGridClient location
  3. Type ant run. This will build and execute the project
  4. When prompted, type 1 to synchronize with the grid trust fabric.
  5. You should see the following:
     [java] Synchronize Once...      
    [java] Synchronize Complete.
    
  6. When prompted for the next action, type 2 to register and account.
  7. Provide input for all requested fields for an existing user.
  8. Upon submission of the register request you should see
    [java] User already registered: <userid>
    
  9. When prompted for the next action, type 2 to register and account.
  10. Provide input for all requested fields for a new user.
  11. Upon submission of the register request you should see
    [java] User registered with Dorian
    
  12. When prompted for the next action, type 3 to login to the grid.
  13. If you have previously logged in via the client, the previous credential will be used by default, and it will ask if another credential should be used.
    Login to the Grid
    Using existing credential:
    subject    : O=caBIG,OU=caGrid,OU=Training,OU=Dorian,CN=<userid>
    issuer     : O=caBIG,OU=caGrid,OU=Training,CN=caGrid Training CA
    strength   : 1024 bits
    timeleft   : 41087 sec
    proxy type : not a proxy
    If you would like to use another credential press 1 otherwise press 0 [0..1] :
    
  14. When prompted, provide username, password and lifetime of the generated credential.
    1. Yes, the password is echoed to the screen, which is not good programming practice. You'll need to mask the password in your UI by using the provided classes, like JPasswordField for Swing.
  15. Upon submission of the login request you should see
    [java] Identity = /O=caBIG/OU=caGrid/OU=Training/OU=Dorian/CN=<userid>
    [java] User credential saved to  = user.proxy
    [java] Login complete.
    
  16. When prompted for the next action, type 3 to login to the grid.
  17. Provide bad username and password.
  18. Upon submission of the login request you should see
    [java] gov.nih.nci.cagrid.authentication.stubs.types.InvalidCredentialFault: User Id or password is incorrect
    
  19. Type 10 to quit.

Conclusion


At this point you should have the following:

  1. You have created a Training Grid account
  2. You have logged into the Training Grid using GAARDS-UI
  3. You have synchronized with the Grid Trust Fabric programmatically
  4. You have registered an account programmatically.
  5. You have logged into the Grid programmatically.

Many additional user specific tasks are made available via the Dorian Client. These methods, such as changing passwords, may be of great use to your application. You are urged to spend some time researching the Dorian Client to determine which actions you should include in your application.

Developers of client applications that serve many users will need to determine an appropriate method of storing grid credentials. These credentials must be associated with a single user context within your application.

References


Last edited by
Saba Bokhari (365 days ago) , ...
Adaptavist Theme Builder Powered by Atlassian Confluence