fix: return rotated refresh token from agent token refresh endpoint
Previously the refresh endpoint only returned a new accessToken, causing agents to lose their refreshToken after the first refresh cycle and forcing a full re-registration every ~2 hours. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -159,8 +159,9 @@ public class AgentRegistrationController {
|
||||
List<String> roles = result.roles().isEmpty()
|
||||
? List.of("AGENT") : result.roles();
|
||||
String newAccessToken = jwtService.createAccessToken(agentId, agent.group(), roles);
|
||||
String newRefreshToken = jwtService.createRefreshToken(agentId, agent.group(), roles);
|
||||
|
||||
return ResponseEntity.ok(new AgentRefreshResponse(newAccessToken));
|
||||
return ResponseEntity.ok(new AgentRefreshResponse(newAccessToken, newRefreshToken));
|
||||
}
|
||||
|
||||
@PostMapping("/{id}/heartbeat")
|
||||
|
||||
@@ -3,5 +3,5 @@ package com.cameleer3.server.app.dto;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "Refreshed access token")
|
||||
public record AgentRefreshResponse(@NotNull String accessToken) {}
|
||||
@Schema(description = "Refreshed access and refresh tokens")
|
||||
public record AgentRefreshResponse(@NotNull String accessToken, @NotNull String refreshToken) {}
|
||||
|
||||
@@ -79,6 +79,8 @@ class JwtRefreshIT extends AbstractPostgresIT {
|
||||
|
||||
JsonNode body = objectMapper.readTree(response.getBody());
|
||||
assertThat(body.get("accessToken").asText()).isNotEmpty();
|
||||
assertThat(body.get("refreshToken").asText()).isNotEmpty();
|
||||
assertThat(body.get("refreshToken").asText()).isNotEqualTo(refreshToken);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -2913,14 +2913,18 @@
|
||||
},
|
||||
"AgentRefreshResponse": {
|
||||
"type": "object",
|
||||
"description": "Refreshed access token",
|
||||
"description": "Refreshed access and refresh tokens",
|
||||
"properties": {
|
||||
"accessToken": {
|
||||
"type": "string"
|
||||
},
|
||||
"refreshToken": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"accessToken"
|
||||
"accessToken",
|
||||
"refreshToken"
|
||||
]
|
||||
},
|
||||
"CommandRequest": {
|
||||
|
||||
3
ui/src/api/schema.d.ts
vendored
3
ui/src/api/schema.d.ts
vendored
@@ -1069,9 +1069,10 @@ export interface components {
|
||||
AgentRefreshRequest: {
|
||||
refreshToken: string;
|
||||
};
|
||||
/** @description Refreshed access token */
|
||||
/** @description Refreshed access and refresh tokens */
|
||||
AgentRefreshResponse: {
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
};
|
||||
/** @description Command to send to agent(s) */
|
||||
CommandRequest: {
|
||||
|
||||
Reference in New Issue
Block a user