diff --git a/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/KerberosServiceAuthenticationProvider.java b/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/KerberosServiceAuthenticationProvider.java index ebbf172..27898e6 100644 --- a/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/KerberosServiceAuthenticationProvider.java +++ b/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/KerberosServiceAuthenticationProvider.java @@ -31,18 +31,18 @@ import org.springframework.util.Assert; /** - *

Authentication Provider which validates Kerberos Service Tickets + *

Authentication Provider which validates Kerberos Service Tickets * or SPNEGO Tokens (which includes Kerberos Service Tickets).

- * + * *

It needs a KerberosTicketValidator, which contains the * code to validate the ticket, as this code is different between * SUN and IBM JRE.
* It also needs an UserDetailsService to load the user properties * and the GrantedAuthorities, as we only get back the username * from Kerbeos

- * + * * You can see an example configuration in SpnegoAuthenticationProcessingFilter. - * + * * @author Mike Wiesner * @since 1.0 * @version $Id$ @@ -51,76 +51,76 @@ import org.springframework.util.Assert; * @see SpnegoAuthenticationProcessingFilter */ public class KerberosServiceAuthenticationProvider implements - AuthenticationProvider, InitializingBean { - - private static final Log LOG = LogFactory.getLog(KerberosServiceAuthenticationProvider.class); - - private KerberosTicketValidator ticketValidator; - private UserDetailsService userDetailsService; - private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker(); - - - /** The UserDetailsService to use, for loading the user properties - * and the GrantedAuthorities. - */ - public void setUserDetailsService(UserDetailsService userDetailsService) { - this.userDetailsService = userDetailsService; - } + AuthenticationProvider, InitializingBean { - /** The KerberosTicketValidator to use, for validating - * the Kerberos/SPNEGO tickets. - */ - public void setTicketValidator(KerberosTicketValidator ticketValidator) { - this.ticketValidator = ticketValidator; - } + private static final Log LOG = LogFactory.getLog(KerberosServiceAuthenticationProvider.class); - /* (non-Javadoc) - * @see org.springframework.security.authentication.AuthenticationProvider#authenticate(org.springframework.security.core.Authentication) - */ - @Override - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { - KerberosServiceRequestToken auth = (KerberosServiceRequestToken) authentication; - byte[] token = auth.getToken(); - LOG.debug("Try to validate Kerberos Token"); - String username = this.ticketValidator.validateTicket(token); - LOG.debug("Succesfully validated " + username); - UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); - userDetailsChecker.check(userDetails); - additionalAuthenticationChecks(userDetails, auth); - return new KerberosServiceRequestToken(userDetails, userDetails.getAuthorities(), token); - } - - - /** - * Allows subclasses to perform any additional checks of a returned UserDetails - * for a given authentication request. - * - * @param userDetails as retrieved from the {@link UserDetailsService} - * @param authentication validated {@link KerberosServiceRequestToken} - * @throws AuthenticationException AuthenticationException if the credentials could not be validated (generally a - * BadCredentialsException, an AuthenticationServiceException) - */ - protected void additionalAuthenticationChecks(UserDetails userDetails, KerberosServiceRequestToken authentication) - throws AuthenticationException { - + private KerberosTicketValidator ticketValidator; + private UserDetailsService userDetailsService; + private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker(); + + + /** The UserDetailsService to use, for loading the user properties + * and the GrantedAuthorities. + */ + public void setUserDetailsService(UserDetailsService userDetailsService) { + this.userDetailsService = userDetailsService; } - /* (non-Javadoc) - * @see org.springframework.security.authentication.AuthenticationProvider#supports(java.lang.Class) - */ - @Override - public boolean supports(Class auth) { - return KerberosServiceRequestToken.class.isAssignableFrom(auth); - } + /** The KerberosTicketValidator to use, for validating + * the Kerberos/SPNEGO tickets. + */ + public void setTicketValidator(KerberosTicketValidator ticketValidator) { + this.ticketValidator = ticketValidator; + } - /* (non-Javadoc) - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws Exception { - Assert.notNull(this.ticketValidator, "ticketValidator must be specified"); - Assert.notNull(this.userDetailsService, "userDetailsService must be specified"); - } + /* (non-Javadoc) + * @see org.springframework.security.authentication.AuthenticationProvider#authenticate(org.springframework.security.core.Authentication) + */ + @Override + public Authentication authenticate(Authentication authentication) + throws AuthenticationException { + KerberosServiceRequestToken auth = (KerberosServiceRequestToken) authentication; + byte[] token = auth.getToken(); + LOG.debug("Try to validate Kerberos Token"); + String username = this.ticketValidator.validateTicket(token); + LOG.debug("Succesfully validated " + username); + UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); + userDetailsChecker.check(userDetails); + additionalAuthenticationChecks(userDetails, auth); + return new KerberosServiceRequestToken(userDetails, userDetails.getAuthorities(), token); + } + + + /** + * Allows subclasses to perform any additional checks of a returned UserDetails + * for a given authentication request. + * + * @param userDetails as retrieved from the {@link UserDetailsService} + * @param authentication validated {@link KerberosServiceRequestToken} + * @throws AuthenticationException AuthenticationException if the credentials could not be validated (generally a + * BadCredentialsException, an AuthenticationServiceException) + */ + protected void additionalAuthenticationChecks(UserDetails userDetails, KerberosServiceRequestToken authentication) + throws AuthenticationException { + + } + + /* (non-Javadoc) + * @see org.springframework.security.authentication.AuthenticationProvider#supports(java.lang.Class) + */ + @Override + public boolean supports(Class auth) { + return KerberosServiceRequestToken.class.isAssignableFrom(auth); + } + + /* (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + @Override + public void afterPropertiesSet() throws Exception { + Assert.notNull(this.ticketValidator, "ticketValidator must be specified"); + Assert.notNull(this.userDetailsService, "userDetailsService must be specified"); + } } diff --git a/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/KerberosServiceRequestToken.java b/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/KerberosServiceRequestToken.java index dcaaee7..9a6c38c 100644 --- a/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/KerberosServiceRequestToken.java +++ b/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/KerberosServiceRequestToken.java @@ -27,11 +27,11 @@ import org.springframework.security.extensions.kerberos.web.SpnegoAuthentication /** * Holds the Kerberos/SPNEGO token for requesting a kerberized service * and is also the output of KerberosServiceAuthenticationProvider.
- * Will mostly be created in SpnegoAuthenticationProcessingFilter + * Will mostly be created in SpnegoAuthenticationProcessingFilter * and authenticated in KerberosServiceAuthenticationProvider. - * + * * This token cannot be re-authenticated, as you will get a Kerberos Reply error. - * + * * @author Mike Wiesner * @since 1.0 * @version $Id$ @@ -41,84 +41,84 @@ import org.springframework.security.extensions.kerberos.web.SpnegoAuthentication public class KerberosServiceRequestToken extends AbstractAuthenticationToken { - private static final long serialVersionUID = 395488921064775014L; - private final byte[] token; - private final Object principal; - - /** Creates an authenticated token, normally used as an output of an authentication provider. - * @param principal the user principal (mostly of instance UserDetails - * @param authorities the authorities which are granted to the user - * @param token the Kerberos/SPNEGO token - * @see UserDetails - */ - public KerberosServiceRequestToken(Object principal, List authorities, byte[] token) { - super(authorities); - this.token = token; - this.principal = principal; - super.setAuthenticated(true); - } + private static final long serialVersionUID = 395488921064775014L; + private final byte[] token; + private final Object principal; - /** - * Creates an unauthenticated instance which should then be authenticated by - * KerberosServiceAuthenticationProvider/code> - * - * @param token Kerberos/SPNEGO token - * @see KerberosServiceAuthenticationProvider - */ - public KerberosServiceRequestToken(byte[] token) { - super(null); - this.token = token; - this.principal = null; - } + /** Creates an authenticated token, normally used as an output of an authentication provider. + * @param principal the user principal (mostly of instance UserDetails + * @param authorities the authorities which are granted to the user + * @param token the Kerberos/SPNEGO token + * @see UserDetails + */ + public KerberosServiceRequestToken(Object principal, List authorities, byte[] token) { + super(authorities); + this.token = token; + this.principal = principal; + super.setAuthenticated(true); + } - /** - * Calculates hashcode based on the Kerberos token - */ - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + Arrays.hashCode(token); - return result; - } + /** + * Creates an unauthenticated instance which should then be authenticated by + * KerberosServiceAuthenticationProvider/code> + * + * @param token Kerberos/SPNEGO token + * @see KerberosServiceAuthenticationProvider + */ + public KerberosServiceRequestToken(byte[] token) { + super(null); + this.token = token; + this.principal = null; + } - /** - * equals() is based only on the Kerberos token - */ - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - KerberosServiceRequestToken other = (KerberosServiceRequestToken) obj; - if (!Arrays.equals(token, other.token)) - return false; - return true; - } + /** + * Calculates hashcode based on the Kerberos token + */ + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + Arrays.hashCode(token); + return result; + } - /* (non-Javadoc) - * @see org.springframework.security.core.Authentication#getCredentials() - */ - @Override - public Object getCredentials() { - return null; - } + /** + * equals() is based only on the Kerberos token + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + KerberosServiceRequestToken other = (KerberosServiceRequestToken) obj; + if (!Arrays.equals(token, other.token)) + return false; + return true; + } - /* (non-Javadoc) - * @see org.springframework.security.core.Authentication#getPrincipal() - */ - @Override - public Object getPrincipal() { - return this.principal; - } + /* (non-Javadoc) + * @see org.springframework.security.core.Authentication#getCredentials() + */ + @Override + public Object getCredentials() { + return null; + } - /** Returns the Kerberos token - */ - public byte[] getToken() { - return this.token; - } + /* (non-Javadoc) + * @see org.springframework.security.core.Authentication#getPrincipal() + */ + @Override + public Object getPrincipal() { + return this.principal; + } + + /** Returns the Kerberos token + */ + public byte[] getToken() { + return this.token; + } } diff --git a/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/KerberosTicketValidator.java b/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/KerberosTicketValidator.java index 9dd9551..9d72d7a 100644 --- a/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/KerberosTicketValidator.java +++ b/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/KerberosTicketValidator.java @@ -21,7 +21,7 @@ import org.springframework.security.authentication.BadCredentialsException; /** * Implementations of this interface are used in * {@link KerberosServiceAuthenticationProvider} to validate a Kerberos/SPNEGO Ticket. - * + * * @author Mike Wiesner * @since 1.0 * @version $Id$ @@ -29,11 +29,11 @@ import org.springframework.security.authentication.BadCredentialsException; */ public interface KerberosTicketValidator { - /** Validates a Kerberos/SPNEGO ticket. - * @param token Kerbeos/SPNEGO ticket - * @return authenticated kerberos principal - * @throws BadCredentialsException if the ticket is not valid - */ - public String validateTicket(byte[] token) throws BadCredentialsException; + /** Validates a Kerberos/SPNEGO ticket. + * @param token Kerbeos/SPNEGO ticket + * @return authenticated kerberos principal + * @throws BadCredentialsException if the ticket is not valid + */ + public String validateTicket(byte[] token) throws BadCredentialsException; } \ No newline at end of file diff --git a/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/SunJaasKerberosTicketValidator.java b/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/SunJaasKerberosTicketValidator.java index d7914f2..b65ce7b 100644 --- a/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/SunJaasKerberosTicketValidator.java +++ b/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/SunJaasKerberosTicketValidator.java @@ -39,142 +39,142 @@ import org.springframework.util.Assert; /** * Implementation of {@link KerberosTicketValidator} which uses the SUN JAAS - * login module, which is included in the SUN JRE, it will not work with an IBM JRE. + * login module, which is included in the SUN JRE, it will not work with an IBM JRE. * The whole configuration is done in this class, no additional JAAS configuration * is needed. - * + * * @author Mike Wiesner * @since 1.0 * @version $Id$ */ public class SunJaasKerberosTicketValidator implements KerberosTicketValidator, InitializingBean { - private String servicePrincipal; - private Resource keyTabLocation; - private Subject serviceSubject; - private boolean debug = false; + private String servicePrincipal; + private Resource keyTabLocation; + private Subject serviceSubject; + private boolean debug = false; - /* (non-Javadoc) - * @see org.springframework.security.extensions.kerberos.KerberosTicketValidator#validateTicket(byte[]) - */ - public String validateTicket(byte[] token) { - String username = null; - try { - username = Subject.doAs(this.serviceSubject, new KerberosValidateAction(token)); - } catch (PrivilegedActionException e) { - throw new BadCredentialsException("Kerberos validation not succesfull", e); - } - return username; - } + /* (non-Javadoc) + * @see org.springframework.security.extensions.kerberos.KerberosTicketValidator#validateTicket(byte[]) + */ + public String validateTicket(byte[] token) { + String username = null; + try { + username = Subject.doAs(this.serviceSubject, new KerberosValidateAction(token)); + } catch (PrivilegedActionException e) { + throw new BadCredentialsException("Kerberos validation not succesfull", e); + } + return username; + } - /** The service principal of the application. - * For web apps this is HTTP/full-qualified-domain-name@DOMAIN. - * The keytab must contain the key for this principal. - * - * @param servicePrincipal service principal to use - * @see #setKeyTabLocation(Resource) - */ - public void setServicePrincipal(String servicePrincipal) { - this.servicePrincipal = servicePrincipal; - } + /** The service principal of the application. + * For web apps this is HTTP/full-qualified-domain-name@DOMAIN. + * The keytab must contain the key for this principal. + * + * @param servicePrincipal service principal to use + * @see #setKeyTabLocation(Resource) + */ + public void setServicePrincipal(String servicePrincipal) { + this.servicePrincipal = servicePrincipal; + } - /** - * The location of the keytab. You can use the normale Spring Resource - * prefixes like file: or classpath:, but as the - * file is later on read by JAAS, we cannot guarantee that classpath - * works in every environment, esp. not in Java EE application servers. You - * should use file: there. - * - * @param keyTabLocation The location where the keytab resides - */ - public void setKeyTabLocation(Resource keyTabLocation) { - this.keyTabLocation = keyTabLocation; - } - - /** Enables the debug mode of the JAAS Kerberos login module - * @param debug default is false - */ - public void setDebug(boolean debug) { - this.debug = debug; - } + /** + * The location of the keytab. You can use the normale Spring Resource + * prefixes like file: or classpath:, but as the + * file is later on read by JAAS, we cannot guarantee that classpath + * works in every environment, esp. not in Java EE application servers. You + * should use file: there. + * + * @param keyTabLocation The location where the keytab resides + */ + public void setKeyTabLocation(Resource keyTabLocation) { + this.keyTabLocation = keyTabLocation; + } - /* (non-Javadoc) - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws Exception { - Assert.notNull(this.servicePrincipal, "servicePrincipal must be specified"); - Assert.notNull(this.keyTabLocation, "keyTab must be specified"); - LoginConfig loginConfig = new LoginConfig(this.keyTabLocation.getURL().toExternalForm(), this.servicePrincipal, - this.debug); - Set princ = new HashSet(1); - princ.add(new KerberosPrincipal(this.servicePrincipal)); - Subject sub = new Subject(false, princ, new HashSet(), new HashSet()); - LoginContext lc = new LoginContext("", sub, null, loginConfig); - lc.login(); - this.serviceSubject = lc.getSubject(); - } + /** Enables the debug mode of the JAAS Kerberos login module + * @param debug default is false + */ + public void setDebug(boolean debug) { + this.debug = debug; + } - /** - * This class is needed, because the validation must run with previously generated JAAS subject - * which belongs to the service principal and was loaded out of the keytab during startup. - * - * @author Mike Wiesner - * @since 1.0 - */ - private static class KerberosValidateAction implements PrivilegedExceptionAction { - byte[] kerberosTicket; + /* (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + @Override + public void afterPropertiesSet() throws Exception { + Assert.notNull(this.servicePrincipal, "servicePrincipal must be specified"); + Assert.notNull(this.keyTabLocation, "keyTab must be specified"); + LoginConfig loginConfig = new LoginConfig(this.keyTabLocation.getURL().toExternalForm(), this.servicePrincipal, + this.debug); + Set princ = new HashSet(1); + princ.add(new KerberosPrincipal(this.servicePrincipal)); + Subject sub = new Subject(false, princ, new HashSet(), new HashSet()); + LoginContext lc = new LoginContext("", sub, null, loginConfig); + lc.login(); + this.serviceSubject = lc.getSubject(); + } - public KerberosValidateAction(byte[] kerberosTicket) { - this.kerberosTicket = kerberosTicket; - } + /** + * This class is needed, because the validation must run with previously generated JAAS subject + * which belongs to the service principal and was loaded out of the keytab during startup. + * + * @author Mike Wiesner + * @since 1.0 + */ + private static class KerberosValidateAction implements PrivilegedExceptionAction { + byte[] kerberosTicket; - @Override - public String run() throws Exception { - GSSContext context = GSSManager.getInstance().createContext((GSSCredential) null); - context.acceptSecContext(kerberosTicket, 0, kerberosTicket.length); - String user = context.getSrcName().toString(); - context.dispose(); - return user; - } + public KerberosValidateAction(byte[] kerberosTicket) { + this.kerberosTicket = kerberosTicket; + } - } + @Override + public String run() throws Exception { + GSSContext context = GSSManager.getInstance().createContext((GSSCredential) null); + context.acceptSecContext(kerberosTicket, 0, kerberosTicket.length); + String user = context.getSrcName().toString(); + context.dispose(); + return user; + } - /** - * Normally you need a JAAS config file in order to use the JAAS Kerberos Login Module, - * with this class it is not needed and you can have different configurations in one JVM. - * - * @author Mike Wiesner - * @since 1.0 - */ - private static class LoginConfig extends Configuration { - private String keyTabLocation; - private String servicePrincipalName; - private boolean debug; + } - public LoginConfig(String keyTabLocation, String servicePrincipalName, boolean debug) { - this.keyTabLocation = keyTabLocation; - this.servicePrincipalName = servicePrincipalName; - this.debug = debug; - } + /** + * Normally you need a JAAS config file in order to use the JAAS Kerberos Login Module, + * with this class it is not needed and you can have different configurations in one JVM. + * + * @author Mike Wiesner + * @since 1.0 + */ + private static class LoginConfig extends Configuration { + private String keyTabLocation; + private String servicePrincipalName; + private boolean debug; - @Override - public AppConfigurationEntry[] getAppConfigurationEntry(String name) { - HashMap options = new HashMap(); - options.put("useKeyTab", "true"); - options.put("keyTab", this.keyTabLocation); - options.put("principal", this.servicePrincipalName); - options.put("storeKey", "true"); - options.put("doNotPrompt", "true"); - if (this.debug) { - options.put("debug", "true"); - } - options.put("isInitiator", "false"); + public LoginConfig(String keyTabLocation, String servicePrincipalName, boolean debug) { + this.keyTabLocation = keyTabLocation; + this.servicePrincipalName = servicePrincipalName; + this.debug = debug; + } - return new AppConfigurationEntry[] { new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", - AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options), }; - } + @Override + public AppConfigurationEntry[] getAppConfigurationEntry(String name) { + HashMap options = new HashMap(); + options.put("useKeyTab", "true"); + options.put("keyTab", this.keyTabLocation); + options.put("principal", this.servicePrincipalName); + options.put("storeKey", "true"); + options.put("doNotPrompt", "true"); + if (this.debug) { + options.put("debug", "true"); + } + options.put("isInitiator", "false"); - } + return new AppConfigurationEntry[] { new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", + AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options), }; + } + + } } diff --git a/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/web/SpnegoAuthenticationProcessingFilter.java b/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/web/SpnegoAuthenticationProcessingFilter.java index 2f126b7..c5cf827 100644 --- a/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/web/SpnegoAuthenticationProcessingFilter.java +++ b/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/web/SpnegoAuthenticationProcessingFilter.java @@ -39,7 +39,7 @@ import org.springframework.web.filter.GenericFilterBean; * Parses the SPNEGO authentication Header, which was generated by the browser * and creates a {@link KerberosServiceRequestToken} out if it. It will then call the * {@link AuthenticationManager}. - * + * *

