Skip to content

Commit

Permalink
Merge pull request #871 from danibusu/login-behavior
Browse files Browse the repository at this point in the history
update gateway login challenge behavior
  • Loading branch information
David Witherspoon committed Mar 3, 2017
2 parents 9e75852 + 619474c commit 5e29765
Show file tree
Hide file tree
Showing 28 changed files with 1,641 additions and 372 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ public int getId() {

@Override
public String getAuthorizationMode() {
return realm.getAuthenticationContext().getAuthorizationMode();
return realm.getAuthenticationContext() == null ? null : realm.getAuthenticationContext().getAuthorizationMode();
}

@Override
public String getSessionTimeout() {
return realm.getAuthenticationContext().getSessionTimeout();
return realm.getAuthenticationContext() == null ? null : realm.getAuthenticationContext().getSessionTimeout();
}

@Override
Expand Down Expand Up @@ -98,22 +98,25 @@ public String getDescription() {

@Override
public String getHTTPChallengeScheme() {
return realm.getAuthenticationContext().getHttpChallengeScheme();
return realm.getAuthenticationContext() == null ? null : realm.getAuthenticationContext().getHttpChallengeScheme();
}

@Override
public String getHTTPCookieNames() {
return makeJSONArray(realm.getAuthenticationContext().getHttpCookieNames());
return makeJSONArray(
realm.getAuthenticationContext() == null ? null : realm.getAuthenticationContext().getHttpCookieNames());
}

@Override
public String getHTTPHeaders() {
return makeJSONArray(realm.getAuthenticationContext().getHttpHeaders());
return makeJSONArray(
realm.getAuthenticationContext() == null ? null : realm.getAuthenticationContext().getHttpHeaders());
}

@Override
public String getHTTPQueryParameters() {
return makeJSONArray(realm.getAuthenticationContext().getHttpQueryParameters());
return makeJSONArray(
realm.getAuthenticationContext() == null ? null : realm.getAuthenticationContext().getHttpQueryParameters());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ public class JmxRoundTripLatencyIT {
.realm()
.name("jmxrealm")
.description("realm for jmx")
.httpChallengeScheme("Application Basic")
.loginModule()
.type("class:org.kaazing.gateway.management.test.util.TestLoginModule")
.success("requisite")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ public class JmxSessionIT {
.realm()
.name("jmxrealm")
.description("realm for jmx")
.httpChallengeScheme("Application Basic")
.loginModule()
.type("class:org.kaazing.gateway.management.test.util.TestLoginModule")
.success("requisite")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ protected GatewayConfiguration getGatewayConfiguration() {
.realm()
.name("demo")
.description("Kaazing WebSocket Gateway Demo")
.httpChallengeScheme("Application Token")
.httpQueryParameter("token")
.userPrincipalClass("org.kaazing.gateway.management.test.util.TokenCustomLoginModule$RolePrincipal")
.userPrincipalClass("org.kaazing.gateway.management.test.util.TokenCustomLoginModule$UserPrincipal")
Expand All @@ -121,7 +120,6 @@ protected GatewayConfiguration getGatewayConfiguration() {
.realm()
.name("jmxrealm")
.description("realm for jmx")
.httpChallengeScheme("Application Basic")
.loginModule()
.type("class:org.kaazing.gateway.management.test.util.TestLoginModule")
.success("required")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ protected GatewayConfiguration getGatewayConfiguration() {
.realm()
.name("demo")
.description("Kaazing WebSocket Gateway Demo")
.httpChallengeScheme("Application Token")
.httpQueryParameter("token")
// Specify supertypes (an implemented interface) for the principles, this should work
.userPrincipalClass("org.kaazing.gateway.management.test.util.TokenCustomLoginModule$RoleInterface")
Expand All @@ -76,7 +75,6 @@ protected GatewayConfiguration getGatewayConfiguration() {
.realm()
.name("jmxrealm")
.description("realm for jmx")
.httpChallengeScheme("Application Basic")
.loginModule()
.type("class:org.kaazing.gateway.management.test.util.TestLoginModule")
.success("required")
Expand Down
5 changes: 5 additions & 0 deletions security/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@
<artifactId>jmock-legacy</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.kaazing</groupId>
<artifactId>netx.data</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,33 @@
*/
package org.kaazing.gateway.security.auth;

import java.io.IOException;
import java.util.Map;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

import org.kaazing.gateway.server.spi.security.LoginResult;
import org.kaazing.gateway.server.spi.security.LoginResultCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class BaseStateDrivenLoginModule implements LoginModule {

public static final Logger LOGGER = LoggerFactory.getLogger(BaseStateDrivenLoginModule.class);

protected enum State { INITIALIZE_REQUIRED, INITIALIZE_COMPLETE, LOGIN_COMPLETE, COMMIT_COMPLETE }

protected State state = State.INITIALIZE_REQUIRED;
protected Subject subject;
protected CallbackHandler handler;
protected Map<String, ?> sharedState;
protected Map<String, ?> options;
protected LoginResult loginResult;

@Override
public void initialize(Subject subject,
Expand All @@ -42,7 +53,7 @@ public void initialize(Subject subject,
this.sharedState = sharedState;
this.options = options;
this.state = State.INITIALIZE_COMPLETE;

this.loginResult = getLoginResultFromCallback();
}

@Override
Expand Down Expand Up @@ -141,5 +152,18 @@ public boolean logout() throws LoginException {

protected abstract boolean doLogout() throws LoginException;

private LoginResult getLoginResultFromCallback() {
LoginResultCallback loginResultCallback = new LoginResultCallback();

try {
this.handler.handle(new Callback[]{loginResultCallback});
} catch (IOException | UnsupportedCallbackException e) {
LOGGER.debug("Unable to handle LoginResultCallback", e);
return null;
}

return loginResultCallback.getLoginResult();
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,26 @@ public void initialize(Subject subject, CallbackHandler callbackHandler,
protected boolean doLogin() throws LoginException {

if (!authenticationSchemeIsBasic()) {
return true;
throw new LoginException("Only able to handle Basic authentication scheme");
}

// always challenge for basic authentication
if (loginResult == null) {
LoginException le = new LoginException("Missing login result");
if (debug) {
LOG.debug("[BasicLoginModule] Unable to perform authentication", le);
}
throw le;
}
loginResult.challenge();

if (tryFirstToken) {
try {
attemptAuthenticate(true);
return true;
} catch (LoginException le) {
if (debug) {
LOG.debug("[BasicLoginModule] " + "reading from shared state failed: " + le.getMessage());
LOG.debug("[BasicLoginModule] reading from shared state failed: ", le);
}
}
}
Expand All @@ -81,28 +91,23 @@ protected boolean doLogin() throws LoginException {
} catch (LoginException loginException) {
cleanState();
if (debug) {
LOG.debug("[BasicLoginModule] " + "regular authentication failed: " + loginException.getMessage());
LOG.debug("[BasicLoginModule] regular authentication failed: ", loginException);
}
throw loginException;
}

return false;
}

private boolean authenticationSchemeIsBasic() throws LoginException {
final AuthenticationTokenCallback authenticationTokenCallback = new AuthenticationTokenCallback();

try {
handler.handle(new Callback[]{authenticationTokenCallback});
} catch (IOException e) {
if (LOG.isTraceEnabled()) {
LOG.trace("Encountered exception handling authenticationTokenCallback.", e);
}
return false;
} catch (UnsupportedCallbackException e) {
if (LOG.isTraceEnabled()) {
LOG.trace("UnsupportedCallbackException handling authenticationTokenCallback.");
} catch (IOException | UnsupportedCallbackException e) {
if (debug) {
LOG.debug("Unable to handle AuthenticationTokenCallback.", e);
}
return false;
throw wrapInLoginException(e);
}

return authenticationTokenCallback.getAuthenticationToken() != null &&
Expand Down Expand Up @@ -142,33 +147,28 @@ private void attemptAuthenticate(boolean useSharedState) throws LoginException {
} else {
throw new LoginException("Syntax error while decoding HTTP Basic Authentication token.");
}
} catch (Throwable e) {
} catch (Exception e) {
if (debug) {
LOG.debug("Exception decoding HTTP Basic Authentication token", e);
}
cleanState();
throw (LoginException) (new LoginException(e.getMessage())).initCause(e);
throw wrapInLoginException(e);
}
}

private String getBasicAuthToken(boolean useSharedState) {
private String getBasicAuthToken(boolean useSharedState) throws LoginException {
if (useSharedState) {
return (String) ((Map) sharedState).get(KAAZING_TOKEN_KEY);
}

final AuthenticationTokenCallback authenticationTokenCallback = new AuthenticationTokenCallback();
try {
handler.handle(new Callback[]{authenticationTokenCallback});
} catch (IOException e) {
if (LOG.isTraceEnabled()) {
LOG.trace("Encountered exception handling authenticationTokenCallback.", e);
}
return null;
} catch (UnsupportedCallbackException e) {
if (LOG.isTraceEnabled()) {
LOG.trace("UnsupportedCallbackException handling authenticationTokenCallback.");
} catch (IOException | UnsupportedCallbackException e) {
if (debug) {
LOG.debug("Unable to handle AuthenticationTokenCallback.", e);
}
return null;
throw wrapInLoginException(e);
}

AuthenticationToken authToken = authenticationTokenCallback.getAuthenticationToken();
Expand Down Expand Up @@ -197,6 +197,7 @@ protected boolean doLogout() throws LoginException {
return true;
}



private LoginException wrapInLoginException(Exception e) {
return (LoginException) new LoginException(e.getMessage()).initCause(e);
}
}
Loading

0 comments on commit 5e29765

Please sign in to comment.