Bulk Update Okta User-Profile Custom HYPR Attribute
Purpose
Bulk update an Okta user-profile custom attribute across a list of users supplied via CSV. The reference script is parameterized for the HYPR SSO integration custom attribute hasHyprDeviceRegisteredForHYPRSSO and defaults to clearing the flag ($false), but the script's $Attribute and $Value variables accept any custom attribute name and any value supported by the Okta user-profile schema.
Typical use cases:
- Resetting the HYPR device-registration flag across a tenant before a HYPR re-registration campaign.
- Bootstrapping the attribute on a newly-provisioned Okta-HYPR integration.
- Marking a population of users as registered after an offline migration.
Prerequisites
- An Okta admin token with permission to read and update user profiles (super-admin or a custom admin role that grants
okta.users.readandokta.users.manage). - The custom attribute already defined in the Okta user-profile schema (Directory → Profile Editor → User (default) → Profile). The script does not create the attribute.
- A CSV file of Okta logins prepared in advance (see CSV format).
- PowerShell 5.1 or PowerShell 7 on a host that can reach
https://<your-tenant>.okta.com/api/v1.
CSV format
A single column named login with one Okta login identifier per row:
login
user.one@example.com
user.two@example.com
user.three@example.com
Save the file (default path in the script: C:\Temp\users.csv). The script trims whitespace on each row.
Procedure
Step 1 — Save the script locally
Save the reference script below as Update-OktaHYPRAttribute.ps1 on a host that can reach your Okta API:
# =====================
# Update-OktaHYPRAttribute.ps1
#
# Bulk-update an Okta user-profile custom attribute (default: clear a HYPR
# device-registration flag) for users listed in a CSV file.
#
# Usage:
# 1. Update CONFIG values below for your Okta tenant.
# 2. Create users.csv with a single column named "login" and one Okta login
# identifier per row.
# 3. Run from a host that can reach your Okta API.
# =====================
# =====================
# CONFIG
# =====================
$OktaDomain = "https://<your-tenant>.okta.com"
$ApiToken = "<your_api_token>"
$CsvPath = "C:\Temp\users.csv"
# Update the attribute name to match your environment.
$Attribute = "hasHyprDeviceRegisteredForHYPRSSO"
# Value to set. Default is $false (clears the flag). Change to $true if you
# need to bulk-set the flag instead.
$Value = $false
# =====================
# REQUEST HEADERS
# =====================
$Headers = @{
"Authorization" = "SSWS $ApiToken"
"Content-Type" = "application/json"
"Accept" = "application/json"
}
# =====================
# RUN
# =====================
$Users = Import-Csv -Path $CsvPath
$Success = 0
$Failed = 0
foreach ($Row in $Users) {
$Login = $Row.login.Trim()
try {
# Lookup user
$Encoded = [uri]::EscapeDataString($Login)
$UserResult = Invoke-RestMethod -Uri "$OktaDomain/api/v1/users/$Encoded" -Headers $Headers -Method GET
$UserId = $UserResult.id
# GET full profile, modify, PUT back
$UserResult.profile.$Attribute = $Value
$Body = @{ profile = $UserResult.profile } | ConvertTo-Json -Depth 5
$Result = Invoke-RestMethod -Uri "$OktaDomain/api/v1/users/$UserId" -Headers $Headers -Method PUT -Body $Body
Write-Host "[OK] $Login -> $Attribute = $($Result.profile.$Attribute)" -ForegroundColor Green
$Success++
}
catch {
Write-Host "[FAIL] $Login -> $($_.Exception.Message)" -ForegroundColor Red
$Failed++
}
}
Write-Host "`n--- Done: $Success succeeded, $Failed failed ---"
Step 2 — Configure script variables
Update the CONFIG block at the top of the script:
| Variable | Value |
|---|---|
$OktaDomain | Your Okta tenant URL (https://<your-tenant>.okta.com) |
$ApiToken | The Okta admin API token used for authentication |
$CsvPath | Path to the CSV file from CSV format |
$Attribute | The custom attribute name in your Okta profile schema (default: hasHyprDeviceRegisteredForHYPRSSO) |
$Value | Value to set on each user (default: $false; change to $true to bulk-set, or any value valid for the attribute's schema type) |
The script reads $ApiToken directly from the CONFIG block. For production runs, retrieve the token from a secure store at runtime or replace the inline value with a file-based read (similar to the locked-down secret pattern in the Azure Blob CRL Distribution playbook). Do not commit the token to source control.
Step 3 — Run the script
.\Update-OktaHYPRAttribute.ps1
Per-row output:
[OK] <login> -> <attribute> = <value>— successful update.[FAIL] <login> -> <exception message>— error during lookup or update.
A summary line prints at the end:
--- Done: <success-count> succeeded, <fail-count> failed ---
What the script does
For each row in the CSV:
- URL-encodes the
loginvalue. - Fetches the full user record via
GET /api/v1/users/<login>. - Sets the configured
$Attributeon the user's profile object to$Value. - Sends the modified profile back via
PUT /api/v1/users/<userId>with the full profile as the body.
The script reports per-row outcome and totals at the end. It does not stop on error — failed rows are logged and the run continues so a single bad row does not halt the bulk job.
Validation
-
Pick one user from your CSV and verify the attribute value in the Okta admin console (Directory → People → <user> → Profile).
-
Cross-check with a separate API call:
$Encoded = [uri]::EscapeDataString("user.one@example.com")
Invoke-RestMethod -Uri "$OktaDomain/api/v1/users/$Encoded" -Headers $Headers -Method GET |
Select-Object -ExpandProperty profile |
Select-Object hasHyprDeviceRegisteredForHYPRSSO -
If the script returned a non-zero
failedcount, the failed login identifiers are visible in the per-row[FAIL]lines — investigate those individually.
Troubleshooting
401 Unauthorized— the API token is invalid, revoked, or lacks permission. Confirm the token is current and the admin role grantsokta.users.manage.404 Not Foundon lookup — the login identifier in the CSV does not match a user in Okta. Confirm the value is the user's Oktalogin(often the primary email) and not a display name.400 Bad Requeston update — the attribute name in$Attributeis not defined in the Okta profile schema, or the value type is incompatible. Confirm the attribute exists in Profile Editor and that$Valuematches the attribute's declared type.- Rate limiting (
429 Too Many Requests) — Okta's user-management endpoints are rate-limited. For very large populations, run the script in batches or insertStart-Sleepbetween iterations.
Related
- Playbooks overview
- Azure Blob CRL Distribution — for the file-based secret pattern referenced above
- Okta Users API reference (external)