Skip to content

Commit

Permalink
chore: fix the JaasAuthProvider post jetty upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
agavra committed Feb 3, 2022
1 parent 9b8eb00 commit 8432d87
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 48 deletions.
Expand Up @@ -16,42 +16,33 @@
package io.confluent.ksql.api.auth;

import java.io.IOException;
import java.util.Objects;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.TextOutputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.eclipse.jetty.jaas.callback.DefaultCallbackHandler;
import org.eclipse.jetty.jaas.callback.ObjectCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class BasicCallbackHandler implements CallbackHandler {
public class BasicCallbackHandler extends DefaultCallbackHandler {

private static final Logger log = LoggerFactory.getLogger(BasicCallbackHandler.class);

private final String username;
private final String password;

BasicCallbackHandler(final String username, final String password) {
this.username = Objects.requireNonNull(username, "username");
this.password = Objects.requireNonNull(password, "password");
}

@Override
public void handle(final Callback[] callbacks)
throws IOException, UnsupportedCallbackException {
for (final Callback callback : callbacks) {
if (callback instanceof NameCallback) {
final NameCallback nc = (NameCallback) callback;
nc.setName(username);
nc.setName(getUserName());
} else if (callback instanceof ObjectCallback) {
final ObjectCallback oc = (ObjectCallback)callback;
oc.setObject(password);
oc.setObject(getCredential());
} else if (callback instanceof PasswordCallback) {
final PasswordCallback pc = (PasswordCallback) callback;
pc.setPassword(password.toCharArray());
pc.setPassword(((String) getCredential()).toCharArray());
} else if (callback instanceof TextOutputCallback) {
final TextOutputCallback toc = (TextOutputCallback) callback;
switch (toc.getMessageType()) {
Expand All @@ -73,22 +64,4 @@ public void handle(final Callback[] callbacks)
}
}
}

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final BasicCallbackHandler that = (BasicCallbackHandler) o;
return username.equals(that.username)
&& password.equals(that.password);
}

@Override
public int hashCode() {
return Objects.hash(username, password);
}
}
Expand Up @@ -34,6 +34,8 @@
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import org.apache.commons.collections4.CollectionUtils;
import org.eclipse.jetty.jaas.JAASLoginService;
import org.eclipse.jetty.server.UserIdentity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -107,36 +109,38 @@ private void getUser(
final List<String> allowedRoles,
final Promise<User> promise
) {
final LoginContext lc;
final JAASLoginService login = new JAASLoginService();
login.setCallbackHandlerClass(BasicCallbackHandler.class.getName());
login.setLoginModuleName(contextName);

try {
lc = loginContextSupplier.get(contextName, new BasicCallbackHandler(username, password));
} catch (LoginException | SecurityException e) {
log.error("Failed to create LoginContext. " + e.getMessage());
promise.fail("Failed to create LoginContext.");
return;
login.start();
} catch (final Exception e) {
log.error("Could not start login service.", e);
promise.fail("Could not start login service.");
}

try {
lc.login();
} catch (LoginException le) {
log.error("Failed to log in. " + le.getMessage());
final UserIdentity user = login.login(username, password, null);

if (user == null) {
log.error("Failed to log in. ");
promise.fail("Failed to log in: Invalid username/password.");
return;
}

// We do the actual authorization here not in the User class
final boolean authorized = validateRoles(lc, allowedRoles);
final boolean authorized = validateRoles(user, allowedRoles);

promise.complete(new JaasUser(username, authorized));
}

private static boolean validateRoles(final LoginContext lc, final List<String> allowedRoles) {
private static boolean validateRoles(final UserIdentity ui, final List<String> allowedRoles) {
if (allowedRoles.contains("*")) {
// all users allowed
return true;
}

final Set<String> userRoles = lc.getSubject().getPrincipals().stream()
final Set<String> userRoles = ui.getSubject().getPrincipals().stream()
.map(Principal::getName)
.collect(Collectors.toSet());
return !CollectionUtils.intersection(userRoles, allowedRoles).isEmpty();
Expand Down
Expand Up @@ -46,7 +46,9 @@ public class BasicCallbackHandlerTest {

@Before
public void setUp() {
callbackHandler = new BasicCallbackHandler(USERNAME, PASSWORD);
callbackHandler = new BasicCallbackHandler();
callbackHandler.setUserName(USERNAME);
callbackHandler.setCredential(PASSWORD);
}

@Test
Expand Down
Expand Up @@ -81,12 +81,15 @@ public class JaasAuthProviderTest {

@Before
public void setUp() throws Exception {
final BasicCallbackHandler callbackHandler = new BasicCallbackHandler();
callbackHandler.setUserName(USERNAME);
callbackHandler.setCredential(PASSWORD);

handleAsyncExecution();
when(config.getString(KsqlRestConfig.AUTHENTICATION_REALM_CONFIG)).thenReturn(REALM);
when(authInfo.getString("username")).thenReturn(USERNAME);
when(authInfo.getString("password")).thenReturn(PASSWORD);
when(loginContextSupplier.get(REALM, new BasicCallbackHandler(USERNAME, PASSWORD)))
.thenReturn(loginContext);
when(loginContextSupplier.get(REALM, callbackHandler)).thenReturn(loginContext);
when(loginContext.getSubject()).thenReturn(subject);

authProvider = new JaasAuthProvider(server, config, loginContextSupplier);
Expand Down

0 comments on commit 8432d87

Please sign in to comment.