Skip to content

Conversation

@ase-101
Copy link
Contributor

@ase-101 ase-101 commented Jan 25, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced error handling with new error codes for PKCE and configuration scenarios.
    • Improved feature configuration management through server profiles.
  • Bug Fixes

    • Refined PKCE validation with more descriptive error messaging.
  • Refactor

    • Consolidated feature flag initialization and simplified configuration flow.
    • Removed deprecated profile caching mechanism.

✏️ Tip: You can customize this high-level summary in your review settings.

Signed-off-by: ase-101 <sunkadaeanusha@gmail.com>
Signed-off-by: ase-101 <sunkadaeanusha@gmail.com>
@coderabbitai
Copy link

coderabbitai bot commented Jan 25, 2026

Walkthrough

This PR refactors server profile and feature flag handling by introducing a ServerProfile bean that centralizes feature configuration, replacing distributed feature map parameters with consolidated boolean flags in OIDCTransaction. It adds PKCE-related error codes and updates authorization flows to enforce PKCE requirements through per-transaction feature flags rather than global configuration.

Changes

Cohort / File(s) Summary
OpenAPI Specification
docs/esignet-openapi.yaml
Adds use_pkce error code to POST /client-mgmt/oidc-client, /authorize (oauth-details v1/v2/v3), and introduces invalid_additional_config error code to POST /client-mgmt/oauth-client
Error Constants & Core DTOs
esignet-core/src/main/java/io/mosip/esignet/core/constants/ErrorConstants.java, esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java, esignet-core/src/main/java/io/mosip/esignet/core/dto/ServerProfile.java
Adds USE_PKCE constant; refactors OIDCTransaction to replace additionalConfigMap with discrete boolean flags (requirePushedAuthorizationRequests, dpopBoundAccessToken, requirePKCE); introduces new ServerProfile DTO for profile name and feature map storage
Configuration & Repository Management
esignet-service/src/main/java/io/mosip/esignet/config/AppConfig.java, esignet-service/src/main/resources/application-default.properties, oidc-service-impl/src/main/java/io/mosip/esignet/repository/ServerProfileRepository.java
New serverProfile() bean loads profiles from repository and populates feature maps; removes server profile caching configuration and TTL settings; removes @Cacheable annotation from findByProfileName()
Service Layer Refactoring
oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java, oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java
Removes getFeaturesByProfileName() and related imports from AuthorizationHelperService; refactors AuthorizationServiceImpl to consolidate feature flag application via new setFeatureFlags() method, removes feature map parameters from checkAndBuildOIDCTransaction() and buildTransactionAndOAuthDetailResponse() overloads, adds PKCE enforcement via oidcTransaction.isRequirePKCE() with USE_PKCE error throwing
Test Coverage
esignet-service/src/test/java/io/mosip/esignet/AppConfigTest.java, oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationHelperServiceTest.java, oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java
New AppConfigTest covers profile loading and feature population; removes three getFeaturesByProfileName tests from AuthorizationHelperServiceTest; extends AuthorizationServiceTest with new ServerProfile mock, PKCE/PAR feature flag scenarios, and changes getOauthDetailsV2_withoutPKCE_thenFail expectation to USE_PKCE error
Integration Test Data
postman-collection/eSignet.postman_collection.json
Adds RSA JWK algorithm (alg: "RS256") and usage (use: "sig") parameters to public key setup

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • pvsaidurga

Poem

