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
76
77
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
99
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 }