-
Notifications
You must be signed in to change notification settings - Fork 400
Add changes required for FAPI 2.0 compliance #2963
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
|
||
| return authorizationResponseIssParameterSupported; | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 1
| public void setAuthorizationResponseIssParameterSupported(Boolean authorizationResponseIssParameterSupported) { | |
| log.debug("Setting authorizationResponseIssParameterSupported to: " + authorizationResponseIssParameterSupported); |
| configMap.put(DiscoveryConstants.AUTHORIZATION_DETAILS_TYPES_SUPPORTED, | ||
| this.authorizationDetailsTypesSupported); | ||
| configMap.put(DiscoveryConstants.AUTHORIZATION_RESPONSE_ISS_PARAMETER_SUPPORTED, | ||
| this.authorizationResponseIssParameterSupported); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 2
| this.authorizationResponseIssParameterSupported); | |
| this.authorizationResponseIssParameterSupported); | |
| if (log.isDebugEnabled()) { | |
| log.debug("Configuration map created with " + configMap.size() + " entries"); | |
| } |
| providerConfig | ||
| .setAuthorizationDetailsTypesSupported(authorizationDetailTypes.stream().toArray(String[]::new)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 3
| providerConfig | |
| .setAuthorizationDetailsTypesSupported(authorizationDetailTypes.stream().toArray(String[]::new)); | |
| providerConfig | |
| .setAuthorizationDetailsTypesSupported(authorizationDetailTypes.stream().toArray(String[]::new)); | |
| if (log.isDebugEnabled()) { | |
| log.debug("Setting authorization details types supported: " + authorizationDetailTypes.size() + " types"); | |
| } |
| if (OAuth2Util.isFapi2Enabled()) { | ||
| providerConfig.setAuthorizationResponseIssParameterSupported(Boolean.TRUE); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 4
| if (OAuth2Util.isFapi2Enabled()) { | |
| providerConfig.setAuthorizationResponseIssParameterSupported(Boolean.TRUE); | |
| } | |
| if (OAuth2Util.isFapi2Enabled()) { | |
| providerConfig.setAuthorizationResponseIssParameterSupported(Boolean.TRUE); | |
| log.info("FAPI 2.0 enabled: Setting authorization response ISS parameter support to true"); | |
| } |
| if (isFapiConformant(oAuthAuthzRequest.getClientId()) && OAuth2Util.isFapi1Enabled()) { | ||
| EndpointUtil.validateFAPIAllowedResponseTypeAndMode(oauthParams.get(RESPONSE_TYPE), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 5
| if (isFapiConformant(oAuthAuthzRequest.getClientId()) && OAuth2Util.isFapi1Enabled()) { | |
| EndpointUtil.validateFAPIAllowedResponseTypeAndMode(oauthParams.get(RESPONSE_TYPE), | |
| if (isFapiConformant(oAuthAuthzRequest.getClientId()) && OAuth2Util.isFapi1Enabled()) { | |
| log.info("Processing FAPI 1.0 conformant authorization request for client: " + oAuthAuthzRequest.getClientId()); | |
| EndpointUtil.validateFAPIAllowedResponseTypeAndMode(oauthParams.get(RESPONSE_TYPE), |
| } else if (isFapiConformant(oAuthAuthzRequest.getClientId()) && OAuth2Util.isFapi1Enabled()) { | ||
| /* Mandate request object for FAPI 1.0 Advanced requests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 6
| } else if (isFapiConformant(oAuthAuthzRequest.getClientId()) && OAuth2Util.isFapi1Enabled()) { | |
| /* Mandate request object for FAPI 1.0 Advanced requests | |
| } else if (isFapiConformant(oAuthAuthzRequest.getClientId()) && OAuth2Util.isFapi1Enabled()) { | |
| log.warn("Request object is missing for FAPI 1.0 Advanced client: " + oAuthAuthzRequest.getClientId()); | |
| /* Mandate request object for FAPI 1.0 Advanced requests |
|
|
||
| if (isFapiConformant(params.getClientId())) { | ||
| if (isFapiConformant(params.getClientId()) && OAuth2Util.isFapi1Enabled()) { | ||
| EndpointUtil.validateFAPIAllowedResponseTypeAndMode(params.getResponseType(), params.getResponseMode()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 7
| if (isFapiConformant(params.getClientId())) { | |
| if (isFapiConformant(params.getClientId()) && OAuth2Util.isFapi1Enabled()) { | |
| EndpointUtil.validateFAPIAllowedResponseTypeAndMode(params.getResponseType(), params.getResponseMode()); | |
| } | |
| if (isFapiConformant(params.getClientId()) && OAuth2Util.isFapi1Enabled()) { | |
| log.debug("FAPI 1.0 validation enabled for client: " + params.getClientId()); | |
| EndpointUtil.validateFAPIAllowedResponseTypeAndMode(params.getResponseType(), params.getResponseMode()); | |
| } |
| if (isFapiConformant(oAuthMessage.getClientId()) && OAuth2Util.isFapi2Enabled()) { | ||
| /* For FAPI 2.0 compliance, state parameter sent in the par request should be returned in the | ||
| authorization response */ | ||
| Object parState = oAuthMessage.getRequest().getAttribute(ParConstants.PAR_STATE); | ||
| if (parState != null) { | ||
| params.setState(parState.toString()); | ||
| } | ||
| } else { | ||
| params.setState(oauthRequest.getState()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 8
| if (isFapiConformant(oAuthMessage.getClientId()) && OAuth2Util.isFapi2Enabled()) { | |
| /* For FAPI 2.0 compliance, state parameter sent in the par request should be returned in the | |
| authorization response */ | |
| Object parState = oAuthMessage.getRequest().getAttribute(ParConstants.PAR_STATE); | |
| if (parState != null) { | |
| params.setState(parState.toString()); | |
| } | |
| } else { | |
| params.setState(oauthRequest.getState()); | |
| } | |
| if (isFapiConformant(oAuthMessage.getClientId()) && OAuth2Util.isFapi2Enabled()) { | |
| log.debug("FAPI 2.0 compliance check for client: " + oAuthMessage.getClientId()); | |
| /* For FAPI 2.0 compliance, state parameter sent in the par request should be returned in the | |
| authorization response */ | |
| Object parState = oAuthMessage.getRequest().getAttribute(ParConstants.PAR_STATE); | |
| if (parState != null) { | |
| log.debug("Using PAR state parameter for FAPI 2.0 compliant client"); | |
| params.setState(parState.toString()); | |
| } | |
| } else { | |
| params.setState(oauthRequest.getState()); | |
| } |
| @Test | ||
| public void testParseJsonTokenRequest() throws Exception { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 9
| @Test | |
| public void testParseJsonTokenRequest() throws Exception { | |
| @Test | |
| public void testParseJsonTokenRequest() throws Exception { | |
| log.info("Testing parseJsonTokenRequest method"); |
| Assert.fail("Expected TokenEndpointBadRequestException was not thrown"); | ||
| } catch (TokenEndpointBadRequestException e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 10
| Assert.fail("Expected TokenEndpointBadRequestException was not thrown"); | |
| } catch (TokenEndpointBadRequestException e) { | |
| } catch (TokenEndpointBadRequestException e) { | |
| log.debug("Expected exception caught for malformed JSON: " + e.getMessage()); | |
| assertTrue(e.getMessage().contains("Malformed or unsupported request payload")); |
| params = ParAuthServiceComponentDataHolder.getInstance().getParAuthService() | ||
| .retrieveParams(uuid, request.getParameter(OAuthConstants.OAuth20Params.CLIENT_ID)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 11
| params = ParAuthServiceComponentDataHolder.getInstance().getParAuthService() | |
| .retrieveParams(uuid, request.getParameter(OAuthConstants.OAuth20Params.CLIENT_ID)); | |
| params = ParAuthServiceComponentDataHolder.getInstance().getParAuthService() | |
| .retrieveParams(uuid, request.getParameter(OAuthConstants.OAuth20Params.CLIENT_ID)); | |
| if (log.isDebugEnabled()) { | |
| log.debug("Successfully retrieved PAR parameters for request UUID: " + uuid); | |
| } |
| } catch (ParClientException e) { | ||
| throw new ParAuthFailureException(e.getErrorCode(), e.getMessage(), e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 12
| } catch (ParClientException e) { | |
| throw new ParAuthFailureException(e.getErrorCode(), e.getMessage(), e); | |
| } catch (ParClientException e) { | |
| log.error("PAR client error occurred while retrieving parameters: " + e.getMessage()); | |
| throw new ParAuthFailureException(e.getErrorCode(), e.getMessage(), e); |
| useEntityIDAsIssuer = Boolean.parseBoolean(openIDConnectConfigElem.getFirstChildWithName( | ||
| getQNameWithIdentityNS(ConfigElements.OPENID_CONNECT_USE_ENTITY_ID_AS_ISSUER)). | ||
| getText().trim()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 13
| useEntityIDAsIssuer = Boolean.parseBoolean(openIDConnectConfigElem.getFirstChildWithName( | |
| getQNameWithIdentityNS(ConfigElements.OPENID_CONNECT_USE_ENTITY_ID_AS_ISSUER)). | |
| getText().trim()); | |
| } | |
| useEntityIDAsIssuer = Boolean.parseBoolean(openIDConnectConfigElem.getFirstChildWithName( | |
| getQNameWithIdentityNS(ConfigElements.OPENID_CONNECT_USE_ENTITY_ID_AS_ISSUER)). | |
| getText().trim()); | |
| log.info("UseEntityIdAsIssuer configuration loaded: " + useEntityIDAsIssuer); | |
| } |
| if (fapiElem.getFirstChildWithName(getQNameWithIdentityNS(ConfigElements.FAPI_VERSION)) != null) { | ||
| fapiVersion = fapiElem.getFirstChildWithName(getQNameWithIdentityNS( | ||
| ConfigElements.FAPI_VERSION)).getText().trim(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 14
| if (fapiElem.getFirstChildWithName(getQNameWithIdentityNS(ConfigElements.FAPI_VERSION)) != null) { | |
| fapiVersion = fapiElem.getFirstChildWithName(getQNameWithIdentityNS( | |
| ConfigElements.FAPI_VERSION)).getText().trim(); | |
| } | |
| if (fapiElem.getFirstChildWithName(getQNameWithIdentityNS(ConfigElements.FAPI_VERSION)) != null) { | |
| fapiVersion = fapiElem.getFirstChildWithName(getQNameWithIdentityNS( | |
| ConfigElements.FAPI_VERSION)).getText().trim(); | |
| log.info("FAPI version configured: " + fapiVersion); | |
| } |
| boolean isAuthorizedClient = authzHandler.isAuthorizedClient(authzReqMsgCtx); | ||
| if (!isAuthorizedClient) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 15
| boolean isAuthorizedClient = authzHandler.isAuthorizedClient(authzReqMsgCtx); | |
| if (!isAuthorizedClient) { | |
| boolean isAuthorizedClient = authzHandler.isAuthorizedClient(authzReqMsgCtx); | |
| if (!isAuthorizedClient) { | |
| if (log.isDebugEnabled()) { | |
| log.debug("Client is not authorized to use the requested authorization grant type. ClientId: " + authzReqDTO.getConsumerKey()); | |
| } |
| } catch (InvalidOAuthClientException e) { | ||
| throw new IdentityOAuth2Exception("Error occurred while retrieving the fapi conformance of the " + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 16
| } catch (InvalidOAuthClientException e) { | |
| throw new IdentityOAuth2Exception("Error occurred while retrieving the fapi conformance of the " + | |
| } catch (InvalidOAuthClientException e) { | |
| log.error("Error occurred while retrieving the FAPI conformance status for client: " + authzReqDTO.getConsumerKey(), e.getMessage()); | |
| throw new IdentityOAuth2Exception("Error occurred while retrieving the fapi conformance of the " + |
| try { | ||
| if (OAuth2Util.isFapiConformantApp(authorizationResponseDTO.getClientId()) && | ||
| OAuth2Util.isFapi2Enabled()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 17
| try { | |
| if (OAuth2Util.isFapiConformantApp(authorizationResponseDTO.getClientId()) && | |
| OAuth2Util.isFapi2Enabled()) { | |
| try { | |
| if (log.isDebugEnabled()) { | |
| log.debug("Checking FAPI conformance for client: " + authorizationResponseDTO.getClientId()); | |
| } | |
| if (OAuth2Util.isFapiConformantApp(authorizationResponseDTO.getClientId()) && |
| } catch (IdentityOAuth2Exception | InvalidOAuthClientException e) { | ||
| throw new OAuthRuntimeException("Error occurred while retrieving application details. ", e); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 18
| } catch (IdentityOAuth2Exception | InvalidOAuthClientException e) { | |
| throw new OAuthRuntimeException("Error occurred while retrieving application details. ", e); | |
| } | |
| } catch (IdentityOAuth2Exception | InvalidOAuthClientException e) { | |
| log.error("Error occurred while retrieving application details for client: " + authorizationResponseDTO.getClientId()); | |
| throw new OAuthRuntimeException("Error occurred while retrieving application details. ", e); |
| if (OAuthServerConfiguration.getInstance().getIsUseEntityIDAsIssuerEnabled() || isFapi2Enabled()) { | ||
| return getResidentIdpEntityId(tenantDomain); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 19
| if (OAuthServerConfiguration.getInstance().getIsUseEntityIDAsIssuerEnabled() || isFapi2Enabled()) { | |
| return getResidentIdpEntityId(tenantDomain); | |
| } | |
| if (OAuthServerConfiguration.getInstance().getIsUseEntityIDAsIssuerEnabled() || isFapi2Enabled()) { | |
| String entityId = getResidentIdpEntityId(tenantDomain); | |
| if (log.isDebugEnabled()) { | |
| log.debug("Using entity ID as issuer for tenant domain: " + tenantDomain + ", entity ID: " + entityId); | |
| } | |
| return entityId; | |
| } |
| */ | ||
| public static boolean isFapi2Enabled() { | ||
|
|
||
| return OAuthConstants.FAPIVersions.FAPI2.equals(OAuthServerConfiguration.getInstance().getFapiVersion()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 20
| */ | |
| public static boolean isFapi2Enabled() { | |
| return OAuthConstants.FAPIVersions.FAPI2.equals(OAuthServerConfiguration.getInstance().getFapiVersion()); | |
| } | |
| public static boolean isFapi2Enabled() { | |
| boolean isFapi2 = OAuthConstants.FAPIVersions.FAPI2.equals(OAuthServerConfiguration.getInstance().getFapiVersion()); | |
| if (log.isDebugEnabled()) { | |
| log.debug("FAPI 2.0 enabled status: " + isFapi2); | |
| } | |
| return isFapi2; | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AI Agent Log Improvement Checklist
- The log-related comments and suggestions in this review were generated by an AI tool to assist with identifying potential improvements. Purpose of reviewing the code for log improvements is to improve the troubleshooting capabilities of our products.
- Please make sure to manually review and validate all suggestions before applying any changes. Not every code suggestion would make sense or add value to our purpose. Therefore, you have the freedom to decide which of the suggestions are helpful.
✅ Before merging this pull request:
- Review all AI-generated comments for accuracy and relevance.
- Complete and verify the table below. We need your feedback to measure the accuracy of these suggestions and the value they add. If you are rejecting a certain code suggestion, please mention the reason briefly in the suggestion for us to capture it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements changes required for FAPI 2.0 compliance in WSO2 IS-7.1, adding support for FAPI version configuration and related functionality.
Key changes include:
- Added FAPI version configuration support with new helper methods to distinguish between FAPI 1.0 and 2.0
- Implemented FAPI 2.0 specific behaviors including issuer parameter in authorization responses and state parameter prioritization from PAR requests
- Updated test cases to accommodate the new FAPI version configurations
Reviewed Changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| OAuth2Util.java | Added FAPI version check methods and updated issuer logic to support entity ID usage |
| QueryResponseModeProvider.java | Added issuer parameter to authorization responses for FAPI 2.0 compliance |
| AuthorizationHandlerManager.java | Updated error codes for FAPI 2.0 compliant applications |
| OAuthServerConfiguration.java | Added FAPI version and entity ID issuer configuration support |
| ParRequestBuilder.java | Added state parameter extraction from PAR requests |
| AuthzUtil.java | Updated FAPI checks to be version-specific and prioritized PAR state parameter |
| OAuth2ParEndpoint.java | Made FAPI request object validation specific to FAPI 1.0 |
| ProviderConfigBuilder.java | Added authorization response issuer parameter support for FAPI 2.0 |
| OIDProviderConfigResponse.java | Added property for authorization response issuer parameter |
| DiscoveryConstants.java | Added constant for authorization response issuer parameter |
| Various test files | Updated test configurations and mocks to support new FAPI version settings |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| if (parState != null) { | ||
| params.setState(parState.toString()); | ||
| } | ||
| } else { |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The else block only contains a single statement. Consider moving this outside the conditional block and only setting the PAR state when the condition is met, to improve code readability.
| } else { | |
| } | |
| if (params.getState() == null) { |
| // `authorization_response_iss` should be true for FAPI 2.0 compliance. | ||
| if (OAuth2Util.isFapi2Enabled()) { | ||
| providerConfig.setAuthorizationResponseIssParameterSupported(Boolean.TRUE); | ||
| } | ||
| } |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The FAPI 2.0 check is placed inside the authorization details types condition. This means the authorization response issuer parameter will only be set if authorization detail types are configured. Consider moving this check outside the authorization details condition to ensure it's always evaluated for FAPI 2.0.
| // `authorization_response_iss` should be true for FAPI 2.0 compliance. | |
| if (OAuth2Util.isFapi2Enabled()) { | |
| providerConfig.setAuthorizationResponseIssParameterSupported(Boolean.TRUE); | |
| } | |
| } | |
| } | |
| // `authorization_response_iss` should be true for FAPI 2.0 compliance. | |
| if (OAuth2Util.isFapi2Enabled()) { | |
| providerConfig.setAuthorizationResponseIssParameterSupported(Boolean.TRUE); | |
| } |
Codecov Report❌ Patch coverage is ❌ Your patch check has failed because the patch coverage (23.21%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## master #2963 +/- ##
============================================
- Coverage 58.54% 58.38% -0.16%
+ Complexity 9349 9244 -105
============================================
Files 669 669
Lines 52226 51627 -599
Branches 11835 11734 -101
============================================
- Hits 30577 30145 -432
+ Misses 17495 17350 -145
+ Partials 4154 4132 -22
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Add changes required for FAPI 2.0 compliance
This PR contains the changes required to make WSO2 IS-7.1 FAPI 2.0 conformant.
Related Issues: wso2/product-is#25863
Changes Introduced
New Configurations
identity.xml