🐰 Server profiles now hop in place,
Feature flags dance with graceful grace,
PKCE's check won't let things slip,
Refactored flows make logic quip,
Constants spring where errors dwell! 🌳

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title 'ES-2712' is a ticket identifier that doesn't convey the actual changes made to the codebase. Use a descriptive title summarizing the main change, such as 'Refactor feature flags handling and add PKCE support' or 'Consolidate server profile feature configuration'.
Docstring Coverage ⚠️ Warning Docstring coverage is 7.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java`:
- Around line 75-90: Update the database seed in the esignet-server profile SQL
so that the fapi2.0 profile no longer sets require_pkce=true: remove or set
require_pkce to false for the fapi2.0 INSERT/UPDATE and keep only PAR
(require_pushed_authorization_requests), DPOP (dpop_bound_access_token), and JWE
settings; then add a new nisdsp profile row in the same seed script with
features require_pushed_authorization_requests=true,
dpop_bound_access_token=true, require_pkce=true and set the proper
userinfo_response_type value (and any related DPoP nonce TTL/JKT columns if
present) so that nisdsp contains PAR, DPoP, PKCE and the userinfo_response_type
as specified.

In `@esignet-service/src/main/java/io/mosip/esignet/config/AppConfig.java`:
- Around line 85-105: Handle a null serverProfile explicitly and replace the
hard-coded error string with a constant: in the serverProfile() method check if
(serverProfile == null || "none".equalsIgnoreCase(serverProfile)) then return
the empty profile to avoid passing null into
serverProfileRepository.findByProfileName; when throwing the exception use
ErrorConstants.INVALID_SERVER_PROFILE instead of the literal
"INVALID_SERVER_PROFILE"; and add a public static final String
INVALID_SERVER_PROFILE = "invalid_server_profile" to the ErrorConstants class so
the constant is defined.

In
`@oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java`:
- Around line 630-635: The Javadoc for the method in AuthorizationServiceImpl
describing defaults is inaccurate: the code actually defaults feature booleans
to false and response type to "JWS" rather than "all available features". Update
the Javadoc to state the actual default behavior (booleans default to false and
response type defaults to "JWS"), or if the intended behavior is to enable all
features by default, change the implementation in the method that sets
additional config on the OIDCTransaction to initialize those booleans to true
and response type accordingly; reference the AuthorizationServiceImpl method
that takes OIDCTransaction and adjusts server/client additional config and the
OIDCTransaction fields that store the booleans and response type to make the
change.

In
`@oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java`:
- Around line 115-117: Tests are failing because the `@Mock` ServerProfile returns
null for getFeatureMap(), causing an NPE when setFeatureFlags is exercised; in
the AuthorizationServiceTest setUp() method stub ServerProfile#getFeatureMap()
to return an empty Map (e.g., Collections.emptyMap()) so tests have a safe
default; update the setup in AuthorizationServiceTest (the setUp() method) to
add a when(serverProfile.getFeatureMap()).thenReturn(emptyMap) stub before
invoking code that calls setFeatureFlags.
🧹 Nitpick comments (3)
esignet-core/src/main/java/io/mosip/esignet/core/dto/ServerProfile.java (1)

12-17: Consider initializing featureMap to prevent potential NPE.

While the current usage in AppConfig.serverProfile() always sets the map, initializing the field defensively would prevent accidental NPE if the DTO is used elsewhere without explicit initialization.

♻️ Optional defensive initialization
 `@Data`
 public class ServerProfile {
 
     private String name;
-    private Map<String, String> featureMap;
+    private Map<String, String> featureMap = new HashMap<>();
 }
esignet-service/src/test/java/io/mosip/esignet/AppConfigTest.java (2)

34-35: Remove unused @Value annotation.

The @Value annotation has no effect in a @ExtendWith(MockitoExtension.class) test since Spring's property injection is not active. The field is never used as all tests set the value via ReflectionTestUtils.

♻️ Remove dead code
-    `@Value`("${mosip.esignet.server.profile:none}")
-    private String serverProfile;
-
     `@Test`
     void serverProfile_ServerProfileIsNone_returnsWithNoFeatures() throws EsignetException {

57-63: Test relies on implicit repository behavior for null input.

The test serverProfile_NullProfile_ThrowsException passes because findByProfileName(null) returns null or empty list. However, this test doesn't mock the repository behavior, making the assertion dependent on default mock behavior (returning null). Consider explicitly mocking for clarity.

♻️ Add explicit mock for clarity
 `@Test`
 void serverProfile_NullProfile_ThrowsException() {
     ReflectionTestUtils.setField(appConfig, "serverProfile", null);
+    when(serverProfileRepository.findByProfileName(null)).thenReturn(null);

     EsignetException exception = assertThrows(EsignetException.class, () -> appConfig.serverProfile());
     assertEquals("INVALID_SERVER_PROFILE", exception.getMessage());
 }

Comment on lines +75 to +90
//Shared flags between signup and eSignet services
String verificationStatus;
String verificationErrorCode;
String userInfoResponseType;

String[] prompt;
int consentExpireMinutes;

boolean requirePushedAuthorizationRequests;
boolean dpopBoundAccessToken;
boolean requirePKCE;
Map<String, String> additionalConfigMap;
String dpopJkt;
String dpopServerNonce;
Long dpopServerNonceTTL;

//Feature flags
boolean requirePushedAuthorizationRequests;
boolean dpopBoundAccessToken;
boolean requirePKCE;
String userInfoResponseType;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

rg -n --type=java "OIDCTransaction" -C3 | head -100

Repository: mosip/esignet

Length of output: 12740


🏁 Script executed:

rg -n --type=java "requirePKCE|requirePushedAuthorizationRequests|dpopBoundAccessToken" -C3 | head -150

Repository: mosip/esignet

Length of output: 864


🏁 Script executed:

rg -n --type=java "additionalConfigMap" -C3

Repository: mosip/esignet

Length of output: 39


🏁 Script executed:

rg -n --type=java "fapi2\.0|nisdsp" -C3 | head -100

Repository: mosip/esignet

Length of output: 2365


🏁 Script executed:

fd -n "ServerProfile" --type f

Repository: mosip/esignet

Length of output: 287


🏁 Script executed:

rg -n --type=java "setRequirePKCE|setRequirePushedAuthorizationRequests|setDpopBoundAccessToken" -C5

Repository: mosip/esignet

Length of output: 18881


🏁 Script executed:

rg -n --type=java "getFeaturesByProfileName" -C5 | head -80

Repository: mosip/esignet

Length of output: 926


🏁 Script executed:

rg -n --type=java "class ServerProfile" -A20

Repository: mosip/esignet

Length of output: 4269


🏁 Script executed:

rg -n --type=java "REQUIRE_PKCE|REQUIRE_PAR|DPOP_BOUND_ACCESS_TOKENS" -C2 | head -100

Repository: mosip/esignet

Length of output: 10946


🏁 Script executed:

rg -n --type=java "serverProfile\|ServerProfile" oidc-service-impl/src/main/java -A5 | head -150

Repository: mosip/esignet

Length of output: 39


🏁 Script executed:

rg -n --type=java "cache.*ttl\|TTL\|Cache.*config" -C3 | head -100

Repository: mosip/esignet

Length of output: 39


🏁 Script executed:

rg -n --type=java "@Cacheable|CacheManager|cache.put" -C3 | head -80

Repository: mosip/esignet

Length of output: 9962


🏁 Script executed:

rg -n --type=java "setFeatureFlags" -B3 -A3

Repository: mosip/esignet

Length of output: 8085


🏁 Script executed:

rg -n --type=java "cache.*expire\|cache.*ttl\|redis\.timeout\|spring.cache" -i | head -80

Repository: mosip/esignet

Length of output: 39


🏁 Script executed:

rg -n --type=properties "cache\|redis\|ttl" esignet-service/src/main/resources | head -100

Repository: mosip/esignet

Length of output: 91


🏁 Script executed:

cat esignet-service/src/main/resources/application-default.properties | head -100

Repository: mosip/esignet

Length of output: 4738


🏁 Script executed:

rg -n --type=java "fapi2|nisdsp" -C5 | head -150

Repository: mosip/esignet

Length of output: 3492


🏁 Script executed:

rg -n --type=java "ServerProfile" oidc-service-impl/src/main/java -A10 | head -100

Repository: mosip/esignet

Length of output: 7221


🏁 Script executed:

rg -n "INSERT INTO" | grep -i "profile\|feature" | head -20

Repository: mosip/esignet

Length of output: 1302


🏁 Script executed:

rg -n "INSERT INTO.*server_profile" -A1

Repository: mosip/esignet

Length of output: 1524


🏁 Script executed:

cat db_scripts/mosip_esignet/dml/esignet-server_profile.sql

Repository: mosip/esignet

Length of output: 284


🏁 Script executed:

cat db_upgrade_script/mosip_esignet/sql/1.7.1_to_1.8.0_upgrade.sql | grep -A20 "INSERT INTO.*server_profile"

Repository: mosip/esignet

Length of output: 477


🏁 Script executed:

cat db_scripts/mosip_esignet/dml/esignet-server_profile.sql | head -20

Repository: mosip/esignet

Length of output: 284


🏁 Script executed:

rg -n "nisdsp" -C3

Repository: mosip/esignet

Length of output: 2365


🏁 Script executed:

rg -n "nisdsp.*PKCE\|nisdsp.*PAR\|nisdsp.*DPOP"

Repository: mosip/esignet

Length of output: 39


🏁 Script executed:

fd esignet-server_profile

Repository: mosip/esignet

Length of output: 168


🏁 Script executed:

rg -n "profile_name.*nisdsp"

Repository: mosip/esignet

Length of output: 39


🏁 Script executed:

cat db_scripts/mosip_esignet/dml/esignet-server_profile.sql

Repository: mosip/esignet

Length of output: 284


🏁 Script executed:

cat db_upgrade_script/mosip_esignet/sql/1.7.1_to_1.8.0_upgrade.sql | grep -A30 "server_profile"

Repository: mosip/esignet

Length of output: 718


Fix server profile database configuration: fapi2.0 should not include PKCE

The database profile configuration violates the documented profile specifications. The fapi2.0 profile currently includes PKCE (as seen in db_scripts/mosip_esignet/dml/esignet-server_profile.sql), but per profile constraints, fapi2.0 should only enable PAR, DPOP, and JWE. The require_pkce feature should be exclusive to the nisdsp profile. Additionally, the nisdsp profile configuration is missing entirely from the database initialization scripts and should be added with features: PAR, DPOP, PKCE, and userinfo_response_type.

Update the database seed data to remove PKCE from fapi2.0 and add the complete nisdsp profile with the correct feature set.

🤖 Prompt for AI Agents
In `@esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java`
around lines 75 - 90, Update the database seed in the esignet-server profile SQL
so that the fapi2.0 profile no longer sets require_pkce=true: remove or set
require_pkce to false for the fapi2.0 INSERT/UPDATE and keep only PAR
(require_pushed_authorization_requests), DPOP (dpop_bound_access_token), and JWE
settings; then add a new nisdsp profile row in the same seed script with
features require_pushed_authorization_requests=true,
dpop_bound_access_token=true, require_pkce=true and set the proper
userinfo_response_type value (and any related DPoP nonce TTL/JKT columns if
present) so that nisdsp contains PAR, DPoP, PKCE and the userinfo_response_type
as specified.

Comment on lines +85 to +105
public ServerProfile serverProfile() throws EsignetException {
ServerProfile profile = new ServerProfile();
profile.setName(serverProfile);
final Map<String, String> profileDataMap = new HashMap<>();
profile.setFeatureMap(profileDataMap);

if("none".equalsIgnoreCase(serverProfile)) {
return profile;
}

List<io.mosip.esignet.entity.ServerProfile> profiles = serverProfileRepository.findByProfileName(serverProfile);
if (profiles == null || profiles.isEmpty()) {
log.error("**** No features found for the configured server profile: {} ****", serverProfile);
throw new EsignetException("INVALID_SERVER_PROFILE");
}

for (io.mosip.esignet.entity.ServerProfile serverProfileEntity : profiles) {
profileDataMap.put(serverProfileEntity.getAdditionalConfigKey(), serverProfileEntity.getFeature());
}
return profile;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Handle null serverProfile explicitly and define the error constant.

Two issues identified:

  1. When serverProfile is null, the equalsIgnoreCase check on line 91 returns false, causing a repository query with null parameter. This relies on implicit behavior. Explicit null handling would be clearer.

  2. The error code "INVALID_SERVER_PROFILE" is not defined in ErrorConstants. For consistency with the codebase, define it there.

🔧 Suggested fix

Add to ErrorConstants.java:

public static final String INVALID_SERVER_PROFILE = "invalid_server_profile";

Update the method:

 `@Bean`
 public ServerProfile serverProfile() throws EsignetException {
     ServerProfile profile = new ServerProfile();
     profile.setName(serverProfile);
     final Map<String, String> profileDataMap = new HashMap<>();
     profile.setFeatureMap(profileDataMap);

+    if(serverProfile == null) {
+        log.error("**** Server profile is not configured ****");
+        throw new EsignetException(ErrorConstants.INVALID_SERVER_PROFILE);
+    }
+
     if("none".equalsIgnoreCase(serverProfile)) {
         return profile;
     }

     List<io.mosip.esignet.entity.ServerProfile> profiles = serverProfileRepository.findByProfileName(serverProfile);
     if (profiles == null || profiles.isEmpty()) {
         log.error("**** No features found for the configured server profile: {} ****", serverProfile);
-        throw new EsignetException("INVALID_SERVER_PROFILE");
+        throw new EsignetException(ErrorConstants.INVALID_SERVER_PROFILE);
     }
🤖 Prompt for AI Agents
In `@esignet-service/src/main/java/io/mosip/esignet/config/AppConfig.java` around
lines 85 - 105, Handle a null serverProfile explicitly and replace the
hard-coded error string with a constant: in the serverProfile() method check if
(serverProfile == null || "none".equalsIgnoreCase(serverProfile)) then return
the empty profile to avoid passing null into
serverProfileRepository.findByProfileName; when throwing the exception use
ErrorConstants.INVALID_SERVER_PROFILE instead of the literal
"INVALID_SERVER_PROFILE"; and add a public static final String
INVALID_SERVER_PROFILE = "invalid_server_profile" to the ErrorConstants class so
the constant is defined.

Comment on lines 630 to 635
/**
* Set additional config in OIDC transaction based on openid profile and client additional config
* Set additional config in OIDC transaction based on configured server profile and client additional config.
* Priority is given to server profile config
* Second priority is given to client additional config
* Otherwise the default value is set to all the available features
* @param oidcTransaction {@link OIDCTransaction}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Javadoc default-feature statement doesn’t match behavior.
The comment says defaults are “all available features,” but the implementation defaults booleans to false and response type to "JWS". Please align the comment with the actual behavior (or adjust defaults if that was intended).

🤖 Prompt for AI Agents
In
`@oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java`
around lines 630 - 635, The Javadoc for the method in AuthorizationServiceImpl
describing defaults is inaccurate: the code actually defaults feature booleans
to false and response type to "JWS" rather than "all available features". Update
the Javadoc to state the actual default behavior (booleans default to false and
response type defaults to "JWS"), or if the intended behavior is to enable all
features by default, change the implementation in the method that sets
additional config on the OIDCTransaction to initialize those booleans to true
and response type accordingly; reference the AuthorizationServiceImpl method
that takes OIDCTransaction and adjusts server/client additional config and the
OIDCTransaction fields that store the booleans and response type to make the
change.

Comment on lines +115 to +117
@Mock
private ServerProfile serverProfile;

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Stub the ServerProfile feature map in test setup.
The new @Mock ServerProfile returns null for getFeatureMap() unless stubbed, which can NPE in tests that reach setFeatureFlags (unless prod code now guards). Add a default empty map in setUp() to keep tests stable.

🧪 Default empty feature map stub
     when(environment.getActiveProfiles()).thenReturn(new String[]{"test"});
+    when(serverProfile.getFeatureMap()).thenReturn(Collections.emptyMap());
🤖 Prompt for AI Agents
In
`@oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java`
around lines 115 - 117, Tests are failing because the `@Mock` ServerProfile
returns null for getFeatureMap(), causing an NPE when setFeatureFlags is
exercised; in the AuthorizationServiceTest setUp() method stub
ServerProfile#getFeatureMap() to return an empty Map (e.g.,
Collections.emptyMap()) so tests have a safe default; update the setup in
AuthorizationServiceTest (the setUp() method) to add a
when(serverProfile.getFeatureMap()).thenReturn(emptyMap) stub before invoking
code that calls setFeatureFlags.

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