diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/sasl/ClientCallbackHandler.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/sasl/ClientCallbackHandler.java new file mode 100644 index 0000000000..d73f2a2708 --- /dev/null +++ b/core-java-modules/core-java-security/src/main/java/com/baeldung/sasl/ClientCallbackHandler.java @@ -0,0 +1,29 @@ +package com.baeldung.sasl; + +import java.io.IOException; + +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.UnsupportedCallbackException; +import javax.security.sasl.RealmCallback; + +public class ClientCallbackHandler implements CallbackHandler { + + @Override + public void handle(Callback[] cbs) throws IOException, UnsupportedCallbackException { + for (Callback cb : cbs) { + if (cb instanceof NameCallback) { + NameCallback nc = (NameCallback) cb; + nc.setName("username"); + } else if (cb instanceof PasswordCallback) { + PasswordCallback pc = (PasswordCallback) cb; + pc.setPassword("password".toCharArray()); + } else if (cb instanceof RealmCallback) { + RealmCallback rc = (RealmCallback) cb; + rc.setText("myServer"); + } + } + } +} diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/sasl/ServerCallbackHandler.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/sasl/ServerCallbackHandler.java new file mode 100644 index 0000000000..3e071d68cc --- /dev/null +++ b/core-java-modules/core-java-security/src/main/java/com/baeldung/sasl/ServerCallbackHandler.java @@ -0,0 +1,34 @@ +package com.baeldung.sasl; + +import java.io.IOException; + +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.UnsupportedCallbackException; +import javax.security.sasl.AuthorizeCallback; +import javax.security.sasl.RealmCallback; + +public class ServerCallbackHandler implements CallbackHandler { + + @Override + public void handle(Callback[] cbs) throws IOException, UnsupportedCallbackException { + for (Callback cb : cbs) { + if (cb instanceof AuthorizeCallback) { + AuthorizeCallback ac = (AuthorizeCallback) cb; + ac.setAuthorized(true); + } else if (cb instanceof NameCallback) { + NameCallback nc = (NameCallback) cb; + nc.setName("username"); + + } else if (cb instanceof PasswordCallback) { + PasswordCallback pc = (PasswordCallback) cb; + pc.setPassword("password".toCharArray()); + } else if (cb instanceof RealmCallback) { + RealmCallback rc = (RealmCallback) cb; + rc.setText("myServer"); + } + } + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/sasl/SaslUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/sasl/SaslUnitTest.java new file mode 100644 index 0000000000..6601654781 --- /dev/null +++ b/core-java-modules/core-java-security/src/test/java/com/baeldung/sasl/SaslUnitTest.java @@ -0,0 +1,76 @@ +package com.baeldung.sasl; + +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslClient; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class SaslUnitTest { + + private static final String MECHANISM = "DIGEST-MD5"; + private static final String SERVER_NAME = "myServer"; + private static final String PROTOCOL = "myProtocol"; + private static final String AUTHORIZATION_ID = null; + private static final String QOP_LEVEL = "auth-conf"; + + private SaslServer saslServer; + private SaslClient saslClient; + + @Before + public void setUp() throws SaslException { + + ServerCallbackHandler serverHandler = new ServerCallbackHandler(); + ClientCallbackHandler clientHandler = new ClientCallbackHandler(); + + Map props = new HashMap<>(); + props.put(Sasl.QOP, QOP_LEVEL); + + saslServer = Sasl.createSaslServer(MECHANISM, PROTOCOL, SERVER_NAME, props, serverHandler); + saslClient = Sasl.createSaslClient(new String[] { MECHANISM }, AUTHORIZATION_ID, PROTOCOL, SERVER_NAME, props, clientHandler); + + } + + @Test + public void givenHandlers_whenStarted_thenAutenticationWorks() throws SaslException { + + byte[] challenge; + byte[] response; + + challenge = saslServer.evaluateResponse(new byte[0]); + response = saslClient.evaluateChallenge(challenge); + + challenge = saslServer.evaluateResponse(response); + response = saslClient.evaluateChallenge(challenge); + + assertTrue(saslServer.isComplete()); + assertTrue(saslClient.isComplete()); + + String qop = (String) saslClient.getNegotiatedProperty(Sasl.QOP); + assertEquals("auth-conf", qop); + + byte[] outgoing = "Baeldung".getBytes(); + byte[] secureOutgoing = saslClient.wrap(outgoing, 0, outgoing.length); + + byte[] secureIncoming = secureOutgoing; + byte[] incoming = saslServer.unwrap(secureIncoming, 0, secureIncoming.length); + assertEquals("Baeldung", new String(incoming, StandardCharsets.UTF_8)); + } + + @After + public void tearDown() throws SaslException { + saslClient.dispose(); + saslServer.dispose(); + } + +}