View Javadoc

1   /*
2    * Copyright 2004-2005 The Apache Software Foundation or its licensors,
3    *                     as applicable.
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.portals.graffito.jcr.security;
18  
19  import org.apache.jackrabbit.core.security.AnonymousPrincipal;
20  import org.apache.jackrabbit.core.security.CredentialsCallback;
21  import org.apache.jackrabbit.core.security.SecurityConstants;
22  import org.apache.jackrabbit.core.security.UserPrincipal;
23  import org.apache.log4j.Logger;
24  
25  import javax.jcr.Credentials;
26  import javax.jcr.SimpleCredentials;
27  import javax.security.auth.Subject;
28  import javax.security.auth.callback.Callback;
29  import javax.security.auth.callback.CallbackHandler;
30  import javax.security.auth.callback.UnsupportedCallbackException;
31  import javax.security.auth.login.FailedLoginException;
32  import javax.security.auth.login.LoginException;
33  import javax.security.auth.spi.LoginModule;
34  import java.util.HashSet;
35  import java.util.Map;
36  import java.util.Set;
37  
38  /***
39   * A <code>SimpleLoginModule</code> ...
40   */
41  public class SimpleLoginModule implements LoginModule
42  {
43  
44  	private static Logger log = Logger.getLogger(SimpleLoginModule.class);
45  
46  	/***
47  	 * Name of the anonymous user id option in the LoginModule configuration
48  	 */
49  	private static final String OPT_ANONYMOUS = "anonymousId";
50  
51  	/***
52  	 * The default user id for anonymous login
53  	 */
54  	private static final String DEFAULT_ANONYMOUS_ID = "anonymous";
55  
56  	// initial state
57  	private Subject subject;
58  
59  	private CallbackHandler callbackHandler;
60  
61  	private Map sharedState;
62  
63  	private Map options;
64  
65  	// configurable options
66  	//private boolean someOpt = false;
67  
68  	// local authentication state:
69  	// the principals, i.e. the authenticated identities
70  	private final Set principals = new HashSet();
71  
72  	/***
73  	 * Id of an anonymous user login
74  	 */
75  	private String anonymousUserId = DEFAULT_ANONYMOUS_ID;
76  
77  	/***
78  	 * Constructor
79  	 */
80  	public SimpleLoginModule()
81  	{
82  	}
83  
84  	//----------------------------------------------------------< LoginModule >
85  	/***
86  	 * {@inheritDoc}
87  	 */
88  	public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options)
89  	{
90  		this.subject = subject;
91  		this.callbackHandler = callbackHandler;
92  		this.sharedState = sharedState;
93  		this.options = options;
94  
95  		// initialize any configured options
96  		//someOpt = "true".equalsIgnoreCase((String)options.get("someOpt"));
97  		String userId = (String) options.get(OPT_ANONYMOUS);
98  		if (userId != null)
99  		{
100 			anonymousUserId = userId;
101 		}
102 	}
103 
104 	/***
105 	 * {@inheritDoc}
106 	 */
107 	public boolean login() throws LoginException
108 	{
109 		// prompt for a user name and password
110 		if (callbackHandler == null)
111 		{
112 			throw new LoginException("no CallbackHandler available");
113 		}
114 
115 		Callback[] callbacks = new Callback[]
116 		{ new CredentialsCallback() };
117 
118 		boolean authenticated = false;
119 		principals.clear();
120 		try
121 		{
122 			callbackHandler.handle(callbacks);
123 			// credentials
124 			CredentialsCallback ccb = (CredentialsCallback) callbacks[0];
125 			Credentials creds = ccb.getCredentials();
126 			if (creds != null)
127 			{
128 				if (creds instanceof SimpleCredentials)
129 				{
130 					SimpleCredentials sc = (SimpleCredentials) creds;
131 					// authenticate
132 
133 					Object attr = sc.getAttribute(SecurityConstants.IMPERSONATOR_ATTRIBUTE);
134 					if (attr != null && attr instanceof Subject)
135 					{
136 						Subject impersonator = (Subject) attr;
137 						// @todo check privileges to 'impersonate' the user represented by the supplied credentials
138 					}
139 					else
140 					{
141 						// @todo implement simple username/password authentication
142 					}
143 
144 					if (anonymousUserId.equals(sc.getUserID()))
145 					{
146 						principals.add(new AnonymousPrincipal());
147 					}
148 					else
149 					{
150 						// else assume the user we authenticated is the UserPrincipal
151 						principals.add(new UserPrincipal(sc.getUserID()));
152 					}
153 					authenticated = true;
154 				}
155 			}
156 		}
157 		catch (java.io.IOException ioe)
158 		{
159 			throw new LoginException(ioe.toString());
160 		}
161 		catch (UnsupportedCallbackException uce)
162 		{
163 			throw new LoginException(uce.getCallback().toString() + " not available");
164 		}
165 
166 		if (authenticated)
167 		{
168 			return !principals.isEmpty();
169 		}
170 		else
171 		{
172 			// authentication failed: clean out state
173 			principals.clear();
174 			throw new FailedLoginException();
175 		}
176 	}
177 
178 	/***
179 	 * {@inheritDoc}
180 	 */
181 	public boolean commit() throws LoginException
182 	{
183 		if (principals.isEmpty())
184 		{
185 			return false;
186 		}
187 		else
188 		{
189 			// add a principals (authenticated identities) to the Subject
190 			subject.getPrincipals().addAll(principals);
191 			return true;
192 		}
193 	}
194 
195 	/***
196 	 * {@inheritDoc}
197 	 */
198 	public boolean abort() throws LoginException
199 	{
200 		if (principals.isEmpty())
201 		{
202 			return false;
203 		}
204 		else
205 		{
206 			logout();
207 		}
208 		return true;
209 	}
210 
211 	/***
212 	 * {@inheritDoc}
213 	 */
214 	public boolean logout() throws LoginException
215 	{
216 		subject.getPrincipals().removeAll(principals);
217 		principals.clear();
218 		return true;
219 	}
220 }