[
https://issues.apache.org/jira/browse/KNOX-3480?focusedWorklogId=1043492&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1043492
]
ASF GitHub Bot logged work on KNOX-3480:
----------------------------------------
Author: ASF GitHub Bot
Created on: 23/Sep/26 08:21
Start Date: 23/Sep/26 08:21
Worklog Time Spent: 10m
Work Description: smolnar82 opened a new pull request, #1422:
URL: https://github.com/apache/knox/pull/1422
[KNOX-3480](https://issues.apache.org/jira/browse/KNOX-3480) - Support
user-supplied clientId in the Client Credentials endpoint
## What changes were proposed in this pull request?
The `clientid/api/v1/oauth/credentials` endpoint
(`ClientCredentialsResource`) previously always returned a server-generated
UUID as the `client_id`, which is persisted as the `KNOX_TOKENS.token_id`
primary key. Well-known IdPs (Auth0, Okta, Keycloak) instead let the caller
choose the client identifier at registration time. This PR adds the same
capability:
- **New topology service param `clientid.allowUserSuppliedClientId` (default
`false`).** When enabled, a caller-supplied `clientId` query param becomes the
token's `knox.id` claim / `token_id`. When disabled or the param is omitted,
behavior is unchanged (a UUID is generated).
- **JWT minting:** threaded an optional `tokenId` through
`JWTokenAttributes` / `JWTokenAttributesBuilder`; `JWTToken` uses it as the
`knox.id` claim when present, otherwise a random UUID
(`TokenResource.getRequestedTokenId()` hook, defaulting to null).
- **Validation:** a supplied `clientId` must match `^[A-Za-z0-9._-]{1,128}$`
(matching the `token_id` column width); otherwise `400 Bad Request`
(`invalid_request`).
- **Uniqueness:** enforced atomically by the `token_id` primary key (no
check-then-insert race across an HA pair). A duplicate surfaces as the new
unchecked `TokenAlreadyExistsException` (translated from a DB unique-constraint
violation in `JDBCTokenStateService`, best-effort on the in-memory
`DefaultTokenStateService`), which the resource maps to `409 Conflict`
(`invalid_client`) rather than a generic 500.
- Documented the new param and behavior in
`knox-site/docs/config_client_credentials.md`.
## How was this patch tested?
- **Unit tests** (all pass):
- `TokenServiceResourceTest` — enabled+valid → `client_id` equals supplied
value; disabled or omitted → UUID; invalid (bad chars / >128) → 400; duplicate
→ 409.
-
`JDBCTokenStateServiceTest#testAddDuplicateTokenIdThrowsTokenAlreadyExists` —
H2-backed duplicate `token_id` insert surfaces as
`TokenAlreadyExistsException`, one row survives.
- `JWTTokenTest` — supplied token id becomes the `knox.id` claim verbatim;
blank falls back to UUID.
- Run: `mvn -pl gateway-spi,gateway-service-knoxtoken,gateway-server -am
test`
## Integration Tests
Added `.github/workflows/tests/test_clientid_credentials.py` plus two
bind-mounted topologies (`clientid.xml` with the feature ON,
`clientid-default.xml` with it OFF). The CI gateway runs on H2 (persistent,
PK-enforced), so the duplicate → 409 path is genuinely exercised.
Cases:
- supplied id used
- E2E passcode authenticates (custom id becomes the audit actor username)
omitted → UUID
- invalid → 400
- over-long → 400
- duplicate → 409, and supplied-but-ignored on the default (feature-off)
topology.
**All 109 CI integration tests pass.**:
```
tests-1 | ------------------------------------
tests-1 | Your code has been rated at 10.00/10
tests-1 |
tests-1 | Waiting for knox...
tests-1 | ============================= test session starts
==============================
tests-1 | platform linux
Issue Time Tracking
-------------------
Worklog Id: (was: 1043492)
Time Spent: 0.5h (was: 20m)
> Support user-supplied clientId in the Client Credentials endpoint
> -----------------------------------------------------------------
>
> Key: KNOX-3480
> URL: https://issues.apache.org/jira/browse/KNOX-3480
> Project: Apache Knox
> Issue Type: Task
> Components: JWT, Server
> Affects Versions: 3.0.0
> Reporter: Sandor Molnar
> Assignee: Sandor Molnar
> Priority: Major
> Fix For: 3.1.0
>
> Time Spent: 0.5h
> Remaining Estimate: 0h
>
> Today {{{}clientid/api/v1/oauth/credentials }} always returns a
> server-generated UUID as {{client_id{}}}, which is stored as
> {{{}KNOX_TOKENS.token_id{}}}. Well-known IdPs (Auth0, Okta, Keycloak) let the
> caller choose the client identifier at registration. Add the same capability
> to Knox.
> When the caller supplies a {{clientId}} query param, use that value as the
> token's {{knox.id/token_id}} instead of a generated UUID. When omitted,
> behavior is unchanged (random UUID). Uniqueness is backed by the
> {{KNOX_TOKENS.token_id}} primary key.
> Scope / implementation:
> - Read optional clientId param in {{{}ClientCredentialsResource{}}}; thread
> it down through TokenResource.getJWT() → JWTokenAttributes(Builder) →
> JWTToken so the {{knox.id}} claim uses the supplied value (fall back to
> UUID.randomUUID()).
> - Reject collisions explicitly (pre-check via TokenStateService) — do not
> depend on the DB PK, since the in-memory store overwrites silently.
> - Validate the supplied value: non-blank, length ≤128, restricted charset.
> Acceptance criteria:
> - clientId supplied → response client_id equals it, and it is the token_id
> row / passcode-auth works.
> - clientId omitted → unchanged UUID behavior.
> - Duplicate clientId → clear client error (not 500, not silent overwrite).
> - Invalid clientId (too long / bad chars) → clear client error.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)