1 /** 2 * Waffle (https://github.com/dblock/waffle) 3 * 4 * Copyright (c) 2010 - 2015 Application Security, Inc. 5 * 6 * All rights reserved. This program and the accompanying materials 7 * are made available under the terms of the Eclipse Public License v1.0 8 * which accompanies this distribution, and is available at 9 * http://www.eclipse.org/legal/epl-v10.html 10 * 11 * Contributors: 12 * Application Security, Inc. 13 */ 14 package waffle.shiro.negotiate; 15 16 import org.apache.shiro.authc.AuthenticationInfo; 17 import org.apache.shiro.authc.AuthenticationToken; 18 import org.apache.shiro.authc.pam.AbstractAuthenticationStrategy; 19 import org.apache.shiro.realm.Realm; 20 21 /** 22 * Custom authentication strategy for the negotiate logic required for SSO/Negotiate auth realm 23 * {@link NegotiateAuthenticationRealm}. When the negotiate logic is executing, one of more round trips with the client 24 * occur. When the {@link NegotiateAuthenticationRealm} determines another handshake is needed, it throws the exception: 25 * {@link AuthenticationInProgressException}. This custom strategy detects this exception, and immediately re-throws it 26 * so classes higher up in the call stack will allow the handshake to proceed. Without this added logic, the handshake 27 * could be halted after the first connection by the existing error handling. <br> 28 * <br> 29 * This strategy is needed when using {@link NegotiateAuthenticationFilter} and more than one realm is configured in 30 * shiro.ini. If only one realm is defined, the current error handling in 31 * {@link org.apache.shiro.authc.pam.ModularRealmAuthenticator#doSingleRealmAuthentication(org.apache.shiro.realm.Realm, org.apache.shiro.authc.AuthenticationToken)} 32 * works fine without requiring this strategy. However, the current error handling in 33 * {@link org.apache.shiro.authc.pam.ModularRealmAuthenticator#doMultiRealmAuthentication(java.util.Collection, org.apache.shiro.authc.AuthenticationToken)} 34 * does require the {@link NegotiateAuthenticationStrategy} to ensure negotiate 'continue' calls will proceed. So for 35 * now, the most reliable approach is to use this strategy. 36 * 37 * @author Dan Rollo Date: 3/18/13 Time: 3:31 PM 38 * @see NegotiateAuthenticationStrategy#afterAttempt(org.apache.shiro.realm.Realm, 39 * org.apache.shiro.authc.AuthenticationToken, org.apache.shiro.authc.AuthenticationInfo, 40 * org.apache.shiro.authc.AuthenticationInfo, Throwable) 41 */ 42 public class NegotiateAuthenticationStrategy extends AbstractAuthenticationStrategy { 43 44 /** 45 * When the negotiate logic is executing, one of more round trips with the client occur. When the 46 * {@link NegotiateAuthenticationRealm negotiate realm} determines another handshake is needed, it throws the 47 * exception: {@link AuthenticationInProgressException}. This custom strategy detects this exception, and 48 * immediately re-throws it so classes higher up in the call stack will allow the handshake to proceed. Without this 49 * added logic, the handshake would be halted after the first connection by the existing error handling. 50 * 51 * {@inheritDoc} 52 */ 53 @Override 54 public AuthenticationInfo afterAttempt(final Realm realm, final AuthenticationToken token, 55 final AuthenticationInfo singleRealmInfo, final AuthenticationInfo aggregateInfo, final Throwable t) { 56 57 if (realm instanceof NegotiateAuthenticationRealm && t instanceof AuthenticationInProgressException) { 58 // propagate exception upward as is, to signal continue is needed 59 throw (AuthenticationInProgressException) t; 60 } 61 62 return super.afterAttempt(realm, token, singleRealmInfo, aggregateInfo, t); 63 } 64 }