View Javadoc

1   package org.astrogrid.security.jaas;
2   
3   import java.util.Map;
4   import java.util.Set;
5   import javax.security.auth.Subject;
6   import javax.security.auth.callback.CallbackHandler;
7   import javax.security.auth.login.FailedLoginException;
8   import javax.security.auth.login.LoginException;
9   import javax.security.auth.spi.LoginModule;
10  import org.astrogrid.security.AccountName;
11  import org.astrogrid.security.InvalidAccountException;
12  import org.astrogrid.security.InvalidCredentialException;
13  import org.astrogrid.security.NonceToken;
14  import org.astrogrid.store.Ivorn;
15  
16  
17  /***
18   * A JAAS log-in module implementing AstroGrid's nonce-token protocol.
19   * protocol. This class is called by the JAAS framework when an application
20   * calls a LoginContext that is configured for NonceTokens. Application code
21   * should not need to call this class directly (except for unit tests).
22   *
23   * @author Guy Rixon
24   */
25  public class NonceTokenCheck implements LoginModule {
26  
27    /***
28     * The identity and a priori credentials of the party
29     * to be authenticated.
30     */
31    Subject subject;
32  
33    /***
34     * The authenticated identity of the party.
35     */
36    AccountName account;
37  
38    /***
39     * The nonce token after authentication.
40     */
41    NonceToken token;
42  
43  
44    /***
45     * States the subject of the authentication and sets
46     * shared authentication state (no shared state is used
47     * in this implementation.
48     *
49     * @param subject contains identity and credentials for the
50     * party to be authenticated
51     * @param callback not used with NonceTokens
52     * @param sharedState not used with NonceTokens
53     * @param options not used in NonceTokens
54     */
55    public void initialize (Subject         subject,
56                            CallbackHandler callback,
57                            Map             sharedState,
58                            Map             options) {
59      this.subject = subject;
60    }
61  
62  
63    /***
64     * Authenticates the subject set at initialization.
65     * If authentication succeeds, the NonceToken in the Subject
66     * is updated.
67     *
68     * @return true if the authentication succeeded,
69     * or false if this LoginModule should be ignored
70     * @throws LoginException if authentication fails
71     */
72    public boolean login () throws LoginException {
73      System.out.println("Entering NonceTokenCheck.login()...");
74  
75      // Extract the original token from the context.
76      // No tokens means no authentication.
77      // Treat multiple tokens as an error, for simplicity.
78      NonceToken oldToken = null;
79      NonceToken newToken = null;
80      Set tokens = this.subject.getPrivateCredentials(NonceToken.class);
81      if (tokens.size() == 0) {
82        System.out.println("NonceTokenCheck.login(): authentication failed: No nonce tokens were presented.");
83        throw new LoginException("No nonce tokens were presented");
84      }
85      else if (tokens.size() > 1) {
86        System.out.println("NonceTokenCheck.login(): authentication failed: too many nonce tokens were presented.");
87        throw new LoginException("Too many nonce tokens were presented.");
88      }
89      else {
90        this.token = (NonceToken) tokens.iterator().next();
91        this.account = new AccountName(this.token.getAccount());
92      }
93      System.out.println(" NonceTokenCheck.login(): attempting authentication for " +
94                         this.account.getName() +
95                         " with token " +
96                         this.token.toString());
97  
98      // Check the original token in the community service.
99      // This can cause several types of exception to be thrown.
100     try {
101 	  this.token.validate();
102     }
103     catch (InvalidAccountException iae) {
104       String message = "Authentication failed: " + iae.getMessage();
105       System.out.println("NonceTokenCheck.login(): " + message);
106       throw new FailedLoginException(message);
107     }
108     catch (InvalidCredentialException ice) {
109       String message = "Authentication failed: " + ice.getMessage();
110       System.out.println("NonceTokenCheck.login(): " + message);
111       throw new FailedLoginException(message);
112     }
113     catch (Exception e) {
114       String message = "Authentication failed: " + e.getMessage();
115       System.out.println("NonceTokenCheck.login(): " + message);
116       throw new LoginException(message);
117     }
118 
119     return true;
120   }
121 
122 
123   /***
124    * Executes phase 2 of the log-in process. Extracts
125    * the account name from the token and stores it as a principal
126    * in the Subject.
127    */
128   public boolean commit () throws LoginException {
129 	System.out.println("Entering NonceTokenCheck.commit()");
130 	System.out.println("Committing Principal " + this.account.getName());
131     this.subject.getPrincipals().add(this.account);
132     return true;
133   }
134 
135 
136   /***
137    * Executes phase 2 of the log-in process. There is nothing
138    * to do in phase 2 for NonceTokens.
139    */
140   public boolean abort () throws LoginException {
141     return true;
142   }
143 
144 
145   /***
146    * Logs out the subject.  This has no meaning for
147    * NonceTokens.
148    */
149   public boolean logout () throws LoginException {
150     return true;
151   }
152 
153 
154 }