A typical Spring Security configuration might look like this:

*
  * <beans xmlns="http://www.springframework.org/schema/beans"
@@ -73,7 +73,7 @@ import org.springframework.web.filter.GenericFilterBean;
  *		</property>
  *		<property name="userDetailsService" ref="inMemoryUserDetailsService" />
  *	</bean>
- *	
+ *
  *	<bean id="inMemoryUserDetailsService"
  *		class="org.springframework.security.core.userdetails.memory.InMemoryDaoImpl">
  *		<property name="userProperties">
@@ -84,7 +84,7 @@ import org.springframework.web.filter.GenericFilterBean;
  *	</bean>
  * </beans>
  * 
- * + * * @author Mike Wiesner * @since 1.0 * @version $Id$ @@ -93,62 +93,62 @@ import org.springframework.web.filter.GenericFilterBean; */ public class SpnegoAuthenticationProcessingFilter extends GenericFilterBean { - private AuthenticationManager authenticationManager; + private AuthenticationManager authenticationManager; - @Override - public void doFilter(ServletRequest req, ServletResponse res, - FilterChain chain) throws IOException, ServletException { - HttpServletRequest request = (HttpServletRequest) req; - HttpServletResponse response = (HttpServletResponse) res; + @Override + public void doFilter(ServletRequest req, ServletResponse res, + FilterChain chain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) req; + HttpServletResponse response = (HttpServletResponse) res; - String header = request.getHeader("Authorization"); + String header = request.getHeader("Authorization"); - if ((header != null) && header.startsWith("Negotiate ")) { - if (logger.isDebugEnabled()) { - logger.debug("Received Negotiate Header for request "+ request.getRequestURL()+ ": " + header); - } - String base64Token = header.substring(10); - byte[] kerberosTicket = Base64.decodeBase64(base64Token.trim() - .getBytes()); - KerberosServiceRequestToken authenticationRequest = new KerberosServiceRequestToken( - kerberosTicket); - Authentication authentication; - try { - authentication = authenticationManager - .authenticate(authenticationRequest); - } catch (AuthenticationException e) { - // That shouldn't happen, as it is most likely a wrong configuration on the server side - logger.warn("Negotiate Header was invalid: "+header, e); - SecurityContextHolder.clearContext(); - response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - response.flushBuffer(); - return; - } - SecurityContextHolder.getContext() - .setAuthentication(authentication); - } + if ((header != null) && header.startsWith("Negotiate ")) { + if (logger.isDebugEnabled()) { + logger.debug("Received Negotiate Header for request "+ request.getRequestURL()+ ": " + header); + } + String base64Token = header.substring(10); + byte[] kerberosTicket = Base64.decodeBase64(base64Token.trim() + .getBytes()); + KerberosServiceRequestToken authenticationRequest = new KerberosServiceRequestToken( + kerberosTicket); + Authentication authentication; + try { + authentication = authenticationManager + .authenticate(authenticationRequest); + } catch (AuthenticationException e) { + // That shouldn't happen, as it is most likely a wrong configuration on the server side + logger.warn("Negotiate Header was invalid: "+header, e); + SecurityContextHolder.clearContext(); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + response.flushBuffer(); + return; + } + SecurityContextHolder.getContext() + .setAuthentication(authentication); + } - chain.doFilter(request, response); + chain.doFilter(request, response); - } - - /** - * The authentication manager for validating the ticket. - * - * @param authenticationManager - */ - public void setAuthenticationManager(AuthenticationManager authenticationManager) { - this.authenticationManager = authenticationManager; - } - - /* (non-Javadoc) - * @see org.springframework.web.filter.GenericFilterBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws ServletException { - super.afterPropertiesSet(); - Assert.notNull(this.authenticationManager, "authenticationManager must be specified"); - } + } + + /** + * The authentication manager for validating the ticket. + * + * @param authenticationManager + */ + public void setAuthenticationManager(AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + } + + /* (non-Javadoc) + * @see org.springframework.web.filter.GenericFilterBean#afterPropertiesSet() + */ + @Override + public void afterPropertiesSet() throws ServletException { + super.afterPropertiesSet(); + Assert.notNull(this.authenticationManager, "authenticationManager must be specified"); + } } diff --git a/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/web/SpnegoEntryPoint.java b/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/web/SpnegoEntryPoint.java index 782a18b..edc5ccb 100644 --- a/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/web/SpnegoEntryPoint.java +++ b/spring-security-kerberos-core/src/main/java/org/springframework/security/extensions/kerberos/web/SpnegoEntryPoint.java @@ -30,29 +30,29 @@ import org.springframework.security.web.AuthenticationEntryPoint; /** * Sends back a request for a Negotiate Authentication to the browser. - * + * * @author Mike Wiesner * @since 1.0 * @version $Id$ * @see SpnegoAuthenticationProcessingFilter */ public class SpnegoEntryPoint implements AuthenticationEntryPoint { - - private static final Log LOG = LogFactory.getLog(SpnegoEntryPoint.class); - /* (non-Javadoc) - * @see org.springframework.security.web.AuthenticationEntryPoint#commence(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.core.AuthenticationException) - */ - @Override - public void commence(HttpServletRequest request, HttpServletResponse response, - AuthenticationException ex) throws IOException, ServletException { + private static final Log LOG = LogFactory.getLog(SpnegoEntryPoint.class); + + /* (non-Javadoc) + * @see org.springframework.security.web.AuthenticationEntryPoint#commence(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.core.AuthenticationException) + */ + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, + AuthenticationException ex) throws IOException, ServletException { if (LOG.isDebugEnabled()) { - LOG.debug("Sending back Negotiate Header for request: "+request.getRequestURL()); + LOG.debug("Sending back Negotiate Header for request: "+request.getRequestURL()); } - response.addHeader("WWW-Authenticate", "Negotiate"); + response.addHeader("WWW-Authenticate", "Negotiate"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.flushBuffer(); - } + } } diff --git a/spring-security-kerberos-core/src/test/java/org/springframework/security/extensions/kerberos/KerberosServiceAuthenticationProviderTest.java b/spring-security-kerberos-core/src/test/java/org/springframework/security/extensions/kerberos/KerberosServiceAuthenticationProviderTest.java index b8fcefd..caf72d8 100644 --- a/spring-security-kerberos-core/src/test/java/org/springframework/security/extensions/kerberos/KerberosServiceAuthenticationProviderTest.java +++ b/spring-security-kerberos-core/src/test/java/org/springframework/security/extensions/kerberos/KerberosServiceAuthenticationProviderTest.java @@ -38,94 +38,94 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException; /** * Test class for {@link KerberosServiceAuthenticationProvider} - * + * * @author Mike Wiesner * @since 1.0 * @version $Id$ */ public class KerberosServiceAuthenticationProviderTest { - - private KerberosServiceAuthenticationProvider provider; - private KerberosTicketValidator ticketValidator; - private UserDetailsService userDetailsService; - - // data - private static final byte[] TEST_TOKEN = "TestToken".getBytes(); - private static final String TEST_USER = "Testuser@SPRINGSOURCE.ORG"; - private static final List AUTHORITY_LIST = AuthorityUtils.createAuthorityList("ROLE_ADMIN"); - private static final UserDetails USER_DETAILS = new User(TEST_USER, "empty", true, true, true,true, AUTHORITY_LIST); - private static final KerberosServiceRequestToken INPUT_TOKEN = new KerberosServiceRequestToken(TEST_TOKEN); - - @Before - public void before() { - // mocking - this.ticketValidator = mock(KerberosTicketValidator.class); - this.userDetailsService = mock(UserDetailsService.class); - this.provider = new KerberosServiceAuthenticationProvider(); - this.provider.setTicketValidator(this.ticketValidator); - this.provider.setUserDetailsService(this.userDetailsService); - } - - @Test - public void testEverythingWorks() throws Exception { - Authentication output = callProviderAndReturnUser(USER_DETAILS); - assertNotNull(output); - assertEquals(TEST_USER, output.getName()); - assertEquals(AUTHORITY_LIST, output.getAuthorities()); - assertEquals(USER_DETAILS, output.getPrincipal()); - } - - @Test(expected=DisabledException.class) - public void testUserIsDisabled() throws Exception { - User disabledUser = new User(TEST_USER, "empty", false, true, true,true, AUTHORITY_LIST); - callProviderAndReturnUser(disabledUser); - } - - @Test(expected=AccountExpiredException.class) - public void testUserAccountIsExpired() throws Exception { - User expiredUser = new User(TEST_USER, "empty", true, false, true,true, AUTHORITY_LIST); - callProviderAndReturnUser(expiredUser); - } - - @Test(expected=CredentialsExpiredException.class) - public void testUserCredentialsExpired() throws Exception { - User credExpiredUser = new User(TEST_USER, "empty", true, true, false ,true, AUTHORITY_LIST); - callProviderAndReturnUser(credExpiredUser); - } - - @Test(expected=LockedException.class) - public void testUserAccountLockedCredentialsExpired() throws Exception { - User lockedUser = new User(TEST_USER, "empty", true, true, true ,false, AUTHORITY_LIST); - callProviderAndReturnUser(lockedUser); - } - - @Test(expected=UsernameNotFoundException.class) - public void testUsernameNotFound() throws Exception { - // stubbing - when(ticketValidator.validateTicket(TEST_TOKEN)).thenReturn(TEST_USER); - when(userDetailsService.loadUserByUsername(TEST_USER)).thenThrow(new UsernameNotFoundException("")); - - // testing - provider.authenticate(INPUT_TOKEN); - } - - @Test(expected=BadCredentialsException.class) - public void testTicketValidationWrong() throws Exception { - // stubbing - when(ticketValidator.validateTicket(TEST_TOKEN)).thenThrow(new BadCredentialsException("")); - - // testing - provider.authenticate(INPUT_TOKEN); - } - - private Authentication callProviderAndReturnUser(UserDetails disabledUser) { - // stubbing - when(ticketValidator.validateTicket(TEST_TOKEN)).thenReturn(TEST_USER); - when(userDetailsService.loadUserByUsername(TEST_USER)).thenReturn(disabledUser); - - // testing - return provider.authenticate(INPUT_TOKEN); - } + private KerberosServiceAuthenticationProvider provider; + private KerberosTicketValidator ticketValidator; + private UserDetailsService userDetailsService; + + // data + private static final byte[] TEST_TOKEN = "TestToken".getBytes(); + private static final String TEST_USER = "Testuser@SPRINGSOURCE.ORG"; + private static final List AUTHORITY_LIST = AuthorityUtils.createAuthorityList("ROLE_ADMIN"); + private static final UserDetails USER_DETAILS = new User(TEST_USER, "empty", true, true, true,true, AUTHORITY_LIST); + private static final KerberosServiceRequestToken INPUT_TOKEN = new KerberosServiceRequestToken(TEST_TOKEN); + + @Before + public void before() { + // mocking + this.ticketValidator = mock(KerberosTicketValidator.class); + this.userDetailsService = mock(UserDetailsService.class); + this.provider = new KerberosServiceAuthenticationProvider(); + this.provider.setTicketValidator(this.ticketValidator); + this.provider.setUserDetailsService(this.userDetailsService); + } + + @Test + public void testEverythingWorks() throws Exception { + Authentication output = callProviderAndReturnUser(USER_DETAILS); + assertNotNull(output); + assertEquals(TEST_USER, output.getName()); + assertEquals(AUTHORITY_LIST, output.getAuthorities()); + assertEquals(USER_DETAILS, output.getPrincipal()); + } + + @Test(expected=DisabledException.class) + public void testUserIsDisabled() throws Exception { + User disabledUser = new User(TEST_USER, "empty", false, true, true,true, AUTHORITY_LIST); + callProviderAndReturnUser(disabledUser); + } + + @Test(expected=AccountExpiredException.class) + public void testUserAccountIsExpired() throws Exception { + User expiredUser = new User(TEST_USER, "empty", true, false, true,true, AUTHORITY_LIST); + callProviderAndReturnUser(expiredUser); + } + + @Test(expected=CredentialsExpiredException.class) + public void testUserCredentialsExpired() throws Exception { + User credExpiredUser = new User(TEST_USER, "empty", true, true, false ,true, AUTHORITY_LIST); + callProviderAndReturnUser(credExpiredUser); + } + + @Test(expected=LockedException.class) + public void testUserAccountLockedCredentialsExpired() throws Exception { + User lockedUser = new User(TEST_USER, "empty", true, true, true ,false, AUTHORITY_LIST); + callProviderAndReturnUser(lockedUser); + } + + @Test(expected=UsernameNotFoundException.class) + public void testUsernameNotFound() throws Exception { + // stubbing + when(ticketValidator.validateTicket(TEST_TOKEN)).thenReturn(TEST_USER); + when(userDetailsService.loadUserByUsername(TEST_USER)).thenThrow(new UsernameNotFoundException("")); + + // testing + provider.authenticate(INPUT_TOKEN); + } + + + @Test(expected=BadCredentialsException.class) + public void testTicketValidationWrong() throws Exception { + // stubbing + when(ticketValidator.validateTicket(TEST_TOKEN)).thenThrow(new BadCredentialsException("")); + + // testing + provider.authenticate(INPUT_TOKEN); + } + + private Authentication callProviderAndReturnUser(UserDetails disabledUser) { + // stubbing + when(ticketValidator.validateTicket(TEST_TOKEN)).thenReturn(TEST_USER); + when(userDetailsService.loadUserByUsername(TEST_USER)).thenReturn(disabledUser); + + // testing + return provider.authenticate(INPUT_TOKEN); + } } diff --git a/spring-security-kerberos-core/src/test/java/org/springframework/security/extensions/kerberos/web/SpnegoAuthenticationProcessingFilterTest.java b/spring-security-kerberos-core/src/test/java/org/springframework/security/extensions/kerberos/web/SpnegoAuthenticationProcessingFilterTest.java index 8efbaa2..b0050f1 100644 --- a/spring-security-kerberos-core/src/test/java/org/springframework/security/extensions/kerberos/web/SpnegoAuthenticationProcessingFilterTest.java +++ b/spring-security-kerberos-core/src/test/java/org/springframework/security/extensions/kerberos/web/SpnegoAuthenticationProcessingFilterTest.java @@ -36,7 +36,7 @@ import org.springframework.security.extensions.kerberos.KerberosServiceRequestTo /** * Test class for {@link SpnegoAuthenticationProcessingFilter} - * + * * @author Mike Wiesner * @since 1.0 * @version $Id$ @@ -45,72 +45,72 @@ public class SpnegoAuthenticationProcessingFilterTest { - private SpnegoAuthenticationProcessingFilter filter; - private AuthenticationManager authenticationManager; - private HttpServletRequest request; - private HttpServletResponse response; - private FilterChain chain; - - // data - private static final byte[] TEST_TOKEN = "TestToken".getBytes(); - private static final String TEST_TOKEN_BASE64 = "VGVzdFRva2Vu"; - private static final Authentication AUTHENTICATION = new KerberosServiceRequestToken("test", - AuthorityUtils.createAuthorityList("ROLE_ADMIN"), TEST_TOKEN); - private static final String HEADER = "Authorization"; - private static final String TOKEN_PREFIX = "Negotiate "; - + private SpnegoAuthenticationProcessingFilter filter; + private AuthenticationManager authenticationManager; + private HttpServletRequest request; + private HttpServletResponse response; + private FilterChain chain; - @Before - public void before() { - // mocking - authenticationManager = mock(AuthenticationManager.class); - filter = new SpnegoAuthenticationProcessingFilter(); - filter.setAuthenticationManager(authenticationManager); - request = mock(HttpServletRequest.class); - response = mock(HttpServletResponse.class); - chain = mock(FilterChain.class); - } + // data + private static final byte[] TEST_TOKEN = "TestToken".getBytes(); + private static final String TEST_TOKEN_BASE64 = "VGVzdFRva2Vu"; + private static final Authentication AUTHENTICATION = new KerberosServiceRequestToken("test", + AuthorityUtils.createAuthorityList("ROLE_ADMIN"), TEST_TOKEN); + private static final String HEADER = "Authorization"; + private static final String TOKEN_PREFIX = "Negotiate "; + + + @Before + public void before() { + // mocking + authenticationManager = mock(AuthenticationManager.class); + filter = new SpnegoAuthenticationProcessingFilter(); + filter.setAuthenticationManager(authenticationManager); + request = mock(HttpServletRequest.class); + response = mock(HttpServletResponse.class); + chain = mock(FilterChain.class); + } + + @Test + public void testEverythingWorks() throws Exception { + // stubbing + when(request.getHeader(HEADER)).thenReturn(TOKEN_PREFIX+TEST_TOKEN_BASE64); + when(authenticationManager.authenticate(new KerberosServiceRequestToken(TEST_TOKEN))).thenReturn(AUTHENTICATION); + + // testing + filter.doFilter(request, response, chain); + verify(chain).doFilter(request, response); + assertEquals(AUTHENTICATION, SecurityContextHolder.getContext().getAuthentication()); + } + + @Test + public void testNoHeader() throws Exception { + filter.doFilter(request, response, chain); + // If the header is not present, the filter is not allowed to call authenticate() + verify(authenticationManager, never()).authenticate(any(Authentication.class)); + // chain should go on + verify(chain).doFilter(request, response); + assertEquals(null, SecurityContextHolder.getContext().getAuthentication()); + } + + @Test + public void testAuthenticationFails() throws Exception { + // stubbing + when(request.getHeader(HEADER)).thenReturn(TOKEN_PREFIX+TEST_TOKEN_BASE64); + when(authenticationManager.authenticate(any(Authentication.class))).thenThrow(new BadCredentialsException("")); + + // testing + filter.doFilter(request, response, chain); + // chain should stop here and it should send back a 500 + // future version should call some error handler + verify(chain, never()).doFilter(any(ServletRequest.class), any(ServletResponse.class)); + verify(response).setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + + @After + public void after() { + SecurityContextHolder.clearContext(); + } - @Test - public void testEverythingWorks() throws Exception { - // stubbing - when(request.getHeader(HEADER)).thenReturn(TOKEN_PREFIX+TEST_TOKEN_BASE64); - when(authenticationManager.authenticate(new KerberosServiceRequestToken(TEST_TOKEN))).thenReturn(AUTHENTICATION); - - // testing - filter.doFilter(request, response, chain); - verify(chain).doFilter(request, response); - assertEquals(AUTHENTICATION, SecurityContextHolder.getContext().getAuthentication()); - } - - @Test - public void testNoHeader() throws Exception { - filter.doFilter(request, response, chain); - // If the header is not present, the filter is not allowed to call authenticate() - verify(authenticationManager, never()).authenticate(any(Authentication.class)); - // chain should go on - verify(chain).doFilter(request, response); - assertEquals(null, SecurityContextHolder.getContext().getAuthentication()); - } - - @Test - public void testAuthenticationFails() throws Exception { - // stubbing - when(request.getHeader(HEADER)).thenReturn(TOKEN_PREFIX+TEST_TOKEN_BASE64); - when(authenticationManager.authenticate(any(Authentication.class))).thenThrow(new BadCredentialsException("")); - - // testing - filter.doFilter(request, response, chain); - // chain should stop here and it should send back a 500 - // future version should call some error handler - verify(chain, never()).doFilter(any(ServletRequest.class), any(ServletResponse.class)); - verify(response).setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } - - @After - public void after() { - SecurityContextHolder.clearContext(); - } - } diff --git a/spring-security-kerberos-core/src/test/java/org/springframework/security/extensions/kerberos/web/SpnegoEntryPointTest.java b/spring-security-kerberos-core/src/test/java/org/springframework/security/extensions/kerberos/web/SpnegoEntryPointTest.java index 8d0af86..14fe9cb 100644 --- a/spring-security-kerberos-core/src/test/java/org/springframework/security/extensions/kerberos/web/SpnegoEntryPointTest.java +++ b/spring-security-kerberos-core/src/test/java/org/springframework/security/extensions/kerberos/web/SpnegoEntryPointTest.java @@ -23,23 +23,23 @@ import org.junit.Test; /** * Test class for {@link SpnegoEntryPoint} - * + * * @author Mike Wiesner * @since 1.0 * @version $Id$ */ public class SpnegoEntryPointTest { - - private SpnegoEntryPoint entryPoint = new SpnegoEntryPoint(); - - @Test - public void testEntryPointOk() throws Exception { - HttpServletResponse response = mock(HttpServletResponse.class); - - entryPoint.commence(null, response, null); - - verify(response).addHeader("WWW-Authenticate", "Negotiate"); - verify(response).setStatus(HttpServletResponse.SC_UNAUTHORIZED); - } + + private SpnegoEntryPoint entryPoint = new SpnegoEntryPoint(); + + @Test + public void testEntryPointOk() throws Exception { + HttpServletResponse response = mock(HttpServletResponse.class); + + entryPoint.commence(null, response, null); + + verify(response).addHeader("WWW-Authenticate", "Negotiate"); + verify(response).setStatus(HttpServletResponse.SC_UNAUTHORIZED); + } }