Skip to content

feat(api): implement JWT authentication for data collectors#24

Merged
shark0F0497 merged 3 commits intomainfrom
feat/collector-auth
Mar 31, 2026
Merged

feat(api): implement JWT authentication for data collectors#24
shark0F0497 merged 3 commits intomainfrom
feat/collector-auth

Conversation

@shark0F0497
Copy link
Copy Markdown
Collaborator

Pull Request Checklist

Please ensure your PR meets the following requirements:

  • Code follows the style guidelines
  • Tests pass locally
  • Code is formatted
  • Documentation updated if needed
  • Commit messages follow conventional commits
  • PR description is complete and clear

Summary

This PR implements JWT-based authentication for data collectors, enabling secure login, token-based session management, and protected API endpoints.


Motivation

Data collectors need a secure, standardized authentication mechanism to access the Keystone Edge API. This feature introduces:

  • Secure password-based login for data collectors
  • JWT token issuance for authenticated sessions
  • Consistent authentication middleware for API endpoints
  • Configuration-driven JWT settings for flexibility across environments

Changes

Modified Files

Added Files


Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update (documentation changes only)
  • Refactoring (code improvement without functional changes)
  • Performance improvement (code changes that improve performance)
  • Test changes (adding, modifying, or removing tests)

Impact Analysis

Breaking Changes

None - existing functionality is preserved.

Backward Compatibility

Fully backward compatible. The new password_hash and last_login_at columns are nullable and won't affect existing deployments.


Testing

Test Environment

Development environment with MySQL database.

Test Cases

  • Unit tests pass locally
  • Integration tests pass locally
  • E2E tests pass (if applicable)
  • Manual testing completed

Manual Testing Steps

  1. Create a data collector with password via POST /api/v1/data-collectors
  2. Login with credentials via POST /api/v1/auth/login
  3. Verify JWT token is returned in response
  4. Call GET /api/v1/auth/me with Bearer token to verify authentication
  5. Test logout via POST /api/v1/auth/logout

Test Coverage

  • New tests added
  • Existing tests updated
  • Coverage maintained or improved

Screenshots / Recordings


Performance Impact

  • Memory usage: No change
  • CPU usage: No change (minimal JWT operations)
  • Throughput: No change
  • Lock contention: No change

Documentation


Related Issues

  • Related to collector authentication feature

Additional Notes

Environment Variables

The following environment variables are used:

Variable Description Default
KEYSTONE_JWT_SECRET Secret key for signing JWT tokens (required in production)
KEYSTONE_JWT_ISSUER JWT issuer claim keystone-edge
KEYSTONE_JWT_EXPIRY_HOURS Token expiration in hours 24
KEYSTONE_AUTH_ALLOW_NO_AUTH_ON_DEV Skip JWT secret validation in dev false

API Endpoints

Method Endpoint Auth Required Description
POST /api/v1/auth/login No Login with operator_id and password
POST /api/v1/auth/logout Yes Logout current session
GET /api/v1/auth/me Yes Get current collector info

Reviewers

@kilo-code-bot


Notes for Reviewers

  • Please review the JWT token generation and validation logic
  • Verify password hashing implementation follows security best practices
  • Check that the auth middleware integration is consistent with the server architecture

Checklist for Reviewers

  • Code changes are correct and well-implemented
  • Tests are adequate and pass
  • Documentation is updated and accurate
  • No unintended side effects
  • Performance impact is acceptable
  • Backward compatibility maintained (if applicable)

var passwordHash sql.NullString
password := req.Password
if password == "" {
password = "123456"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRITICAL: Hardcoded default password "123456" is a severe security vulnerability

Using a predictable default password allows attackers to easily gain unauthorized access to any data collector account created without an explicit password. This violates security best practices.

Recommendations:

  1. Require password to be explicitly provided during creation
  2. Or generate a secure random password and return it in the response
  3. At minimum, use a cryptographically secure random default that's unique per account
Suggested change
password = "123456"
password = generateSecureRandomPassword()

Alternatively, require password and remove the default entirely.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just ignore that.

return
}

_, _ = h.db.Exec("UPDATE data_collectors SET last_login_at = NOW() WHERE id = ?", row.ID)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Database update error is silently ignored

The last_login_at update failure is silently swallowed. While this is a non-critical operation, silently ignoring errors can mask underlying database issues.

Suggested change
_, _ = h.db.Exec("UPDATE data_collectors SET last_login_at = NOW() WHERE id = ?", row.ID)
if _, err := h.db.Exec("UPDATE data_collectors SET last_login_at = NOW() WHERE id = ?", row.ID); err != nil {
logger.Printf("[Auth] Failed to update last_login_at for collector %d: %v", row.ID, err)
}

At minimum, log the error for observability.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just ignore that

@kilo-code-bot
Copy link
Copy Markdown

kilo-code-bot bot commented Mar 31, 2026

Code Review Summary

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 2
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

CRITICAL

File Line Issue
internal/api/handlers/data_collector.go 266 Hardcoded default password "123456" is a severe security vulnerability
internal/config/config.go 21 JWT secret validation was removed - production could run with empty secret

WARNING

File Line Issue
internal/api/handlers/auth.go 104 Database update error is silently ignored
Files Reviewed (7 files)
  • internal/api/handlers/auth.go - 1 issue
  • internal/api/handlers/data_collector.go - 1 issue
  • internal/config/config.go - 1 issue
  • internal/auth/claims.go
  • internal/auth/jwt.go
  • internal/middleware/jwt_auth.go
  • internal/server/server.go

Summary

This PR implements JWT-based authentication for data collectors. The implementation is well-structured overall, but has critical security issues that should be addressed before merging.

Key concerns:

  1. The hardcoded default password "123456" in data_collector.go:266 is a severe security vulnerability that could allow unauthorized access
  2. The JWT secret validation was removed from Validate() - without this check, production deployments could start with an empty JWT secret, allowing anyone to forge valid authentication tokens

Positive observations:

  • JWT implementation uses HMAC-SHA256 which is appropriate for symmetric key signing
  • Password hashing uses bcrypt with DefaultCost which is secure
  • Token validation properly checks signing algorithm to prevent algorithm substitution attacks
  • #nosec G117 comments appropriately added to suppress false-positive linter warnings on DTO fields

Fix these issues in Kilo Cloud

…ensitive fields in request and response DTOs
Storage StorageConfig
QA QAConfig
Sync SyncConfig
Auth AuthConfig
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRITICAL: JWT secret validation was removed from Validate() function

The previous validation if c.Auth.JWTSecret == "" && !c.Auth.AllowNoAuthOnDev was removed from the Validate() function. Without this check, a production deployment could start with an empty JWT secret, allowing anyone to forge valid authentication tokens.

Either restore the validation or add a new check that ensures JWTSecret is non-empty when the application needs authentication.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just Ignore that

@shark0F0497 shark0F0497 merged commit d73fbb5 into main Mar 31, 2026
6 checks passed
@shark0F0497 shark0F0497 deleted the feat/collector-auth branch March 31, 2026 11:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant