package examples.session;
import com.vtence.molecule.WebServer;
import com.vtence.molecule.support.Delorean;
import com.vtence.molecule.support.StackTrace;
import com.vtence.molecule.testing.http.HttpRequest;
import com.vtence.molecule.testing.http.HttpResponse;
import com.vtence.molecule.testing.http.UrlEncodedForm;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import static com.vtence.molecule.testing.http.HttpResponseAssert.assertThat;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
public class SessionTest {
Delorean delorean = new Delorean();
SessionExample sessions = new SessionExample(delorean);
WebServer server = WebServer.create(9999);
Throwable error;
// The default session cookie name, it can be set to something different
String SESSION_COOKIE = "molecule.session";
int FIVE_MIN = 300;
HttpRequest request = new HttpRequest(9999);
HttpResponse response;
@Before
public void startServer() throws IOException {
sessions.run(server);
server.failureReporter(e -> error = e);
}
@After
public void stopServer() throws IOException {
delorean.back();
server.stop();
}
@Test
public void accessingTheSessionWithoutCreatingANewSession() throws IOException {
response = request.get("/");
assertNoError();
assertThat(response).hasNoCookie(SESSION_COOKIE)
.hasBodyText("Hello, Guest");
}
@Test
public void trackingASessionAcrossRequests() throws IOException {
response = request.but().content(new UrlEncodedForm().addField("username", "Vincent")).post("/login");
assertNoError();
String sessionId = response.cookie(SESSION_COOKIE).getValue();
response = request.but().cookie(SESSION_COOKIE, sessionId).get("/");
assertNoError();
assertThat(response).hasBodyText("Hello, Vincent");
}
@Test
public void creatingATransientSessionCookie() throws IOException {
response = request.content(new UrlEncodedForm().addField("username", "Vincent")).post("/login");
assertNoError();
assertThat(response).hasCookie(SESSION_COOKIE).hasMaxAge(-1);
}
@Test
public void creatingAPersistentSessionCookieWhichExpiresAfterFiveMinutes() throws IOException {
response = request.content(new UrlEncodedForm().addField("username", "Vincent")
.addField("remember_me", "true"))
.post("/login");
assertNoError();
assertThat(response).hasCookie(SESSION_COOKIE).hasMaxAge(FIVE_MIN);
String sessionId = response.cookie(SESSION_COOKIE).getValue();
// Play the same request again and include the cookie
response = request.cookie(SESSION_COOKIE, sessionId).send();
assertNoError();
// ... the cookie will have been refreshed
assertThat(response).hasCookie(SESSION_COOKIE).hasMaxAge(FIVE_MIN);
}
@Test
public void deletingASession() throws IOException {
response = request.but().content(new UrlEncodedForm().addField("username", "Vincent")).post("/login");
assertNoError();
assertThat(response).hasCookie(SESSION_COOKIE);
String sessionId = response.cookie(SESSION_COOKIE).getValue();
response = request.but().cookie(SESSION_COOKIE, sessionId).delete("/logout");
assertNoError();
// Session cookie should be expired
assertThat(response).hasCookie(SESSION_COOKIE).hasMaxAge(0);
response = request.but().get("/");
assertNoError();
// Back to being a guest
assertThat(response).hasBodyText("Hello, Guest");
}
@Test
public void
attemptingToUseAnExpiredSession() throws Exception {
response = request.but().content(new UrlEncodedForm().addField("username", "Vincent")
.addField("remember_me", "true"))
.post("/login");
assertNoError();
String sessionId = response.cookie(SESSION_COOKIE).getValue();
delorean.travelInTime(SECONDS.toMillis(FIVE_MIN));
response = request.but().cookie(SESSION_COOKIE, sessionId).get("/");
assertNoError();
assertThat(response).hasNoCookie(SESSION_COOKIE)
.hasBodyText("Hello, Guest");
}
@Test
public void
renewingASessionToAvoidSessionFixation() throws Exception {
response = request.but().content(new UrlEncodedForm().addField("username", "attacker")).post("/login");
assertNoError();
String fixatedSession = response.cookie(SESSION_COOKIE).getValue();
response = request.but().cookie(SESSION_COOKIE, fixatedSession)
.content(new UrlEncodedForm().addField("username", "Vincent")
.addField("remember_me", "true")
.addField("renew", "true"))
.post("/login");
assertNoError();
assertThat(response).hasCookie(SESSION_COOKIE);
String sessionId = response.cookie(SESSION_COOKIE).getValue();
assertThat("new session id", sessionId, not(equalTo(fixatedSession)));
}
private void assertNoError() {
if (error != null) fail(StackTrace.of(error));
}
}