AFAS OAuth Migration Runbook (Target Users)
Purpose
This document helps migrate an existing AFAS Profit target connector for users from classic token authentication to OAuth client credentials.
Use targeted changes only. Do not replace complete scripts, because customer-specific logic may already be present.
Scope
Apply these changes to:
- create.ps1
- update.ps1
- delete.ps1
- disable.ps1
- enable.ps1
- import.ps1
- configuration.json
Preconditions In AFAS
Before changing the connector, make sure the customer has arranged the following in AFAS Profit:
- An AFAS App Connector exists.
- The App Connector is configured for OAuth client credentials as OAuth-only (no hybrid setup with classic token + OAuth).
- The following values are available:
- The App Connector has access to the same Get/Update connectors as the old setup.
Important: advise customers to use an OAuth-only App Connector. AFAS states that in September 2026 existing Classic tokens will automatically get an end date of 15 February 2027. From that date those tokens no longer work. New Classic tokens can still be created with another end date until 31 August 2027. App connectors that have not been used for 6 months or longer are blocked.
See AFAS documentation for more information: Eigen app connector inrichten in vogelvlucht and Eigen app connector beheren.
Required connectors:
- GetConnector: T4E_HelloID_Users_v2 (or customer-specific equivalent)
- UpdateConnector: KnUser
Summary Of The Change
Classic flow:
- reads Configuration.Token
- Base64-encodes the token
- sends Authorization: AfasToken ...
OAuth flow:
- reads Configuration.ClientId and Configuration.ClientSecret
- requests an access token from https://.../ProfitRestServices/oauth/token
- sends Authorization: Bearer ...
Recommended Working Method
- Make a backup copy of create.ps1, update.ps1, delete.ps1, disable.ps1, enable.ps1, import.ps1, and configuration.json.
- Apply each change below: replace the Before block with the After block, or insert the block at the indicated anchor.
- Do not remove unrelated customer customizations.
- Validate all lifecycle actions and import after the update.
Step 1: Update configuration.json
Remove (located after the BaseUri object):
{
"key": "Token",
"type": "input",
"defaultValue": "",
"templateOptions": {
"label": "Token in XML format",
"type": "password",
"placeholder": "<token><version>1</version><data>D5R324DD5F4TRD945E530ED3CDD70D94BBDEC4C732B43F285ECB12345678</data></token>",
"description": "",
"required": true
}
},
Insert after the BaseUri object:
{
"key": "ClientId",
"type": "input",
"templateOptions": {
"label": "ClientId",
"placeholder": "Example: 2f8a2f4d-9a5f-41d8-aec8-6ab123456789",
"description": "The OAuth client id of the AFAS AppConnector.",
"required": true
}
},
{
"key": "ClientSecret",
"type": "input",
"templateOptions": {
"label": "ClientSecret",
"type": "password",
"placeholder": "Example: 1234567890abcdef1234567890abcdef12345678",
"description": "The OAuth client secret of the AFAS AppConnector.",
"required": true
}
},
Step 2: Update create/update/delete/disable/enable/import scripts
All scripts (create.ps1, update.ps1, delete.ps1, disable.ps1, enable.ps1, import.ps1) — replace the classic header block:
Before:
$encodedToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($actionContext.Configuration.Token))
$authValue = "AfasToken $encodedToken"
$Headers = @{ Authorization = $authValue }
$Headers.Add("IntegrationId", "45963_140664")
After:
$tokenUri = "$($actionContext.Configuration.BaseUri)/oauth/token"
Write-Verbose "Requesting OAuth access token from [$tokenUri]"
$tokenRequestBody = @{
grant_type = 'client_credentials'
client_id = $actionContext.Configuration.ClientId
client_secret = $actionContext.Configuration.ClientSecret
}
$tokenResponse = Invoke-RestMethod -Method Post -Uri $tokenUri -Body $tokenRequestBody -ContentType 'application/x-www-form-urlencoded' -UseBasicParsing -Verbose:$false
if ([String]::IsNullOrWhiteSpace([String]$tokenResponse.access_token)) {
throw "OAuth token endpoint did not return an access_token."
}
if ([String]::IsNullOrWhiteSpace([String]$tokenResponse.token_type)) {
throw "OAuth token endpoint did not return a token_type."
}
$Headers = @{ Authorization = "$($tokenResponse.token_type) $($tokenResponse.access_token)" }
$Headers.Add("IntegrationId", "45963_140664")
Step 3: Search terms to confirm classic auth is fully removed
Search all scripts for:
- Configuration.Token
- AfasToken
- ToBase64String
- ASCII.GetBytes
Expected result: no active matches remain.
Validation
After the migration, run a Preview/Test in HelloID for:
- create.ps1
- update.ps1
- delete.ps1
- disable.ps1
- enable.ps1
- import.ps1
Common Failure Causes
- The AFAS App Connector is not configured for OAuth client credentials.
- ClientId or ClientSecret was copied incorrectly.
- The App Connector lacks required Get/Update connector permissions.
- One script was missed and still uses classic token authentication.
Short Checklist
- Arrange OAuth client credentials in AFAS.
- Update configuration.json: add ClientId and ClientSecret, remove Token.
- Replace all AfasToken logic with OAuth Bearer headers in create/update/delete/disable/enable/import.
- Search for leftover classic-auth keywords.
- Run Preview/Test for all actions and import.
AFAS OAuth Migration Runbook (Target Users)
Purpose
This document helps migrate an existing AFAS Profit target connector for users from classic token authentication to OAuth client credentials.
Use targeted changes only. Do not replace complete scripts, because customer-specific logic may already be present.
Scope
Apply these changes to:
Preconditions In AFAS
Before changing the connector, make sure the customer has arranged the following in AFAS Profit:
Important: advise customers to use an OAuth-only App Connector. AFAS states that in September 2026 existing Classic tokens will automatically get an end date of 15 February 2027. From that date those tokens no longer work. New Classic tokens can still be created with another end date until 31 August 2027. App connectors that have not been used for 6 months or longer are blocked.
See AFAS documentation for more information: Eigen app connector inrichten in vogelvlucht and Eigen app connector beheren.
Required connectors:
Summary Of The Change
Classic flow:
OAuth flow:
Recommended Working Method
Step 1: Update configuration.json
Remove (located after the
BaseUriobject):{ "key": "Token", "type": "input", "defaultValue": "", "templateOptions": { "label": "Token in XML format", "type": "password", "placeholder": "<token><version>1</version><data>D5R324DD5F4TRD945E530ED3CDD70D94BBDEC4C732B43F285ECB12345678</data></token>", "description": "", "required": true } },Insert after the
BaseUriobject:{ "key": "ClientId", "type": "input", "templateOptions": { "label": "ClientId", "placeholder": "Example: 2f8a2f4d-9a5f-41d8-aec8-6ab123456789", "description": "The OAuth client id of the AFAS AppConnector.", "required": true } }, { "key": "ClientSecret", "type": "input", "templateOptions": { "label": "ClientSecret", "type": "password", "placeholder": "Example: 1234567890abcdef1234567890abcdef12345678", "description": "The OAuth client secret of the AFAS AppConnector.", "required": true } },Step 2: Update create/update/delete/disable/enable/import scripts
All scripts (create.ps1, update.ps1, delete.ps1, disable.ps1, enable.ps1, import.ps1) — replace the classic header block:
Before:
After:
Step 3: Search terms to confirm classic auth is fully removed
Search all scripts for:
Expected result: no active matches remain.
Validation
After the migration, run a Preview/Test in HelloID for:
Common Failure Causes
Short Checklist