package com.vtence.molecule.session; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import java.util.Base64; import static com.vtence.molecule.session.SessionMatchers.sameSessionDataAs; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; public class SecureSessionEncoderTest { String key = "secret"; SecureSessionEncoder encoder = new SecureSessionEncoder(key); public @Rule ExpectedException error = ExpectedException.none(); @Test public void decodesSessionWithIntegrityHash() throws Exception { Session data = new Session("42"); data.put("username", "Joe"); String secure = encoder.encode(data); Session decoded = encoder.decode(secure); assertThat("decoded session", decoded, sameSessionDataAs(data)); } @Test public void ignoresTamperedWithEncodedContent() throws Exception { Session data = new Session("42"); data.put("username", "Joe"); String secure = encoder.encode(data); String tampered = encodeInBase64("tampered content") + "--" + digestPartOf(secure); assertThat("tampered session", encoder.decode(tampered), nullValue()); } @Test public void ignoresContentMissingIntegrityHash() throws Exception { Session data = new Session("42"); data.put("username", "Joe"); String secure = encoder.encode(data); String contentOnly = contentPartOf(secure); assertThat("missing hash", encoder.decode(contentOnly), nullValue()); } @Test public void ignoresEmptyContent() throws Exception { assertThat("empty content", encoder.decode(""), nullValue()); } @Test public void allowsGracefulSecretRotation() throws Exception { Session data = new Session("42"); data.put("username", "Joe"); encoder = new SecureSessionEncoder("secret-1"); String encoded = encoder.encode(data); encoder = new SecureSessionEncoder("secret-2").acceptAlternateKeys("secret-1"); Session decoded = encoder.decode(encoded); assertThat("rotation #1", decoded, sameSessionDataAs(data)); encoded = encoder.encode(data); encoder = new SecureSessionEncoder("secret-3").acceptAlternateKeys("secret-2"); decoded = encoder.decode(encoded); assertThat("rotation #2", decoded, sameSessionDataAs(data)); } private String contentPartOf(String secure) { String[] parts = secure.split("--"); return parts[0]; } private String digestPartOf(String secure) { String[] parts = secure.split("--"); return parts[1]; } private String encodeInBase64(String s) { return Base64.getMimeEncoder().encodeToString(s.getBytes()); } }