Skip to content
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

Add ext_application_version field to dcr apps #2574

Merged
merged 8 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public class ApplicationDTO {
private String extApplicationDisplayName = null;


private String extApplicationVersion = null;


private String extApplicationOwner = null;


Expand Down Expand Up @@ -164,7 +167,18 @@ public void setExtApplicationDisplayName(String extApplicationDisplayName) {
this.extApplicationDisplayName = extApplicationDisplayName;
}

/**
/**
**/
@ApiModelProperty(value = "")
@JsonProperty("ext_application_version")
public String getExtApplicationVersion() {
return extApplicationVersion;
}
public void setExtApplicationVersion(String extApplicationVersion) {
this.extApplicationVersion = extApplicationVersion;
}

/**
**/
@ApiModelProperty(value = "")
@JsonProperty("ext_application_owner")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class UpdateRequestDTO {
private String backchannelLogoutUri = null;
private boolean backchannelLogoutSessionRequired;
private String extApplicationDisplayName = null;
private String extApplicationVersion = null;
private String extApplicationOwner = null;
private Long extApplicationTokenLifetime = null;
private Long extUserTokenLifetime = null;
Expand Down Expand Up @@ -153,6 +154,16 @@ public void setExtApplicationDisplayName(String extApplicationDisplayName) {
this.extApplicationDisplayName = extApplicationDisplayName;
}

@ApiModelProperty
@JsonProperty("ext_application_version")
public String getExtApplicationVersion() {
return extApplicationVersion;
}

public void setExtApplicationVersion(String extApplicationVersion) {
this.extApplicationVersion = extApplicationVersion;
}

@ApiModelProperty
@JsonProperty("ext_application_owner")
public String getExtApplicationOwner() {
Expand Down Expand Up @@ -435,6 +446,7 @@ public String toString() {
sb.append(" backchannel_logout_uri: ").append(backchannelLogoutUri).append("\n");
sb.append(" backchannel_logout_session_required: ").append(backchannelLogoutSessionRequired).append("\n");
sb.append(" ext_application_display_name: ").append(extApplicationDisplayName).append("\n");
sb.append(" ext_application_version: ").append(extApplicationVersion).append("\n");
sb.append(" tokenTypeExtension: ").append(tokenType).append("\n");
sb.append(" ext_application_owner: ").append(extApplicationOwner).append("\n");
sb.append(" ext_application_token_lifetime: ").append(extApplicationTokenLifetime).append("\n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ public static ApplicationUpdateRequest getApplicationUpdateRequest(UpdateRequest
applicationUpdateRequest.setTokenType(updateRequestDTO.getTokenType());
applicationUpdateRequest.setBackchannelLogoutUri(updateRequestDTO.getBackchannelLogoutUri());
applicationUpdateRequest.setExtApplicationDisplayName(updateRequestDTO.getExtApplicationDisplayName());
applicationUpdateRequest.setExtApplicationVersion(updateRequestDTO.getExtApplicationVersion());
applicationUpdateRequest.setExtApplicationOwner(updateRequestDTO.getExtApplicationOwner());
applicationUpdateRequest.setExtApplicationTokenLifetime(updateRequestDTO.getExtApplicationTokenLifetime());
applicationUpdateRequest.setExtUserTokenLifetime(updateRequestDTO.getExtUserTokenLifetime());
Expand Down Expand Up @@ -229,6 +230,7 @@ public static ApplicationDTO getApplicationDTOFromApplication(Application applic
https://openid.net/specs/openid-connect-registration-1_0.html */
applicationDTO.setClientSecretExpiresAt(0L);
applicationDTO.setExtApplicationDisplayName(application.getExtApplicationDisplayName());
applicationDTO.setExtApplicationVersion(application.getExtApplicationVersion());
applicationDTO.setExtApplicationOwner(application.getExtApplicationOwner());
applicationDTO.setExtApplicationTokenLifetime(application.getExtApplicationTokenLifetime());
applicationDTO.setExtUserTokenLifetime(application.getExtUserTokenLifetime());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ info:
description: >
This document specifies an **OAuth2 Dynamic Client Registration Endpoint**
for WSO2 **Identity Server** .
It is written with [swagger 2](http://swagger.io/).
contact:
name: WSO2
Expand Down Expand Up @@ -396,6 +394,8 @@ definitions:
type: string
ext_application_owner:
type: string
ext_application_version:
type: string
ext_application_token_lifetime:
type: integer
format: int64
Expand Down Expand Up @@ -478,6 +478,8 @@ definitions:
ext_application_token_lifetime:
type: integer
format: int64
ext_application_version:
type: string
ext_user_token_lifetime:
type: integer
format: int64
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public enum ErrorMessages {
BAD_REQUEST_INVALID_SP_NAME("Client Name is not adhering to the regex: %s"),
BAD_REQUEST_INVALID_SP_TEMPLATE_NAME("Invalid service provider template name: %s"),
BAD_REQUEST_INVALID_INPUT("%s"),
BAD_REQUEST_INVALID_SP_INPUT("Invalid data sent for the service provider : %s"),
BAD_REQUEST_INSUFFICIENT_DATA("Insufficient data in the request"),
NOT_FOUND_APPLICATION_WITH_ID("Application not available for given client key: %s"),
NOT_FOUND_APPLICATION_WITH_NAME("Application not available for given client name: %s"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class Application implements Serializable {
private List<String> redirectUris = null;
private List<String> grantTypes = null;
private String extApplicationDisplayName = null;
private String extApplicationVersion = null;
private String extApplicationOwner = null;
private Long extApplicationTokenLifetime = null;
private Long extUserTokenLifetime = null;
Expand Down Expand Up @@ -149,6 +150,16 @@ public void setExtApplicationDisplayName(String extApplicationDisplayName) {
this.extApplicationDisplayName = extApplicationDisplayName;
}

public String getExtApplicationVersion() {

return extApplicationVersion;
}

public void setExtApplicationVersion(String extApplicationVersion) {

this.extApplicationVersion = extApplicationVersion;
}

public String getExtApplicationDisplayName() {

return extApplicationDisplayName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class ApplicationUpdateRequest implements Serializable {
private String tokenType = null;
private String backchannelLogoutUri = null;
private String extApplicationDisplayName = null;
private String extApplicationVersion = null;
private String extApplicationOwner = null;
private Long extApplicationTokenLifetime = null;
private Long extUserTokenLifetime = null;
Expand Down Expand Up @@ -155,6 +156,24 @@ public void setExtApplicationDisplayName(String extApplicationDisplayName) {
this.extApplicationDisplayName = extApplicationDisplayName;
}

/**
* Get the external parameter application version.
* @return external parameter application version.
*/
public String getExtApplicationVersion() {

return extApplicationVersion;
}

/**
* Set the external parameter application version.
* @param extApplicationVersion external parameter application version.
*/
public void setExtApplicationVersion(String extApplicationVersion) {

this.extApplicationVersion = extApplicationVersion;
}

/**
* Get the external application owner.
* @return external application owner.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException;
import org.wso2.carbon.identity.application.common.IdentityApplicationManagementValidationException;
import org.wso2.carbon.identity.application.common.model.AssociatedRolesConfig;
import org.wso2.carbon.identity.application.common.model.InboundAuthenticationConfig;
import org.wso2.carbon.identity.application.common.model.InboundAuthenticationRequestConfig;
Expand Down Expand Up @@ -247,6 +248,7 @@ public Application updateApplication(ApplicationUpdateRequest updateRequest, Str
updateRequest.getExtApplicationOwner() :
PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
String clientName = updateRequest.getClientName();
String applicationVersion = updateRequest.getExtApplicationVersion();
AdditionalAttributeFilter attributeHandler = null;
Map<String, Object> processedAttributes = null;

Expand Down Expand Up @@ -306,6 +308,8 @@ public Application updateApplication(ApplicationUpdateRequest updateRequest, Str
if (StringUtils.isNotEmpty(updateRequest.getJwksURI())) {
sp.setJwksUri(updateRequest.getJwksURI());
}
// Todo: validate version input. Create a function at app mgt.
sp.setApplicationVersion(applicationVersion);
// Need to create a deep clone, since modifying the fields of the original object,
// will modify the cached SP object.
ServiceProvider clonedSP = cloneServiceProvider(sp);
Expand Down Expand Up @@ -683,6 +687,7 @@ private Application buildResponse(OAuthConsumerAppDTO createdApp, String tenantD
application.setGrantTypes(grantTypesList);
ServiceProvider sp = getServiceProvider(createdApp.getApplicationName(), tenantDomain);
application.setExtApplicationDisplayName(getDisplayNameProperty(sp));
application.setExtApplicationVersion(sp.getApplicationVersion());
application.setExtApplicationOwner(createdApp.getUsername());
application.setExtApplicationTokenLifetime(createdApp.getApplicationAccessTokenExpiryTime());
application.setExtUserTokenLifetime(createdApp.getUserAccessTokenExpiryTime());
Expand Down Expand Up @@ -969,6 +974,9 @@ private void updateServiceProvider(ServiceProvider serviceProvider, String tenan
try {
DCRDataHolder.getInstance().getApplicationManagementService()
.updateApplication(serviceProvider, tenantDomain, userName);
} catch (IdentityApplicationManagementValidationException e) {
throw DCRMUtils.generateClientException(DCRMConstants.ErrorMessages.BAD_REQUEST_INVALID_SP_INPUT,
serviceProvider.getApplicationName());
} catch (IdentityApplicationManagementException e) {
throw DCRMUtils.generateServerException(
DCRMConstants.ErrorMessages.FAILED_TO_UPDATE_SP, serviceProvider.getApplicationName(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,6 @@ private OAuth2AccessTokenRespDTO validateGrantAndIssueToken(OAuth2AccessTokenReq
String grantType = tokenReqDTO.getGrantType();
boolean isRefreshRequest = GrantType.REFRESH_TOKEN.toString().equals(grantType);
boolean isOfTypeApplicationUser = authzGrantHandler.isOfTypeApplicationUser(tokReqMsgCtx);
boolean useClientIdAsSubClaimForAppTokensEnabled = OAuthServerConfiguration.getInstance()
.isUseClientIdAsSubClaimForAppTokensEnabled();

boolean isValidGrant = false;
String error = "Provided Authorization Grant is invalid";
Expand Down Expand Up @@ -458,13 +456,17 @@ private OAuth2AccessTokenRespDTO validateGrantAndIssueToken(OAuth2AccessTokenReq
OAuth2Util.setTokenRequestContext(tokReqMsgCtx);

AuthenticatedUser authorizedUser = tokReqMsgCtx.getAuthorizedUser();
ServiceProvider serviceProvider = getServiceProvider(tokReqMsgCtx.getOauth2AccessTokenReqDTO());
boolean useClientIdAsSubClaimForAppTokensEnabledServerConfig = OAuthServerConfiguration.getInstance()
.isUseClientIdAsSubClaimForAppTokensEnabled();
boolean useClientIdAsSubClaimForAppTokensEnabled = OAuth2Util
.isAllowedToStopUsingAppOwnerForTokenIdentification(serviceProvider.getApplicationVersion());
if (authorizedUser.getAuthenticatedSubjectIdentifier() == null) {
if (!isOfTypeApplicationUser && useClientIdAsSubClaimForAppTokensEnabled) {
if ((!isOfTypeApplicationUser && (useClientIdAsSubClaimForAppTokensEnabled
|| useClientIdAsSubClaimForAppTokensEnabledServerConfig))) {
authorizedUser.setAuthenticatedSubjectIdentifier(oAuthAppDO.getOauthConsumerKey());
} else {
authorizedUser.setAuthenticatedSubjectIdentifier(
getSubjectClaim(getServiceProvider(tokReqMsgCtx.getOauth2AccessTokenReqDTO()),
authorizedUser));
authorizedUser.setAuthenticatedSubjectIdentifier(getSubjectClaim(serviceProvider, authorizedUser));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ public class OAuth2Util {
public static final String ENABLE_OPENID_CONNECT_AUDIENCES = "EnableAudiences";
public static final String OPENID_CONNECT_AUDIENCE = "audience";
public static final String OPENID_SCOPE = "openid";

/*
* Maintain a separate parameter "OPENID_CONNECT_AUDIENCE_IDENTITY_CONFIG" to get the audience from the identity.xml
* when user didn't add any audience in the UI while creating service provider.
Expand Down Expand Up @@ -392,6 +393,8 @@ public class OAuth2Util {
ApplicationConstants.MY_ACCOUNT_APPLICATION_CLIENT_ID,
ApplicationConstants.CONSOLE_APPLICATION_CLIENT_ID);

public static final String ALLOWED_VERSION_TO_STOP_USING_APP_OWNER_FOR_TOKEN_IDENTIFICATION = "v1.0.0";

private OAuth2Util() {

}
Expand Down Expand Up @@ -5534,4 +5537,26 @@ public static boolean isPairwiseSubEnabledForAccessTokens() {

return Boolean.parseBoolean(IdentityUtil.getProperty(ENABLE_PPID_FOR_ACCESS_TOKENS));
}

/**
* Compare the app version with allowed minimum version.
*
* @param appVersion App version.
* @return True if the app version is greater than or equal to the allowed minimum version.
*/
public static boolean isAllowedToStopUsingAppOwnerForTokenIdentification(String appVersion) {

String[] appVersionDigits = appVersion.substring(1).split("\\.");
String[] allowedVersionDigits = ALLOWED_VERSION_TO_STOP_USING_APP_OWNER_FOR_TOKEN_IDENTIFICATION.substring(1)
.split("\\.");

for (int i = 0; i < appVersionDigits.length; i++) {
if (appVersionDigits[i].equals(allowedVersionDigits[i])) {
continue;
} else {
return Integer.parseInt(appVersionDigits[i]) >= Integer.parseInt(allowedVersionDigits[i]);
}
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ private OAuth2IntrospectionResponseDTO validateRefreshToken(OAuth2TokenValidatio
private OAuth2IntrospectionResponseDTO validateAccessToken(OAuth2TokenValidationMessageContext messageContext,
OAuth2TokenValidationRequestDTO validationRequest,
OAuth2TokenValidator tokenValidator)
throws IdentityOAuth2Exception {
throws IdentityOAuth2Exception, IdentityApplicationManagementException, InvalidOAuthClientException {

OAuth2IntrospectionResponseDTO introResp = new OAuth2IntrospectionResponseDTO();
AccessTokenDO accessTokenDO = null;
Expand Down Expand Up @@ -567,8 +567,18 @@ private OAuth2IntrospectionResponseDTO validateAccessToken(OAuth2TokenValidation
}

String tokenType = accessTokenDO.getTokenType();
boolean removeUsernameFromAppTokenEnabled = OAuthServerConfiguration.getInstance()

boolean removeUsernameFromAppTokenEnabledServerConfig = OAuthServerConfiguration.getInstance()
.isRemoveUsernameFromIntrospectionResponseForAppTokensEnabled();
String appResidentTenantDomain = OAuth2Util.getTenantDomain(accessTokenDO.getAppResidentTenantId());
if (StringUtils.isEmpty(appResidentTenantDomain)) {
// Get user domain as app domain.
appResidentTenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
}
String consumerKey = accessTokenDO.getConsumerKey();
ServiceProvider serviceProvider = OAuth2Util.getServiceProvider(consumerKey, appResidentTenantDomain);
boolean removeUsernameFromAppTokenEnabled = OAuth2Util
.isAllowedToStopUsingAppOwnerForTokenIdentification(serviceProvider.getApplicationVersion());
boolean isAppTokenType = StringUtils.equals(OAuthConstants.UserType.APPLICATION, tokenType);

// should be in seconds
Expand All @@ -578,7 +588,8 @@ private OAuth2IntrospectionResponseDTO validateAccessToken(OAuth2TokenValidation
// token scopes
introResp.setScope(OAuth2Util.buildScopeString((accessTokenDO.getScope())));
// set user-name
if (!removeUsernameFromAppTokenEnabled || !isAppTokenType) {
if (!(removeUsernameFromAppTokenEnabled || removeUsernameFromAppTokenEnabledServerConfig)
|| !isAppTokenType) {
introResp.setUsername(getAuthzUser(accessTokenDO));
}
// add client id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.lang.StringUtils;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuer;
import org.mockito.Mock;
import org.mockito.MockedStatic;
Expand All @@ -37,6 +38,7 @@
import org.wso2.carbon.identity.application.common.model.FederatedAuthenticatorConfig;
import org.wso2.carbon.identity.application.common.model.IdentityProvider;
import org.wso2.carbon.identity.application.common.model.Property;
import org.wso2.carbon.identity.application.common.model.ServiceProvider;
import org.wso2.carbon.identity.application.common.util.IdentityApplicationManagementUtil;
import org.wso2.carbon.identity.central.log.mgt.utils.LoggerUtils;
import org.wso2.carbon.identity.common.testng.WithAxisConfiguration;
Expand Down Expand Up @@ -84,6 +86,7 @@
import java.util.Optional;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.lenient;
Expand Down Expand Up @@ -318,6 +321,14 @@ public void testBuildIntrospectionResponse(boolean isIDPIdColumnEnabled, String
oAuth2Util.when(() -> OAuth2Util.getAccessTokenExpireMillis(any(), Mockito.anyBoolean()))
.thenReturn(1000L);

ServiceProvider serviceProvider = new ServiceProvider();
serviceProvider.setApplicationVersion("v1.0.0");
oAuth2Util.when(() -> OAuth2Util.getServiceProvider(anyString(), any()))
.thenReturn(serviceProvider);
// As the token is dummy, no point in getting actual tenant details.
oAuth2Util.when(() -> OAuth2Util.getTenantDomain(anyInt()))
.thenReturn(StringUtils.EMPTY);

OAuth2IntrospectionResponseDTO oAuth2IntrospectionResponseDTO = tokenValidationHandler
.buildIntrospectionResponse(oAuth2TokenValidationRequestDTO);
assertNotNull(oAuth2IntrospectionResponseDTO);
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@
<carbon.kernel.registry.imp.pkg.version.range>[1.0.1, 2.0.0)</carbon.kernel.registry.imp.pkg.version.range>

<!-- Carbon Identity Framework version -->
<carbon.identity.framework.version>7.3.62</carbon.identity.framework.version>
<carbon.identity.framework.version>7.5.46</carbon.identity.framework.version>
<carbon.identity.framework.imp.pkg.version.range>[5.25.234, 8.0.0)
</carbon.identity.framework.imp.pkg.version.range>

Expand Down
Loading