Skip to content

Add REST APIs for multiple client secrets and secret expiry - #1154

Open
AfraHussaindeen wants to merge 3 commits into
wso2:masterfrom
AfraHussaindeen:master_multi-secrets
Open

Add REST APIs for multiple client secrets and secret expiry#1154
AfraHussaindeen wants to merge 3 commits into
wso2:masterfrom
AfraHussaindeen:master_multi-secrets

Conversation

@AfraHussaindeen

@AfraHussaindeen AfraHussaindeen commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Purpose

Expose the multiple client secrets lifecycle and client‑secret expiry through the Application Management REST API (v1). Adds dedicated endpoints to create, list, retrieve, and delete an application's OAuth2/OIDC client secrets, and surfaces the latest secret's expiry on the OIDC inbound configuration.

New endpoints (/applications/{applicationId}/inbound-protocols/oidc/secrets)

Method Path Description Required scope
POST /secrets Create a new client secret. Existing secrets, access/refresh tokens, and authorization codes remain valid. 409 when the per‑app secret limit is reached. internal_application_mgt_client_secret_create
GET /secrets List metadata of all client secrets of the application. internal_application_mgt_client_secret_view
GET /secrets/{secretId} Get a single client secret's metadata. internal_application_mgt_client_secret_view
DELETE /secrets/{secretId} Delete a client secret. The latest (active) secret cannot be deleted — at least one active secret must remain (409). internal_application_mgt_client_secret_delete
  • The existing POST …/oidc/regenerate-secret now requires the dedicated internal_application_mgt_client_secret_regenerate scope (it adds a new secret, removes all existing ones, and revokes the app's tokens). When the multiple client secrets feature is disabled, it falls back to internal_application_mgt_client_secret_create.
  • Organization‑level callers use the internal_org_application_mgt_client_secret_* variants.

New API models

  • ClientSecretCreationRequestexpiresAt (Unix epoch seconds; must be a future time; 0 or omitted = non‑expiring).

  • ClientSecretResponsesecretId, secretValue, expiresAt, status (ACTIVE/EXPIRED), latest.

  • ClientSecretListcount, list[].

  • OpenIDConnectConfiguration additions

    • clientSecretExpiresAt — expiry of the client secret as Unix epoch seconds (0 = never). On create, sets the initial secret's expiry.
    • multipleClientSecretsConfigured — flag indicating the app holds more than one secret.

    Both fields are effective in requests and present in responses only when multiple client secrets is enabled, and are stripped from the response when the caller lacks the client‑secret view scope.

Notes

  • Feature‑gated by the multiple‑client‑secrets configuration; when disabled, the new secret endpoints are rejected and the new OIDC config fields are neither accepted in requests nor returned in responses.
  • Secret‑limit and last‑secret violations map to 409 Conflict.

Related PRs

Related Issue

To be merged after

wso2-extensions/identity-inbound-auth-oauth#3284
wso2/carbon-identity-framework#8226

@AfraHussaindeen
AfraHussaindeen marked this pull request as draft July 28, 2026 01:56
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary

Adds REST APIs to manage multiple OAuth client secrets throughout their lifecycle.

Changes

  • Adds endpoints to create, list, retrieve, and delete client secrets.
  • Adds client-secret expiration and multiple-secret status to OIDC configuration.
  • Adds request, response, and list models for client-secret operations.
  • Updates OAuth model mappings and service integrations.
  • Updates secret regeneration and client revocation documentation.
  • Adds handling for invalid secret IDs, secret limits, and invalid deletion requests.

Walkthrough

The application management API now supports OAuth client-secret creation, listing, retrieval, and deletion. OpenAPI definitions add lifecycle endpoints, request and response schemas, scopes, validation responses, and secret metadata. REST and application services delegate operations with the OAuth client ID and tenant domain. OAuth functions invoke the client-secret service, convert DTOs, and map failures to API errors. Unauthorized responses remove secret-related metadata. OIDC configuration mappings include secret expiration and multiple-secret status.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ApplicationsApiServiceImpl
  participant ServerApplicationManagementService
  participant OAuthInboundFunctions
  participant OAuthClientSecretService
  Client->>ApplicationsApiServiceImpl: request client-secret operation
  ApplicationsApiServiceImpl->>ServerApplicationManagementService: delegate application operation
  ServerApplicationManagementService->>OAuthInboundFunctions: resolve client ID and tenant domain
  OAuthInboundFunctions->>OAuthClientSecretService: create, list, retrieve, or delete secret
  OAuthClientSecretService-->>OAuthInboundFunctions: return secret DTO or operation result
  OAuthInboundFunctions-->>ServerApplicationManagementService: return mapped API result
  ServerApplicationManagementService-->>ApplicationsApiServiceImpl: return HTTP response
  ApplicationsApiServiceImpl-->>Client: return client-secret response
Loading
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description explains the feature and related work but omits most required template sections, including the checklist, release note, testing, security, documentation, and migration details. Complete the required template sections and provide testing, security, documentation, release, migration, and checklist details.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main changes: REST APIs for multiple client secrets and support for secret expiry.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@AfraHussaindeen
AfraHussaindeen marked this pull request as ready for review August 4, 2026 23:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/ServerApplicationManagementService.java (1)

1883-1910: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract the repeated client-ID resolution into a helper.

The four new methods repeat the same two statements. regenerateOAuthApplicationSecret and revokeOAuthClient repeat them as well. A single private helper keeps the delegation methods to one line each.

♻️ Proposed refactor
+    private String getOAuthClientId(String applicationId) {
+
+        return getInboundAuthRequestConfig(applicationId, OAUTH2).getInboundAuthKey();
+    }
+
     public ClientSecretResponse createOAuthClientSecret(String applicationId,
                                                           ClientSecretCreationRequest request) {
 
-        InboundAuthenticationRequestConfig oauthInbound = getInboundAuthRequestConfig(applicationId, OAUTH2);
-        String clientId = oauthInbound.getInboundAuthKey();
-        return OAuthInboundFunctions.createClientSecret(clientId, request);
+        return OAuthInboundFunctions.createClientSecret(getOAuthClientId(applicationId), request);
     }
 
     public ClientSecretList getOAuthClientSecrets(String applicationId) {
 
-        InboundAuthenticationRequestConfig oauthInbound = getInboundAuthRequestConfig(applicationId, OAUTH2);
-        String clientId = oauthInbound.getInboundAuthKey();
-        return OAuthInboundFunctions.getClientSecrets(clientId);
+        return OAuthInboundFunctions.getClientSecrets(getOAuthClientId(applicationId));
     }
 
     public ClientSecretResponse getOAuthClientSecret(String applicationId, String secretId) {
 
-        InboundAuthenticationRequestConfig oauthInbound = getInboundAuthRequestConfig(applicationId, OAUTH2);
-        String clientId = oauthInbound.getInboundAuthKey();
-        return OAuthInboundFunctions.getClientSecret(clientId, secretId);
+        return OAuthInboundFunctions.getClientSecret(getOAuthClientId(applicationId), secretId);
     }
 
     public void deleteOAuthClientSecret(String applicationId, String secretId) {
 
-        InboundAuthenticationRequestConfig oauthInbound = getInboundAuthRequestConfig(applicationId, OAUTH2);
-        String clientId = oauthInbound.getInboundAuthKey();
-        OAuthInboundFunctions.deleteClientSecret(clientId, secretId);
+        OAuthInboundFunctions.deleteClientSecret(getOAuthClientId(applicationId), secretId);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/ServerApplicationManagementService.java`
around lines 1883 - 1910, Extract the repeated OAUTH2 inbound client-ID lookup
into a private helper in ServerApplicationManagementService, reusing the logic
from createOAuthClientSecret, getOAuthClientSecrets, getOAuthClientSecret, and
deleteOAuthClientSecret. Update those methods, along with
regenerateOAuthApplicationSecret and revokeOAuthClient, to call the helper and
retain their existing OAuthInboundFunctions delegation behavior.
components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/resources/applications.yaml (1)

1303-1308: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider documenting a Location header for the created secret.

Other creation operations in this contract declare a Location header on 201 (for example lines 99-103 and 152-156). The new secret resource is addressable at /applications/{applicationId}/inbound-protocols/oidc/secrets/{secretId}. Adding the header would align this operation with the existing convention. The implementation currently returns only the entity, so this change also requires a small update in ApplicationsApiServiceImpl.createOAuthClientSecret.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/resources/applications.yaml`
around lines 1303 - 1308, Document a Location header for the 201 response of the
client-secret creation operation, using the addressable secret resource path
under the application and secret identifiers. Update
ApplicationsApiServiceImpl.createOAuthClientSecret to return that Location
header along with the created entity, matching the existing creation-operation
convention.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/oauth2/ApiModelToOAuthConsumerApp.java`:
- Line 71: Guard the client-secret expiry mappings against null values: in
ApiModelToOAuthConsumerApp.java:71-71, call the OAuth consumer DTO expiry setter
only when oidcModel.getClientSecretExpiresAt() is non-null; in
OAuthInboundFunctions.java:303-317, call secretRequest.setExpiryTime(...) only
when request.getExpiresAt() is non-null, while preserving the existing request
!= null guard in createClientSecret.

In
`@components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/oauth2/OAuthInboundFunctions.java`:
- Around line 354-363: The toClientSecretResponse method should not map status
via valueOf(dto.getStatus().name()). Handle a null dto.getStatus() explicitly,
then translate each supported backend status to the corresponding
ClientSecretResponse.StatusEnum through an explicit mapping or dedicated
conversion method, with defined handling for unsupported values.

---

Nitpick comments:
In
`@components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/ServerApplicationManagementService.java`:
- Around line 1883-1910: Extract the repeated OAUTH2 inbound client-ID lookup
into a private helper in ServerApplicationManagementService, reusing the logic
from createOAuthClientSecret, getOAuthClientSecrets, getOAuthClientSecret, and
deleteOAuthClientSecret. Update those methods, along with
regenerateOAuthApplicationSecret and revokeOAuthClient, to call the helper and
retain their existing OAuthInboundFunctions delegation behavior.

In
`@components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/resources/applications.yaml`:
- Around line 1303-1308: Document a Location header for the 201 response of the
client-secret creation operation, using the addressable secret resource path
under the application and secret identifiers. Update
ApplicationsApiServiceImpl.createOAuthClientSecret to return that Location
header along with the created entity, matching the existing creation-operation
convention.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9a17accb-308a-40b1-b089-6bfb3b9131c9

📥 Commits

Reviewing files that changed from the base of the PR and between 9e144a5 and 4a11d64.

⛔ Files ignored due to path filters (6)
  • components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/ApplicationsApi.java is excluded by !**/gen/**
  • components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/ApplicationsApiService.java is excluded by !**/gen/**
  • components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/ClientSecretCreationRequest.java is excluded by !**/gen/**
  • components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/ClientSecretList.java is excluded by !**/gen/**
  • components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/ClientSecretResponse.java is excluded by !**/gen/**
  • components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/OpenIDConnectConfiguration.java is excluded by !**/gen/**
📒 Files selected for processing (6)
  • components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/ServerApplicationManagementService.java
  • components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/oauth2/ApiModelToOAuthConsumerApp.java
  • components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/oauth2/OAuthConsumerAppToApiModel.java
  • components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/oauth2/OAuthInboundFunctions.java
  • components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/impl/ApplicationsApiServiceImpl.java
  • components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/resources/applications.yaml

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant