2 * Copyright 2011 Electronic Business Systems Ltd.
4 * This file is part of GSS.
6 * GSS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GSS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GSS. If not, see <http://www.gnu.org/licenses/>.
19 package gr.ebs.gss.server.webdav.milton;
21 import static gr.ebs.gss.server.configuration.GSSConfigurationFactory.getConfiguration;
22 import gr.ebs.gss.client.exceptions.RpcException;
23 import gr.ebs.gss.server.ejb.ExternalAPI;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.Iterator;
28 import java.util.List;
30 import javax.naming.Context;
31 import javax.naming.InitialContext;
32 import javax.naming.NamingException;
33 import javax.rmi.PortableRemoteObject;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 import com.bradmcevoy.http.Auth;
39 import com.bradmcevoy.http.AuthenticationHandler;
40 import com.bradmcevoy.http.AuthenticationService;
41 import com.bradmcevoy.http.Request;
42 import com.bradmcevoy.http.Resource;
43 import com.bradmcevoy.http.http11.auth.BasicAuthHandler;
44 import com.bradmcevoy.http.http11.auth.DigestAuthenticationHandler;
51 public class GssAuthenticationService extends com.bradmcevoy.http.AuthenticationService{
52 private static final Logger log = LoggerFactory.getLogger( AuthenticationService.class );
53 private List<AuthenticationHandler> authenticationHandlers;
54 private List<AuthenticationHandler> extraHandlers;
55 private List<AuthenticationHandler> allHandlers;
56 private boolean disableBasic;
57 private boolean disableDigest;
60 * Creates a AuthenticationService using the given handlers. Use this if
61 * you don't want the default of a BasicAuthHandler and a DigestAuthenticationHandler
63 * @param authenticationHandlers
65 public GssAuthenticationService( List<AuthenticationHandler> authenticationHandlers ) {
66 this.authenticationHandlers = authenticationHandlers;
72 * Creates with Basic and Digest handlers
75 public GssAuthenticationService() {
76 AuthenticationHandler digest = new com.bradmcevoy.http.http11.auth.DigestAuthenticationHandler();
77 AuthenticationHandler basic = new BasicAuthHandler();
78 authenticationHandlers = new ArrayList<AuthenticationHandler>();
79 authenticationHandlers.add( basic );
80 authenticationHandlers.add( digest );
84 public void setDisableBasic( boolean b ) {
86 Iterator<AuthenticationHandler> it = this.authenticationHandlers.iterator();
87 while( it.hasNext() ) {
88 AuthenticationHandler hnd = it.next();
89 if( hnd instanceof BasicAuthHandler ) {
98 public boolean isDisableBasic() {
102 public void setDisableDigest( boolean b ) {
104 Iterator<AuthenticationHandler> it = this.authenticationHandlers.iterator();
105 while( it.hasNext() ) {
106 AuthenticationHandler hnd = it.next();
107 if( hnd instanceof DigestAuthenticationHandler ) {
116 public boolean isDisableDigest() {
117 return disableDigest;
122 * Generates a list of http authentication challenges, one for each
123 * supported authentication method, to be sent to the client.
125 * @param resource - the resoruce being requested
126 * @param request - the current request
127 * @return - a list of http challenges
129 public List<String> getChallenges( Resource resource, Request request ) {
130 List<String> challenges = new ArrayList<String>();
131 for( AuthenticationHandler h : allHandlers ) {
132 if( h.isCompatible( resource ) ) {
133 log.debug( "challenge for auth: " + h.getClass() );
134 String ch = h.getChallenge( resource, request );
135 challenges.add( ch );
137 log.debug( "not challenging for auth: " + h.getClass() + " for resource type: " + resource.getClass() );
143 public List<AuthenticationHandler> getAuthenticationHandlers() {
147 public List<AuthenticationHandler> getExtraHandlers() {
148 return extraHandlers;
151 public void setExtraHandlers( List<AuthenticationHandler> extraHandlers ) {
152 this.extraHandlers = extraHandlers;
157 * Merge standard and extra handlers into single list
159 private void setAllHandlers() {
160 List<AuthenticationHandler> handlers = new ArrayList<AuthenticationHandler>();
161 if( authenticationHandlers != null ) {
162 handlers.addAll( authenticationHandlers );
164 if( extraHandlers != null ) {
165 handlers.addAll( extraHandlers );
167 this.allHandlers = Collections.unmodifiableList( handlers );
171 public AuthStatus authenticate( Resource resource, Request request ) {
172 log.trace( "authenticate" );
173 Auth auth = request.getAuthorization();
174 boolean preAuthenticated = ( auth != null && auth.getTag() != null );
175 if( preAuthenticated ) {
176 log.trace( "request is pre-authenticated" );
177 return new AuthStatus( auth, false );
179 for( AuthenticationHandler h : getAuthenticationHandlers() ) {
180 if( h.supports( resource, request ) ) {
181 Object loginToken = h.authenticate( resource, request );
182 if( loginToken == null ) {
183 log.warn( "authentication failed by AuthenticationHandler:" + h.getClass() );
184 return new AuthStatus( auth, true );
186 if( log.isTraceEnabled() ) {
187 log.trace( "authentication passed by: " + h.getClass() );
189 if( auth == null ) { // some authentication handlers do not require an Auth object
190 auth = new Auth( Auth.Scheme.FORM, null, loginToken );
191 request.setAuthorization( auth );
193 auth.setTag( loginToken );
195 return new AuthStatus( auth, false );
202 * A helper method that retrieves a reference to the ExternalAPI bean and
203 * stores it for future use.
205 * @return an ExternalAPI instance
206 * @throws RpcException in case an error occurs
208 protected ExternalAPI getService() throws RpcException {
210 final Context ctx = new InitialContext();
211 final Object ref = ctx.lookup(getConfiguration().getString("externalApiPath"));
212 return (ExternalAPI) PortableRemoteObject.narrow(ref, ExternalAPI.class);
213 } catch (final NamingException e) {
214 log.error("Unable to retrieve the ExternalAPI EJB", e);
215 throw new RpcException("An error occurred while contacting the naming service");