Skip to content

Commit

Permalink
Block access for apps ifAccessDisabled (#5707)
Browse files Browse the repository at this point in the history
* Block access for apps at fw ifAapplicationDisabled
* Update returning logic
* address comments
* Update unit tests
  • Loading branch information
VivekVinushanth authored May 29, 2024
1 parent 1e2c4d1 commit 6fcbf44
Show file tree
Hide file tree
Showing 10 changed files with 229 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public class ServiceProvider implements Serializable {
private static final String IS_MANAGEMENT_APP = "IsManagementApp";

private static final String IS_B2B_SELF_SERVICE_APP = "IsB2BSelfServiceApp";
private static final String IS_APPLICATION_ACCESS_ENABLED = "applicationEnabled";
private static final String IS_APPLICATION_ENABLED = "IsApplicationEnabled";
private static final String ASSOCIATED_ROLES_CONFIG = "AssociatedRolesConfig";
private static final String IS_API_BASED_AUTHENTICATION_ENABLED = "IsAPIBasedAuthenticationEnabled";

Expand Down Expand Up @@ -142,8 +142,8 @@ public class ServiceProvider implements Serializable {
private AssociatedRolesConfig associatedRolesConfig;

@IgnoreNullElement
@XmlElement(name = IS_APPLICATION_ACCESS_ENABLED)
private boolean isApplicationAccessEnabled = true;
@XmlElement(name = IS_APPLICATION_ENABLED)
private boolean isApplicationEnabled = true;

@IgnoreNullElement
@XmlElement(name = IS_API_BASED_AUTHENTICATION_ENABLED)
Expand All @@ -170,7 +170,7 @@ public static ServiceProvider build(OMElement serviceProviderOM) {

// by default set to true.
serviceProvider.setSaasApp(true);
serviceProvider.setApplicationAccessEnabled(true);
serviceProvider.setApplicationEnabled(true);

Iterator<?> iter = serviceProviderOM.getChildElements();

Expand Down Expand Up @@ -278,11 +278,11 @@ public static ServiceProvider build(OMElement serviceProviderOM) {
} else if (ASSOCIATED_ROLES_CONFIG.equals(elementName)) {
// build role association.
serviceProvider.setAssociatedRolesConfig(AssociatedRolesConfig.build(element));
} else if (IS_APPLICATION_ACCESS_ENABLED.equals(elementName)) {
} else if (IS_APPLICATION_ENABLED.equals(elementName)) {
if (element.getText() != null && "true".equals(element.getText())) {
serviceProvider.setApplicationAccessEnabled(true);
serviceProvider.setApplicationEnabled(true);
} else {
serviceProvider.setApplicationAccessEnabled(!"false".equals(element.getText()));
serviceProvider.setApplicationEnabled(!"false".equals(element.getText()));
}
}
}
Expand Down Expand Up @@ -614,13 +614,14 @@ public void setClientAttestationMetaData(ClientAttestationMetaData clientAttesta
this.clientAttestationMetaData = clientAttestationMetaData;
}

public boolean isApplicationAccessEnabled() {
return isApplicationAccessEnabled;
public boolean isApplicationEnabled() {

return isApplicationEnabled;
}

public void setApplicationAccessEnabled(boolean applicationAccessEnabled) {
public void setApplicationEnabled(boolean applicationEnabled) {

this.isApplicationAccessEnabled = applicationAccessEnabled;
this.isApplicationEnabled = applicationEnabled;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ private IdentityApplicationConstants() {
public static final String IS_API_BASED_AUTHENTICATION_ENABLED_DISPLAY_NAME = "Is API Based Authentication Enabled";
public static final String IS_ATTESTATION_ENABLED_PROPERTY_NAME = "IsAttestationEnabled";
public static final String IS_ATTESTATION_ENABLED_DISPLAY_NAME = "Is Client Attestation Enabled";
public static final String IS_APPLICATION_ACCESS_ENABLED_PROPERTY_NAME = "applicationEnabled";
public static final String IS_APPLICATION_ACCESS_ENABLED_DISPLAY_NAME = "Application Enabled";
public static final String IS_APPLICATION_ENABLED_PROPERTY_NAME = "IsApplicationEnabled";
public static final String IS_APPLICATION_ENABLED_DISPLAY_NAME = "Is Application Enabled";
public static final String ANDROID_PACKAGE_NAME_PROPERTY_NAME = "androidPackageName";
public static final String ANDROID_PACKAGE_NAME_DISPLAY_NAME = "Android mobile application package name";
public static final String APPLE_APP_ID_PROPERTY_NAME = "appleAppId";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.ISSUER_SP_PROPERTY_NAME;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.IS_API_BASED_AUTHENTICATION_ENABLED_DISPLAY_NAME;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.IS_API_BASED_AUTHENTICATION_ENABLED_PROPERTY_NAME;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.IS_APPLICATION_ACCESS_ENABLED_DISPLAY_NAME;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.IS_APPLICATION_ACCESS_ENABLED_PROPERTY_NAME;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.IS_APPLICATION_ENABLED_DISPLAY_NAME;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.IS_APPLICATION_ENABLED_PROPERTY_NAME;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.IS_ATTESTATION_ENABLED_DISPLAY_NAME;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.IS_ATTESTATION_ENABLED_PROPERTY_NAME;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.IS_B2B_SS_APP_SP_PROPERTY_DISPLAY_NAME;
Expand Down Expand Up @@ -2182,7 +2182,7 @@ public ServiceProvider getApplication(int applicationId) throws IdentityApplicat

serviceProvider.setJwksUri(getJwksUri(propertyList));
serviceProvider.setTemplateId(getTemplateId(propertyList));
serviceProvider.setApplicationAccessEnabled(getAppAccessEnabled(propertyList));
serviceProvider.setApplicationEnabled(getIsApplicationEnabled(propertyList));
serviceProvider.setManagementApp(getIsManagementApp(propertyList));
serviceProvider.setB2BSelfServiceApp(getIsB2BSSApp(propertyList));
serviceProvider.setAPIBasedAuthenticationEnabled(getIsAPIBasedAuthenticationEnabled(propertyList));
Expand Down Expand Up @@ -2435,10 +2435,10 @@ private boolean getIsB2BSSApp(List<ServiceProviderProperty> propertyList) {
return Boolean.parseBoolean(value);
}

private boolean getAppAccessEnabled(List<ServiceProviderProperty> propertyList) {
private boolean getIsApplicationEnabled(List<ServiceProviderProperty> propertyList) {

String value = propertyList.stream()
.filter(property -> IS_APPLICATION_ACCESS_ENABLED_PROPERTY_NAME.equals(property.getName()))
.filter(property -> IS_APPLICATION_ENABLED_PROPERTY_NAME.equals(property.getName()))
.findFirst()
.map(ServiceProviderProperty::getValue)
.orElse("true");
Expand Down Expand Up @@ -5151,8 +5151,8 @@ private void updateConfigurationsAsServiceProperties(ServiceProvider sp)
ServiceProviderProperty isB2BSSAppProperty = buildIsB2BSSAppProperty(sp);
spPropertyMap.put(isB2BSSAppProperty.getName(), isB2BSSAppProperty);

ServiceProviderProperty isApplicationAccessEnabledProperty = buildIsApplicationAccessEnabledProperty(sp);
spPropertyMap.put(isApplicationAccessEnabledProperty.getName(), isApplicationAccessEnabledProperty);
ServiceProviderProperty isApplicationEnabledProperty = buildIsApplicationEnabledProperty(sp);
spPropertyMap.put(isApplicationEnabledProperty.getName(), isApplicationEnabledProperty);

ServiceProviderProperty allowedRoleAudienceProperty = buildAllowedRoleAudienceProperty(sp);
spPropertyMap.put(allowedRoleAudienceProperty.getName(), allowedRoleAudienceProperty);
Expand Down Expand Up @@ -5273,13 +5273,13 @@ private ServiceProviderProperty buildIsB2BSSAppProperty(ServiceProvider sp) {
return isB2BSSAppProperty;
}

private ServiceProviderProperty buildIsApplicationAccessEnabledProperty(ServiceProvider sp) {
private ServiceProviderProperty buildIsApplicationEnabledProperty(ServiceProvider sp) {

ServiceProviderProperty isAppAccessEnabledProperty = new ServiceProviderProperty();
isAppAccessEnabledProperty.setName(IS_APPLICATION_ACCESS_ENABLED_PROPERTY_NAME);
isAppAccessEnabledProperty.setDisplayName(IS_APPLICATION_ACCESS_ENABLED_DISPLAY_NAME);
isAppAccessEnabledProperty.setValue(String.valueOf(sp.isApplicationAccessEnabled()));
return isAppAccessEnabledProperty;
ServiceProviderProperty isAppEnabledProperty = new ServiceProviderProperty();
isAppEnabledProperty.setName(IS_APPLICATION_ENABLED_PROPERTY_NAME);
isAppEnabledProperty.setDisplayName(IS_APPLICATION_ENABLED_DISPLAY_NAME);
isAppEnabledProperty.setValue(String.valueOf(sp.isApplicationEnabled()));
return isAppEnabledProperty;
}

private ServiceProviderProperty buildAllowedRoleAudienceProperty(ServiceProvider serviceProvider) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ private AuthenticationResult getAuthenticationResult(AuthServiceRequestWrapper r

AuthenticationResult authenticationResult =
(AuthenticationResult) request.getAttribute(FrameworkConstants.RequestAttribute.AUTH_RESULT);
if (authenticationResult == null) {
if (authenticationResult == null && request.getSessionDataKey() != null) {
AuthenticationResultCacheEntry authenticationResultCacheEntry =
FrameworkUtils.getAuthenticationResultFromCache(request.getSessionDataKey());
if (authenticationResultCacheEntry != null) {
Expand Down Expand Up @@ -392,6 +392,13 @@ private void validateRequest(AuthServiceRequest authServiceRequest) throws AuthS
clientId, tenantDomain));
}

// Check if the application is enabled to proceed with authentication.
if (!serviceProvider.isApplicationEnabled()) {
throw new AuthServiceClientException(
AuthServiceConstants.ErrorMessage.ERROR_DISABLED_APPLICATION.code(),
AuthServiceConstants.ErrorMessage.ERROR_DISABLED_APPLICATION.description());
}

// Check whether api based authentication is enabled for the SP.
if (!serviceProvider.isAPIBasedAuthenticationEnabled()) {
throw new AuthServiceClientException(
Expand Down Expand Up @@ -526,6 +533,8 @@ private AuthServiceConstants.ErrorMessage getMappedError(String errorCode) {
return AuthServiceConstants.ErrorMessage.ERROR_AUTHENTICATION_FLOW_TIMEOUT;
case FrameworkConstants.ERROR_STATUS_AUTH_CONTEXT_NULL:
return AuthServiceConstants.ErrorMessage.ERROR_AUTHENTICATION_CONTEXT_NULL;
case FrameworkConstants.ERROR_STATUS_APP_DISABLED:
return AuthServiceConstants.ErrorMessage.ERROR_DISABLED_APPLICATION;
default:
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.ACCOUNT_UNLOCK_TIME_CLAIM;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.AnalyticsAttributes.SESSION_ID;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.BACK_TO_FIRST_STEP;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.ERROR_DESCRIPTION_APP_DISABLED;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.ERROR_STATUS_APP_DISABLED;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.IS_API_BASED;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.ORGANIZATION_AUTHENTICATOR;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.ORGANIZATION_LOGIN_HOME_REALM_IDENTIFIER;
Expand All @@ -108,6 +110,7 @@
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.RequestParams.IDF;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.RequestParams.RESTART_FLOW;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.RequestParams.TENANT_DOMAIN;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.RequestParams.TYPE;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.ResidentIdpPropertyName.ACCOUNT_DISABLE_HANDLER_ENABLE_PROPERTY;
import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.USER_TENANT_DOMAIN;
import static org.wso2.carbon.identity.application.authentication.framework.util.SessionNonceCookieUtil.NONCE_ERROR_CODE;
Expand Down Expand Up @@ -250,6 +253,13 @@ public void handle(HttpServletRequest request, HttpServletResponse response) thr
associateTransientRequestData(request, responseWrapper, context);
}

// Check if the application is enabled.
if (!isApplicationEnabled(request, context)) {
FrameworkUtils.sendToRetryPage(request, responseWrapper, null, ERROR_STATUS_APP_DISABLED,
ERROR_DESCRIPTION_APP_DISABLED);
return;
}

if (context != null) {
// Adding the context identifier(sessionDataKey) to the request to be used when the context
// is not available.
Expand Down Expand Up @@ -478,6 +488,30 @@ && isStepHasMultiOption(context)
}
}

private boolean isApplicationEnabled(HttpServletRequest request, AuthenticationContext context)
throws FrameworkException {

String type = request.getParameter(TYPE);
String relyingParty = request.getParameter(FrameworkConstants.RequestParams.ISSUER);
if (StringUtils.isBlank(type)) {
type = context.getRequestType();
}
if (StringUtils.isBlank(relyingParty)) {
relyingParty = context.getRelyingParty();
}
ServiceProvider serviceProvider = getServiceProvider(type, relyingParty, getTenantDomain(request));
if (serviceProvider == null) {
throw new FrameworkException("Unable to retrieve service provider for relying party : " + relyingParty);
}
if (!serviceProvider.isApplicationEnabled()) {
if (log.isDebugEnabled()) {
log.debug("Application is disabled for the service provider with relying party: " + relyingParty);
}
return false;
}
return true;
}

protected void unwrapResponse(CommonAuthResponseWrapper responseWrapper, String sessionDataKey,
HttpServletResponse response, AuthenticationContext context) throws IOException {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,8 @@ public abstract class FrameworkConstants {
public static final String ERROR_DESCRIPTION_AUTH_CONTEXT_NULL = "authentication.context.null.description";
public static final String ERROR_STATUS_AUTH_FLOW_TIMEOUT = "authentication.flow.timeout";
public static final String ERROR_DESCRIPTION_AUTH_FLOW_TIMEOUT = "authentication.flow.timeout.description";
public static final String ERROR_STATUS_APP_DISABLED = "authentication.flow.app.disabled";
public static final String ERROR_DESCRIPTION_APP_DISABLED = "authentication.flow.app.disabled.description";
public static final String IS_SENT_TO_RETRY = "isSentToRetry";
public static final String CONTEXT_IDENTIFIER = "contextIdentifier";
public static final String REQ_ATTR_RETRY_STATUS = "retryStatus";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ public enum ErrorMessage {
ERROR_INVALID_LOGOUT_REQUEST("60010",
"Invalid logout request.",
"Received logout request is invalid."),
ERROR_DISABLED_APPLICATION("60011",
"Application is disabled.",
"Application is disabled. Unable to proceed with authentication as application access " +
"is restricted."),
// Server Error starting from 650xx.
/* The 65001 ERROR_UNABLE_TO_PROCEED is used as the default server error
therefor be cautious if that is being changed.*/
Expand Down
Loading

0 comments on commit 6fcbf44

Please sign in to comment.