rules:
  - id: auth.oauth.long-token-lifetime
    languages:
      - javascript
      - typescript
    severity: WARNING
    message: |
      An OAuth token-lifetime field is set to a literal value longer than
      24 hours. The value of `expires_in` (or a comparable field) exceeds
      86_400 seconds. Long-lived access tokens make every token theft
      catastrophic because they remain valid for days or weeks; the
      industry standard is 15-60 minutes for access tokens, paired with
      a refresh-token rotation flow for longer sessions.

      Don't issue access tokens longer than a day. Use refresh tokens
      with proper rotation (RFC 6749 §6, RFC 9700 §4.14) for "stay
      logged in" semantics.
    pattern-either:
      # Numeric literal as an object property.
      - patterns:
          - pattern-either:
              - pattern: '{ ..., expires_in: $TTL, ... }'
              - pattern: '{ ..., expiresIn: $TTL, ... }'
              - pattern: '{ ..., access_token_ttl: $TTL, ... }'
              - pattern: '{ ..., accessTokenTtl: $TTL, ... }'
              - pattern: '{ ..., tokenLifetime: $TTL, ... }'
          - metavariable-comparison:
              metavariable: $TTL
              comparison: $TTL > 86400
      # Numeric literal via member assignment (config.expires_in = N).
      - patterns:
          - pattern-either:
              - pattern: '$X.expires_in = $TTL'
              - pattern: '$X.expiresIn = $TTL'
              - pattern: '$X.access_token_ttl = $TTL'
              - pattern: '$X.accessTokenTtl = $TTL'
              - pattern: '$X.tokenLifetime = $TTL'
          - metavariable-comparison:
              metavariable: $TTL
              comparison: $TTL > 86400
      # jsonwebtoken / `ms`-style string durations longer than a day: >=2 days,
      # or any weeks / months / years. ('1d', '15m', '12h' are <= 24h and are
      # intentionally not matched.)
      - pattern-regex: |-
          (?:expiresIn|expires_in)\s*[:=]\s*['"](?:[2-9]|[1-9][0-9]+)\s*(?:d|days?)['"]
      - pattern-regex: |-
          (?:expiresIn|expires_in)\s*[:=]\s*['"][1-9][0-9]*\s*(?:w|y|weeks?|years?|months?)['"]
    metadata:
      oauthlint-rule-id: AUTH-OAUTH-009
      oauthlint-doc-url: https://oauthlint.dev/rules/oauth-long-token-lifetime
      category: security
      cwe: CWE-613
      owasp: API2:2023
      llm-prevalence: MEDIUM
      references:
        - https://datatracker.ietf.org/doc/html/rfc9700#section-4.14
        - https://datatracker.ietf.org/doc/html/rfc6749#section-6
