Conversation
appleboy
commented
Mar 1, 2026
- Store only the SHA-256 hash of tokens in the database instead of the raw token string.
- Refactor code to use TokenHash (persisted) and RawToken (in-memory) fields in AccessToken.
- Update all token validations, lookups, and revocation logic to operate on the hash, not the raw token.
- Add a SHA256Hex utility function for consistent hashing.
- Update tests to use RawToken when referencing raw token values, and TokenHash for database interactions.
- Ensure response payloads return RawToken, not TokenHash.
- Store only the SHA-256 hash of tokens in the database instead of the raw token string. - Refactor code to use TokenHash (persisted) and RawToken (in-memory) fields in AccessToken. - Update all token validations, lookups, and revocation logic to operate on the hash, not the raw token. - Add a SHA256Hex utility function for consistent hashing. - Update tests to use RawToken when referencing raw token values, and TokenHash for database interactions. - Ensure response payloads return RawToken, not TokenHash. Signed-off-by: appleboy <[email protected]>
There was a problem hiding this comment.
Pull request overview
This PR refactors access token persistence so only a SHA-256 digest is stored in the database, while the raw token string is kept in-memory for responses and validation.
Changes:
- Introduces
util.SHA256Hexand refactors authorization code hashing to reuse it. - Updates token issuance/validation/revocation paths to persist
TokenHashand return/consumeRawToken. - Updates store lookup APIs and tests to query by token hash rather than raw token.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/util/crypto.go | Adds SHA256Hex helper for consistent hashing. |
| internal/models/token.go | Replaces persisted Token with persisted TokenHash + non-persisted RawToken. |
| internal/store/sqlite.go | Renames token lookup to GetAccessTokenByHash and queries token_hash. |
| internal/services/token.go | Persists token hashes, uses hash-based lookups, restores RawToken when needed for responses. |
| internal/services/authorization.go | Reuses util.SHA256Hex for authorization code hashing. |
| internal/handlers/token.go | Ensures token endpoint responses return RawToken instead of persisted hashes. |
| internal/store/store_test.go | Updates store tests to create/lookup access tokens by hash. |
| internal/services/token_test.go | Updates service tests to use RawToken for validation/revocation and hash for DB asserts. |
| internal/services/token_client_credentials_test.go | Updates client-credentials tests to use RawToken for validation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| type AccessToken struct { | ||
| ID string `gorm:"primaryKey"` | ||
| Token string `gorm:"uniqueIndex;not null"` | ||
| TokenHash string `gorm:"uniqueIndex;not null"` |
There was a problem hiding this comment.
Changing the persisted field from Token to TokenHash will create a new token_hash column via GORM AutoMigrate, but existing installations will still have the old token column (previously NOT NULL + unique). Because AutoMigrate won’t drop/rename columns, inserts can fail (due to the leftover token NOT NULL) and existing token rows won’t have token_hash populated, breaking validation/revocation. Consider adding an explicit migration/backfill (compute hash from existing token, then drop/nullable old column), or map TokenHash to the existing token column using gorm:"column:token" to keep schema compatible.
| TokenHash string `gorm:"uniqueIndex;not null"` | |
| TokenHash string `gorm:"column:token;uniqueIndex;not null"` |
- Update the generate target to also run the swagger step before executing go generate Signed-off-by: appleboy <[email protected]>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
- Clarify the documentation for the SHA-256 helper to better describe when using an unsalted hash is appropriate - Add comprehensive unit tests covering correctness, format, and determinism of the SHA-256 hashing function Signed-off-by: appleboy <[email protected]>
- Reformat test assertions for better readability by expanding them to multi-line calls - Remove the redundant test that checks identical inputs produce the same hash - Keep functional coverage intact for known hash vectors, empty input, and differing inputs Signed-off-by: appleboy <[email protected]>