Overview
Since PFIMCORE-3074, IntegrationManager can authenticate to a Pricefx partition with OAuth credentials instead of partition basic auth. The connection type is pricefx-client-oauth and it works as follows:
-
The client secret stored in the connection is a long-lived refresh token issued by the partition.
-
IM exchanges the refresh token for a short-lived access token at
https://<instance>/pricefx/<partition>/oauth/token(grant_type=refresh_token). -
Every IM call to Core then carries an
Authorization: Bearer <access_token>header. The token is cached and refreshed automatically before it expires.
|
Attribute |
Details |
|---|---|
|
Connection type |
|
|
Core requirement |
Partition release 15.3 or later (OAuth support is experimental) |
|
Credential |
|
|
Default name behavior |
When named |
|
Fallback |
Deploy a basic-auth |
Prerequisites
-
The partition runs Core release 15.3 or later. On older releases the
/oauth/*endpoints return HTTP 404. -
You can edit Advanced Configuration Options on the partition (administrator access).
-
You can sign in to the partition in a browser as the user the IM connection should act as.
Step 1 — Register the OAuth client on the partition
OAuth clients are registered in the oauthConfiguration advanced configuration option. In the partition UI, go to Administration → Configuration → Advanced Configuration Options and create (or extend) oauthConfiguration:
{
"knownClients": {
"im-client": {
"redirect_uri": "http://localhost:8000/callback",
"token_expiry": 7200,
"client_description": "IntegrationManager OAuth client"
}
}
}
-
The JSON key (
im-client) is theclient_idthe client sends — choose your own, but use it consistently in all following steps. -
redirect_uriis mandatory and matched as an exact string (protocol, host, port, path, trailing slash). For a non-interactive client like IM, a placeholder such ashttp://localhost:8000/callbackis fine — nothing needs to listen there. -
token_expiryis the access-token lifetime in seconds (default 7200).
The option can also be set through the API: POST /pricefx/<partition>/configurationmanager.set/oauthConfiguration.
Step 2 — Obtain the authorization code
Core currently implements only the Authorization Code grant, so the initial credential issuance is a one-time manual browser flow.
-
Sign in to the partition in a browser as the user the IM connection should act as. Use a private browser window to avoid a stale session on a different partition.
-
Open the authorization URL (note the URL-encoded
redirect_uri):
https://<instance>/pricefx/<partition>/oauth/authorize?response_type=code&client_id=im-client&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fcallback
-
Confirm the consent screen. The browser is redirected to
http://localhost:8000/callback?code=<CODE>— the page does not load (nothing listens there), but thecodeis in the address bar. Copy it.
The code is valid for 10 minutes and can be used only once. If it expires or the exchange fails, repeat this step.
Step 3 — Exchange the code for tokens
curl -s -X POST "https://<instance>/pricefx/<partition>/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=<CODE>&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fcallback&client_id=im-client"
The response contains both tokens:
{
"access_token": "eyJhbGciOiJSUzI1NiJ9...",
"token_type": "bearer",
"expires_in": 7200,
"refresh_token": "eyJhbGciOiJSUzI1NiJ9..."
}
Store the refresh_token — that is the value for the IM connection's clientSecret. The refresh token currently has an unlimited lifetime (subject to review on the Core side).
Step 4 — Verify the tokens without IM
Verify the refresh flow (this is exactly the request IM sends at runtime):
curl -s -X POST "https://<instance>/pricefx/<partition>/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token&refresh_token=<REFRESH_TOKEN>&client_id=im-client"
Verify the access token on a regular API call:
curl -s -H "Authorization: Bearer <ACCESS_TOKEN>" "https://<instance>/pricefx/<partition>/ping"
Step 5 — Configure the IM connection
Create connections/pricefx.json in the instance repository:
{
"id": "pricefx",
"discriminator": "net.pricefx.integration.component.rest.domain.connection.PriceFxOAuthConnection",
"uri": "https://<instance>/pricefx",
"partition": "<partition>",
"clientId": "im-client",
"clientSecret": "<REFRESH_TOKEN>"
}
-
clientSecretis encrypted at rest by IM the same way as the basic-authpassword(stored as{ENC}...when auto-encrypt is enabled). -
For local development, keep the secret out of git with
local-secret.properties:connections.pricefx.clientSecret=<REFRESH_TOKEN>. -
The
partitionvalue must match the partition the refresh token was issued on — the token carries the partition as a JWT claim and Core validates it.
Step 6 — Verify in IM
-
Run the connection test (
POST /api/connections/test, or the test button in PlatformManager). The OAuth connection test acquires a real access token, so a success proves the whole flow. -
Run any route using the connection; with
"debug": truethe client log showsAuthorization: Bearerheaders instead ofBasic.
Switching between basic auth and OAuth
The authentication mode is determined by which connection type is deployed. To switch a partition to OAuth, replace the basic-auth pricefx connection JSON with the OAuth one (same id); to fall back, deploy the basic-auth JSON again. Connections hot-reload, so no restart is needed and cached tokens are discarded on redeploy.
Troubleshooting
|
Error |
Cause |
Fix |
|---|---|---|
|
|
The |
Send the identical, correctly URL-encoded value in both requests. |
|
|
The refresh token was issued on a different partition than the token endpoint being called — the |
Decode the JWT payload (second dot-separated segment, base64) and check the |
|
|
The authorization code expired (10 minutes) or was already used (single use). |
Repeat Step 2 to obtain a fresh code. |
|
HTTP 404 on |
The partition release is older than 15.3. |
Upgrade the partition or keep basic auth. |
|
IM fails with |
The refresh token is invalid, revoked, or the client was removed from |
Re-issue credentials (Steps 2–3) and update the connection. |
Security notes
-
The refresh token is equivalent to a password — treat it accordingly. IM encrypts it at rest, masks it in logs and
toString, and blocks access to it from the Groovy sandbox. -
Access to the
access_tokenandclientSecretgetters is restricted in sandboxed Groovy expressions. -
Removing the client from
oauthConfigurationon the partition invalidates the credentials; IM surfaces a non-recoverable error and does not retry.