Problem
The activate endpoint in AccountServiceEndpoints uses securityIn(jsonBody[Activate]) on a GET request:
val activate: ServerEndpoint[Any with AkkaStreams, Future] =
setNewCsrfToken(checkMode) {
setSession(sc, st) {
endpoint
.securityIn(jsonBody[Activate]) // <-- JSON body on GET
...
}
}
.in(AccountSettings.Path / "activate")
.get
This is problematic because:
- GET requests should not have a body — per HTTP spec (RFC 7231), GET semantics are defined for retrieval and request bodies have no defined semantics
- Browsers cannot send GET with JSON body — activation links in emails (
/activate?token=...) cannot work directly
- Inconsistency —
checkResetPasswordToken correctly uses path[String] for the same pattern (token in URL path)
Proposed Fix
Change activate to use path[String] (consistent with checkResetPasswordToken):
val activate: ServerEndpoint[Any with AkkaStreams, Future] =
setNewCsrfToken(checkMode) {
setSession(sc, st) {
endpoint
.errorOut(ApiErrors.oneOfApiErrors)
.serverSecurityLogicWithOutput(activate =>
run(activate.token, activate).map {
...
}
)
}
}
.in(AccountSettings.Path / "activate")
.in(path[String])
.get
Route: GET /account/activate/{token} (instead of GET /account/activate with JSON body)
Analysis of Other Endpoints
Review of all endpoints in AccountServiceEndpoints for similar issues:
| Endpoint |
Method |
Input |
Assessment |
signUp |
POST |
jsonBody[SU] |
OK — POST with body |
login/signIn |
POST |
jsonBody[Login] |
OK — POST with body |
activate |
GET |
jsonBody[Activate] |
BUG — should be path[String] |
basic |
POST |
auth.basic[UsernamePassword] |
OK — Basic auth header |
principal |
POST |
jsonBody[UpdateLogin] |
OK — POST with body, authenticated |
logout/signOut |
POST (no body) |
session only |
OK |
sendVerificationCode |
POST |
jsonBody[SendVerificationCode] |
OK — POST with body |
sendResetPasswordToken |
POST |
jsonBody[SendResetPasswordToken] |
OK — POST with body |
checkResetPasswordToken |
GET |
path[String] |
OK — correctly uses path param |
resetPassword |
POST |
jsonBody[ResetPassword] |
OK — POST with body |
unsubscribe |
POST |
session only |
OK |
registerDevice |
POST |
jsonBody[DeviceRegistration] |
OK |
unregisterDevice |
DELETE |
path[String] |
OK |
updatePassword |
POST |
jsonBody[PasswordData] |
OK |
Only activate has this issue. All other GET endpoints correctly use path parameters.
Problem
The
activateendpoint inAccountServiceEndpointsusessecurityIn(jsonBody[Activate])on a GET request:This is problematic because:
/activate?token=...) cannot work directlycheckResetPasswordTokencorrectly usespath[String]for the same pattern (token in URL path)Proposed Fix
Change
activateto usepath[String](consistent withcheckResetPasswordToken):Route:
GET /account/activate/{token}(instead ofGET /account/activatewith JSON body)Analysis of Other Endpoints
Review of all endpoints in
AccountServiceEndpointsfor similar issues:signUpjsonBody[SU]login/signInjsonBody[Login]activatejsonBody[Activate]path[String]basicauth.basic[UsernamePassword]principaljsonBody[UpdateLogin]logout/signOutsendVerificationCodejsonBody[SendVerificationCode]sendResetPasswordTokenjsonBody[SendResetPasswordToken]checkResetPasswordTokenpath[String]resetPasswordjsonBody[ResetPassword]unsubscriberegisterDevicejsonBody[DeviceRegistration]unregisterDevicepath[String]updatePasswordjsonBody[PasswordData]Only
activatehas this issue. All other GET endpoints correctly use path parameters.