Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

meta:
version: "1.0.0"
last_updated: "2026-03-05"
skill_count: 45
last_updated: "2026-06-09"
skill_count: 46
role_count: 5

tag_vocabulary:
Expand Down Expand Up @@ -90,6 +90,18 @@ skills:
file: skills/identity/iam-review/SKILL.md
compatible_tools: [claude-code, gemini-cli, cursor, codex-cli, openclaw, kiro]

- id: oauth-oidc-security
name: "OAuth/OIDC Security Review"
tags: [identity, oauth, oidc, federation, authentication]
role: [appsec-engineer, security-engineer]
phase: [design, build, review]
activity: [review, assess, test]
frameworks: [OAuth-2.0, OpenID-Connect-Core, RFC-9700, RFC-7636, RFC-8252, RFC-8628, OWASP-ASVS-5.0]
difficulty: intermediate
time_estimate: "45-90min"
file: skills/identity/oauth-oidc-security/SKILL.md
compatible_tools: [claude-code, gemini-cli, cursor, codex-cli, openclaw, kiro]

- id: access-review
name: "Access Review & Entitlement Audit"
tags: [identity, access-review, least-privilege]
Expand Down
282 changes: 282 additions & 0 deletions skills/identity/oauth-oidc-security/SKILL.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
case: oauth_oidc_hardened_auth_code_pkce
skill: oauth-oidc-security
category: benign
scenario: Authorization code OIDC login is bound with exact redirect, PKCE S256, state, nonce, and server-side token validation.
evidence:
client_type: web_confidential_bff
authorization_request:
redirect_uri_registration: https://app.example.com/oauth/callback
redirect_match_mode: exact
pkce:
method: S256
verifier_storage: server_side_session
state:
entropy_bits: 128
bound_to_server_session: true
binds_post_login_redirect: true
consumed_once: true
nonce:
generated: true
bound_to_server_session: true
compared_to_id_token: true
consumed_once: true
callback_handler:
code_exchange_location: backend
authorization_code_replay_test: rejects_second_use
token_validation:
signature_verified: true
issuer: https://idp.example.com/
audience: web-client-123
algorithms:
- RS256
azp_check: not_required_single_audience
expiry_and_nbf_checked: true
jwks_source: trusted_issuer_metadata
safe_result: true
expected_findings: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
case: oauth_oidc_public_client_token_storage_controlled
skill: oauth-oidc-security
category: benign
scenario: Native and browser public clients use PKCE, platform storage or BFF isolation, and refresh-token rotation.
evidence:
native_client:
user_agent: external_system_browser
redirect_uri: https_claimed_app_link
pkce_method: S256
token_storage: platform_keychain
embedded_client_secret: absent
browser_client:
architecture: backend_for_frontend
access_token_visible_to_javascript: false
refresh_token_visible_to_javascript: false
session_cookie:
httponly: true
secure: true
samesite: lax
refresh_tokens:
rotation_enabled: true
reuse_detection: true
logout_revokes_refresh_token: true
compromise_revocation_runbook: documented
telemetry:
token_redaction_in_logs: verified
crash_report_token_filter: verified
safe_result: true
expected_findings: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
case: oauth_oidc_resource_server_audience_bound
skill: oauth-oidc-security
category: benign
scenario: API validates access-token audience, issuer, scopes, token type, tenant, and revocation cache behavior.
evidence:
api_resource: https://api.example.com/payments
accepted_tokens:
- token_type: access_token
audience: https://api.example.com/payments
jwt_validation:
signature_verified: true
issuer_allowlist:
- https://idp.example.com/tenant-a
audience_check: exact_resource_audience
authorized_party_check: client_id_allowlist
token_type_check: rejects_id_tokens
algorithms:
- RS256
jwks_source: trusted_issuer_metadata
key_cache_ttl_minutes: 15
authorization:
scope_mapping:
POST /refunds: payments.refund.write
GET /refunds: payments.refund.read
tenant_check: issuer_subject_and_tenant_claim
object_owner_check: database_owner_policy
revocation:
introspection_for_opaque_tokens: supported
validation_cache_ttl_minutes: 5
deprovisioning_recheck: on_session_refresh
safe_result: true
expected_findings: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
case: oauth_oidc_callback_missing_binding
skill: oauth-oidc-security
category: vulnerable
scenario: Authorization code OIDC login accepts callback parameters without request binding.
evidence:
client_type: spa_public_client
authorization_request:
redirect_uri_registration: "https://app.example.com/callback*"
redirect_match_mode: prefix
pkce:
method: plain
verifier_storage: browser_session_storage
state:
generated: true
entropy_bits: 32
bound_to_server_session: false
consumed_once: false
nonce:
generated: false
compared_to_id_token: false
callback_handler:
code_exchange_location: browser
accepts_query_redirect_after_login: true
authorization_code_replay_test: not_performed
token_handling:
id_token_validation: jwt_decode_without_verification
account_link_key: email
expected_findings:
- OAUTH-REDIR-01
- OAUTH-CB-01
- OIDC-NONCE-01
- OAUTH-PKCE-01
- OIDC-JWT-01
- OAUTH-LINK-01
expected_severity: high
safe_result: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
case: oauth_oidc_device_flow_token_leakage
skill: oauth-oidc-security
category: vulnerable
scenario: Device authorization flow and browser client leak long-lived tokens without refresh rotation.
evidence:
device_flow:
user_code_lifetime_minutes: 30
phishing_warning_displayed: false
user_prompt_shows_requesting_device: false
polling_rate_limit: missing
account_binding_evidence: user_code_only
browser_client:
access_token_storage: localStorage
refresh_token_storage: localStorage
third_party_scripts_on_token_origin: true
authorization_response_mode: query
refresh_tokens:
rotation_enabled: false
reuse_detection: false
logout_revokes_refresh_token: false
telemetry:
token_values_in_crash_reports: true
authorization_codes_in_access_logs: true
expected_findings:
- OAUTH-DEVICE-01
- OAUTH-STORE-01
- OAUTH-REFRESH-01
- OAUTH-CODE-01
expected_severity: high
safe_result: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
case: oauth_oidc_resource_server_audience_confusion
skill: oauth-oidc-security
category: vulnerable
scenario: Resource server accepts any signed JWT from a shared IdP without audience, type, or tenant enforcement.
evidence:
api_resource: https://api.example.com/payments
accepted_tokens:
- token_type: id_token
accepted_for_api: true
- token_type: access_token
audience_required: false
jwt_validation:
signature_verified: true
issuer_allowlist:
- https://login.example-idp.com/common
audience_check: missing
authorized_party_check: missing
token_type_check: missing
jwks_source: issuer_metadata_common_endpoint
key_selection: kid_only_without_issuer_partition
authorization:
scope_mapping: "scope string contains admin"
tenant_check: missing
object_owner_check: missing
expected_findings:
- OAUTH-AUD-01
- OIDC-TYPE-01
- OIDC-MULTI-01
- OAUTH-SCOPE-01
- OAUTH-TENANT-01
expected_severity: high
safe_result: false