Files
spring-auth-demo/refresh-tokens/src/test/java/com/ankurm/refresh/LogoutTest.java
T

57 lines
2.8 KiB
Java

package com.ankurm.refresh;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
/** Output 07: logout on one device, logout everywhere, and the access token that outlives both. */
@SpringBootTest
@AutoConfigureMockMvc
@Import(MutableClock.Config.class)
class LogoutTest extends FlowSupport {
int logout(String refreshToken) throws Exception {
return mvc.perform(post("/api/auth/logout").contentType(MediaType.APPLICATION_JSON)
.content("{\"refresh_token\":\"%s\"}".formatted(refreshToken))).andReturn().getResponse().getStatus();
}
@Test
void logoutOneDeviceThenEverywhere() throws Exception {
Transcript t = new Transcript("07-logout");
Tokens phone = login("alice");
Tokens laptop = login("alice");
Tokens tablet = login("alice");
Tokens bob = login("bob");
t.line("alice is logged in on phone, laptop and tablet (3 families); bob on one device.");
t.line("POST /api/auth/logout with the phone's refresh token: HTTP %d", logout(phone.refresh()));
t.line(" phone refresh: HTTP %d", refreshRaw(phone.refresh()).getResponse().getStatus());
Tokens laptop2 = refresh(laptop.refresh());
t.line(" laptop refresh: HTTP 200");
t.line("POST /api/auth/logout with a made-up token: HTTP %d (same answer, no oracle)", logout("not-a-real-token"));
MvcResult all = mvc.perform(post("/api/auth/logout-all").header("Authorization", "Bearer " + laptop2.access())).andReturn();
t.line("POST /api/auth/logout-all with the laptop's access token: HTTP %d %s",
all.getResponse().getStatus(), all.getResponse().getContentAsString());
t.line(" laptop refresh: HTTP %d", refreshRaw(laptop2.refresh()).getResponse().getStatus());
t.line(" tablet refresh: HTTP %d", refreshRaw(tablet.refresh()).getResponse().getStatus());
int bobRefresh = refreshRaw(bob.refresh()).getResponse().getStatus();
t.line(" bob refresh: HTTP %d (untouched)", bobRefresh);
int stillValid = me(laptop2.access());
t.line("alice's laptop ACCESS token on /api/me after logout-all: HTTP %d", stillValid);
t.line(" (it is a signed JWT with 5 minutes left; nothing in the request path asked the store)");
assertThat(all.getResponse().getStatus()).isEqualTo(200);
assertThat(bobRefresh).isEqualTo(200);
assertThat(stillValid).isEqualTo(200);
t.write();
}
}