Skip to main content
Version: 11.3.0

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.read and okta.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:

VariableValue
$OktaDomainYour Okta tenant URL (https://<your-tenant>.okta.com)
$ApiTokenThe Okta admin API token used for authentication
$CsvPathPath to the CSV file from CSV format
$AttributeThe custom attribute name in your Okta profile schema (default: hasHyprDeviceRegisteredForHYPRSSO)
$ValueValue to set on each user (default: $false; change to $true to bulk-set, or any value valid for the attribute's schema type)
Handle the API token like a secret

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:

  1. URL-encodes the login value.
  2. Fetches the full user record via GET /api/v1/users/<login>.
  3. Sets the configured $Attribute on the user's profile object to $Value.
  4. 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

  1. Pick one user from your CSV and verify the attribute value in the Okta admin console (Directory → People → <user> → Profile).

  2. 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
  3. If the script returned a non-zero failed count, 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 grants okta.users.manage.
  • 404 Not Found on lookup — the login identifier in the CSV does not match a user in Okta. Confirm the value is the user's Okta login (often the primary email) and not a display name.
  • 400 Bad Request on update — the attribute name in $Attribute is not defined in the Okta profile schema, or the value type is incompatible. Confirm the attribute exists in Profile Editor and that $Value matches 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 insert Start-Sleep between iterations.