[go: up one dir, main page]

Skip to content

Add JWT callback verification to SdrsAuthenticationService

Add SDRS callback JWT verification support

What does this MR do and why?

Followed threat model https://gitlab.com/gitlab-com/gl-security/product-security/appsec/appsec-reviews/-/issues/249

This MR adds JWT callback token verification to the SdrsAuthenticationService to enable secure asynchronous communication from the Secret Detection Response Service (SDRS) back to GitLab.

Background

The Secret Detection feature needs to verify partner tokens through an external service (SDRS). The flow is:

  1. GitLab sends a verification request to SDRS with a JWT token
  2. SDRS processes the request asynchronously
  3. SDRS callbacks to GitLab with the verification result (active/revoked)

This MR implements step 3 - secure callback verification.

Changes

  • Add verify_callback_token method: Validates JWT tokens from SDRS with proper security checks
  • Implement replay attack prevention: Uses Redis to track JWT IDs (JTI) and prevent token reuse
  • Add clock skew tolerance: 30-second leeway for distributed system time differences
  • Validate GitLab claims: Ensures finding_id is present and valid
  • Add comprehensive error handling: Logs JWT validation failures without exposing sensitive data

Screenshots or screen recordings

N/A - Backend service changes only

How to set up and validate locally

Prerequisites

  1. Enable SDRS feature flag (if applicable):

    Feature.enable(:sdrs_partner_token_verification)
  2. Configure SDRS keys in Rails console:

    # Generate keys for testing
    gitlab_key = OpenSSL::PKey::RSA.generate(2048)
    sdrs_key = OpenSSL::PKey::RSA.generate(2048)
    
    # Set GitLab's signing key (for outgoing requests)
    ApplicationSetting.current.update!(sdrs_jwt_signing_key: gitlab_key.to_pem)
    
    # Set SDRS's public key (for verifying callbacks)
    ApplicationSetting.current.update!(sdrs_jwt_public_key: sdrs_key.public_key.to_pem)

Test Flows

1. Test Token Generation (GitLab → SDRS)

# In Rails console
user = User.first
project = Project.first
finding = Vulnerabilities::Finding.first

# Generate token for SDRS
token = Authz::SdrsAuthenticationService.generate_token(
  user: user,
  project: project,
  finding_id: finding.id
)

puts "Token for SDRS: #{token}"

# Decode to verify contents
public_key = OpenSSL::PKey::RSA.new(ApplicationSetting.current.sdrs_jwt_signing_key).public_key
decoded = JWT.decode(token, public_key, true, algorithm: 'RS256')
pp decoded

2. Test Valid Callback Verification (SDRS → GitLab)

# Simulate SDRS callback
sdrs_private_key = OpenSSL::PKey::RSA.new(ApplicationSetting.current.sdrs_jwt_public_key)

# Create callback JWT
callback_payload = {
  iss: 'sdrs',
  aud: 'gitlab-secret-detection',
  exp: 1.hour.from_now.to_i,
  iat: Time.current.to_i,
  jti: SecureRandom.uuid,
  gitlab: {
    finding_id: finding.id
  }
}

callback_token = JWT.encode(callback_payload, sdrs_private_key, 'RS256')

# Verify the callback
result = Authz::SdrsAuthenticationService.verify_callback_token(callback_token)
puts "Verification result: #{result.inspect}"
# Should return the payload

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Related Issues

Edited by Aditya Tiwari

Merge request reports

Loading