Skip to content
Back to skills

499 Jwt Bearer 6c737eb1

BSecurity

OAuth 2.0 JWT Bearer assertion flow for server-to-server authentication without user interaction.

  • 9 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added October 11, 2026
securityjavascriptpythongojavabashnodeapibackendci/cdsecurity

Works with

  • cli
  • api

Security analysis

B88/100
  • criticalExfiltrates credentials via HTTP โ€” exact pattern from Snyk ToxicSkills study

Pro shows the line behind each finding and how to fix it

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 499-jwt-bearer_6c737eb1 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 499 Jwt Bearer 6c737eb1?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 499 Jwt Bearer 6c737eb1
[![Security: B โ€” Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-499-jwt-bearer-6c737eb1/badge)](https://www.skillsdirectory.com/skills/tools-only-499-jwt-bearer-6c737eb1)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# JWT Bearer Flow Template

OAuth 2.0 JWT Bearer assertion flow for server-to-server authentication without user interaction.

## When to Use
- Server-to-server integrations
- CI/CD pipelines
- Scheduled jobs and automation
- Background processes
- Any headless authentication scenario

## Prerequisites
1. X.509 Certificate uploaded to Salesforce Connected App
2. Pre-authorized user via Permission Set
3. Private key securely stored on server

## Mermaid Template

```mermaid
%%{init: {'theme': 'base', 'themeVariables': {
  'actorBkg': '#ddd6fe',
  'actorTextColor': '#1f2937',
  'actorBorder': '#6d28d9',
  'signalColor': '#334155',
  'signalTextColor': '#1f2937',
  'noteBkgColor': '#f8fafc',
  'noteTextColor': '#1f2937',
  'noteBorderColor': '#334155'
}}}%%
sequenceDiagram
    autonumber

    box rgba(221,214,254,0.3) SERVER ENVIRONMENT
        participant S as ๐Ÿ–ฅ๏ธ Server<br/>(CI/CD, Backend)
        participant K as ๐Ÿ” Key Store
    end

    box rgba(167,243,208,0.3) SALESFORCE
        participant SF as โ˜๏ธ Salesforce<br/>Authorization Server
    end

    Note over S,SF: JWT Bearer Flow (RFC 7523)

    S->>K: 1. Retrieve Private Key
    K->>S: 2. Return Private Key

    S->>S: 3. Create JWT Header
    Note over S: {<br/>  "alg": "RS256",<br/>  "typ": "JWT"<br/>}

    S->>S: 4. Create JWT Payload
    Note over S: {<br/>  "iss": "CONSUMER_KEY",<br/>  "sub": "user@company.com",<br/>  "aud": "https://login.salesforce.com",<br/>  "exp": CURRENT_TIME + 300<br/>}

    S->>S: 5. Sign JWT with Private Key
    Note over S: signature = RS256(header.payload, privateKey)<br/>jwt = header.payload.signature

    S->>SF: 6. POST /services/oauth2/token
    Note over S,SF: grant_type=urn:ietf:params:oauth:<br/>          grant-type:jwt-bearer<br/>assertion=SIGNED_JWT

    SF->>SF: 7. Decode JWT

    SF->>SF: 8. Validate Signature
    Note over SF: Verify using uploaded<br/>X.509 certificate

    SF->>SF: 9. Validate Claims
    Note over SF: โ€ข iss matches Consumer Key<br/>โ€ข sub is pre-authorized user<br/>โ€ข aud is correct endpoint<br/>โ€ข exp is not passed

    SF->>SF: 10. Check User Authorization
    Note over SF: User must be pre-authorized<br/>via Permission Set

    SF->>S: 11. Return Access Token
    Note over SF,S: {<br/>  "access_token": "...",<br/>  "instance_url": "https://...",<br/>  "token_type": "Bearer",<br/>  "issued_at": "...",<br/>  "scope": "api"<br/>}

    Note over S: โš ๏ธ No refresh_token returned

    S->>S: 12. Store Access Token

    S->>SF: 13. Make API Calls
    Note over S,SF: Authorization: Bearer ACCESS_TOKEN

    SF->>S: 14. API Response
```

## ASCII Fallback Template

```
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚     Server/CI/CD      โ”‚     โ”‚     Salesforce     โ”‚
โ”‚    (Private Key)      โ”‚     โ”‚   (Certificate)    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
            โ”‚                           โ”‚
            โ”‚  1. Create JWT Claims     โ”‚
            โ”‚     iss: consumer_key     โ”‚
            โ”‚     sub: user@company.com โ”‚
            โ”‚     aud: login.sf.com     โ”‚
            โ”‚     exp: now + 5 min      โ”‚
            โ”‚                           โ”‚
            โ”‚  2. Sign JWT with         โ”‚
            โ”‚     Private Key (RS256)   โ”‚
            โ”‚                           โ”‚
            โ”‚  3. POST /token           โ”‚
            โ”‚     (grant_type=jwt-bearer)
            โ”‚     (assertion=signed_jwt)โ”‚
            โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€>โ”‚
            โ”‚                           โ”‚
            โ”‚           4. Verify JWT   โ”‚
            โ”‚              signature    โ”‚
            โ”‚              with cert    โ”‚
            โ”‚                           โ”‚
            โ”‚           5. Validate     โ”‚
            โ”‚              claims       โ”‚
            โ”‚                           โ”‚
            โ”‚           6. Check user   โ”‚
            โ”‚              pre-auth     โ”‚
            โ”‚                           โ”‚
            โ”‚  7. Access Token          โ”‚
            โ”‚     (NO refresh token!)   โ”‚
            โ”‚<โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
            โ”‚                           โ”‚
            โ”‚  8. API Request           โ”‚
            โ”‚     (Bearer token)        โ”‚
            โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€>โ”‚
            โ”‚                           โ”‚
            โ”‚  9. API Response          โ”‚
            โ”‚<โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
```

## JWT Structure

### Header
```json
{
  "alg": "RS256",
  "typ": "JWT"
}
```

### Payload (Claims)
```json
{
  "iss": "3MVG9...",          // Consumer Key from Connected App
  "sub": "user@company.com",   // Pre-authorized username
  "aud": "https://login.salesforce.com",  // Or test.salesforce.com for sandbox
  "exp": 1702123456            // Expiration (current time + 5 min max)
}
```

### Signature
```
RS256(
  base64URLEncode(header) + "." + base64URLEncode(payload),
  privateKey
)
```

## Token Request

```bash
curl -X POST https://login.salesforce.com/services/oauth2/token \
  -d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" \
  -d "assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzTVZHOS4uLiIsInN1YiI6InVzZXJAY29tcGFueS5jb20iLCJhdWQiOiJodHRwczovL2xvZ2luLnNhbGVzZm9yY2UuY29tIiwiZXhwIjoxNzAyMTIzNDU2fQ.SIGNATURE"
```

## Code Examples

### Python
```python
import jwt
import time
import requests

private_key = open('server.key').read()

claim_set = {
    'iss': 'YOUR_CONSUMER_KEY',
    'sub': 'user@company.com',
    'aud': 'https://login.salesforce.com',
    'exp': int(time.time()) + 300  # 5 minutes
}

assertion = jwt.encode(claim_set, private_key, algorithm='RS256')

response = requests.post(
    'https://login.salesforce.com/services/oauth2/token',
    data={
        'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
        'assertion': assertion
    }
)

access_token = response.json()['access_token']
instance_url = response.json()['instance_url']
```

### Node.js
```javascript
const jwt = require('jsonwebtoken');
const axios = require('axios');
const fs = require('fs');

const privateKey = fs.readFileSync('server.key');

const token = jwt.sign(
  {
    iss: 'YOUR_CONSUMER_KEY',
    sub: 'user@company.com',
    aud: 'https://login.salesforce.com',
    exp: Math.floor(Date.now() / 1000) + 300
  },
  privateKey,
  { algorithm: 'RS256' }
);

const response = await axios.post(
  'https://login.salesforce.com/services/oauth2/token',
  new URLSearchParams({
    grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
    assertion: token
  })
);

const { access_token, instance_url } = response.data;
```

## Key Characteristics

| Aspect | Value |
|--------|-------|
| User Interaction | None required |
| Refresh Token | **Not returned** - re-authenticate with new JWT |
| Token Lifetime | Default ~2 hours (configurable) |
| Security Model | Certificate-based (asymmetric) |
| Audience | `login.salesforce.com` or `test.salesforce.com` |

## Security Considerations

1. **Protect private key** - Use secrets manager, HSM, or secure vault
2. **Rotate certificates** before expiration
3. **Short JWT expiration** - Maximum 5 minutes recommended
4. **Limit user permissions** - Use dedicated integration user
5. **Monitor token usage** - Set up login history alerts

## Troubleshooting

| Error | Cause | Solution |
|-------|-------|----------|
| `invalid_grant` | JWT expired or invalid | Check exp claim, verify signature |
| `invalid_client` | Consumer key mismatch | Verify iss matches Connected App |
| `user_not_authorized` | User not pre-approved | Assign Permission Set to user |
| `invalid_assertion` | Signature verification failed | Verify certificate upload |

## Customization Points

Replace these placeholders:
- `CONSUMER_KEY` โ†’ Your Connected App's Consumer Key
- `user@company.com` โ†’ Pre-authorized Salesforce username
- `login.salesforce.com` โ†’ Or `test.salesforce.com` for sandbox

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading commentsโ€ฆ

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.