fix: API responses never include a user's password, verification code or reset code hashes, or their expiry dates; verifying an account returns only the public user fields
This commit is contained in:
1 parent
aa865af2e9
commit
2ee28203ab
4 files changed
+389
-1
No files matched your search
@@ -0,0 +1,61 @@
|
||||
Feature: API responses never expose a user's secret fields
|
||||
|
||||
As the maintainer of RenewCMS
|
||||
I want every HTTP response that includes user data to carry only public fields, never a
|
||||
password hash, a verification or password-reset code hash, or their expiry timestamps
|
||||
So that a bug, a future endpoint, or a client inspecting a response body can never recover a
|
||||
credential or a still-valid reset/verification secret
|
||||
|
||||
Background:
|
||||
Given the public shape of a user in any API response is exactly six fields: id, username,
|
||||
email, is_verified, created_at and updated_at
|
||||
And password, password_reset_code, verification_code, verification_expiration and
|
||||
password_reset_expiration never appear in any response body, under any key name, regardless
|
||||
of their value or whether they are set
|
||||
|
||||
Scenario: A successful verification response carries only public fields
|
||||
Given a user repository containing user id 7, username "alice", email "alice@example.com",
|
||||
is_verified false, whose stored VerificationCode is the bcrypt hash of "abc123" and whose
|
||||
VerificationExpiration is one hour from now
|
||||
And a valid jwt cookie for user id 7
|
||||
When the client sends POST /v1/auth/verify with body {"code": "abc123"}
|
||||
Then the response status is 200
|
||||
And the response body is a JSON object with exactly the keys id, username, email,
|
||||
is_verified, created_at and updated_at
|
||||
And the response body does not contain the keys password, password_reset_code,
|
||||
verification_code, verification_expiration or password_reset_expiration
|
||||
And the response body's is_verified is true
|
||||
|
||||
Scenario: A rejected verification attempt never echoes any user field
|
||||
Given a user repository containing user id 7, username "alice", is_verified false, whose
|
||||
stored VerificationCode is the bcrypt hash of "abc123" and whose VerificationExpiration is
|
||||
one hour from now
|
||||
And a valid jwt cookie for user id 7
|
||||
When the client sends POST /v1/auth/verify with body {"code": "wrong-code"}
|
||||
Then the response status is 403
|
||||
And the response body is the plain-text apperr.VerificationFailedErrorMessage, not JSON, and
|
||||
contains no user field at all
|
||||
|
||||
Scenario: Registering while no verified account exists never echoes any user field
|
||||
Given the user repository is empty
|
||||
When the client sends POST /v1/auth/register with username "bob", password "hunter2example12",
|
||||
email "bob@example.com"
|
||||
Then the response status is 200
|
||||
And the response body contains no key named password, password_reset_code,
|
||||
verification_code, verification_expiration or password_reset_expiration
|
||||
|
||||
Scenario Outline: No other auth endpoint under /v1/auth leaks a user field
|
||||
Given a user repository containing user id 7, username "alice", email "alice@example.com",
|
||||
is_verified true, with a non-empty PasswordResetCode or VerificationCode where the endpoint
|
||||
under test would set one
|
||||
When the client sends <method> <path> with <body>
|
||||
Then the response status is <status>
|
||||
And the response body contains no key named password, password_reset_code,
|
||||
verification_code, verification_expiration or password_reset_expiration
|
||||
|
||||
Examples:
|
||||
| method | path | body | status |
|
||||
| POST | /v1/auth/login | {"username":"alice","password":"hunter2example12"} | 200 |
|
||||
| POST | /v1/auth/logout | {} | 200 |
|
||||
| POST | /v1/auth/password-reset | {"email":"alice@example.com"} | 200 |
|
||||
| POST | /v1/auth/password-reset/confirm | {"email":"alice@example.com","code":"wrong","password":"hunter2example12"} | 403 |
|
||||
Reference in new issue
Block a user