diff --git a/component/client-handler/README.md b/component/client-handler/README.md deleted file mode 100644 index 58032336..00000000 --- a/component/client-handler/README.md +++ /dev/null @@ -1,89 +0,0 @@ -##

⚠️ Deprecation Notice

- -**This component has been moved to a new standalone repository.All the future development will be -continued in the new repository and this repository will no longer be maintained.** - -**You can find the new repository here: [identity-oauth-privatekey-jwthandler](https://github.com/wso2-extensions/identity-oauth-privatekey-jwthandler)** - - -
- -## 01. Private Key JWT Client Authentication - -Pre-requisites: - -- Maven 3.x -- Java 1.7 or above - -Tested Platform: - -- Linux -- WSO2 IS 5.3.0 -- Java 1.7 - -Do the following: - -Deploying and Configuring JWT client-handler artifacts: -1. Navigate to client-handler/org.wso2.carbon.identity.oauth2.grant.jwt and build. - -2. Place target/ -org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt-1.0.0-SNAPSHOT.jar in the /repository/component/dropins directory. - -3. To register the JWT grant type, configure the /repository/conf/identity/identity.xml file by adding a new entry under the element. Add a unique identifier between as seen in the code block below. - - - 60 - - -4. Update for supported grant types as below in /repository/conf/identity/identity.xml, under tag - - - authorization_code - org.wso2.carbon.identity.oauth2.token.handlers.grant.AuthorizationCodeGrantHandler - org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.validator.grant.JWTAuthorizationCodeGrantValidator - - - client_credentials - org.wso2.carbon.identity.oauth2.token.handlers.grant.ClientCredentialsGrantHandler - org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.validator.grant.JWTClientCredentialGrantValidator - - -5. Create new table in Identity datasource configured in /repository/conf/identity/identity.xml - - h2.sql - ```CREATE TABLE IF NOT EXISTS IDN_JWT_PRIVATE_KEY (JWT_ID VARCHAR(255), EXP_TIME TIMESTAMP DEFAULT 0, - TIME_CREATED TIMESTAMP DEFAULT 0, PRIMARY KEY (JWT_ID));``` - - mysql.sql, mysql-5.7.sql, postgres.sql - ```CREATE TABLE IF NOT EXISTS IDN_JWT_PRIVATE_KEY (JWT_ID VARCHAR(255), EXP_TIME TIMESTAMP DEFAULT 0, - TIME_CREATED TIMESTAMP DEFAULT 0, PRIMARY KEY (JWT_ID));``` - - - db2.sql - ```CREATE TABLE IDN_JWT_PRIVATE_KEY (JWT_ID VARCHAR(255), EXP_TIME TIMESTAMP, - TIME_CREATED TIMESTAMP, PRIMARY KEY (JWT_ID))``` - - oracle.sql, oracle-rac.sql - ```CREATE TABLE IDN_JWT_PRIVATE_KEY (JWT_ID VARCHAR(255), EXP_TIME TIMESTAMP, - TIME_CREATED TIMESTAMP, PRIMARY KEY (JWT_ID))``` - -6. Add Cache-configuration entry in /repository/conf/identity/identity.xml as below - - - - ... - - - - -7. Restart Server -8. Add service provider - - Select Add under Service Providers menu in the Main menu. - - Fill in the Service Provider Name and provide a brief Description of the service provider. - - Expand the OAuth/OpenID Connect Configuration and click Configure. - - Enter a callback url for example http://localhost:8080/playground2/oauth2client and click Add. - - The OAuth Client Key and OAuth Client Secret will now be visible. - -9. Import the public key of the private_key_jwt issuer. - - Rename the public key certificate file of the private_key_jwt issuer, with the Client Key of the above auth app - - Log in to the API Manager's management console (https://localhost:9443/carbon) using admin/admin credentials and select Keystores under Manage menu in the Main menu. - - Import above cert in to the default key store defined in /repository/conf/carbon.xml. In a default pack, keystore name is wso2carbon.jks - -10. The cURL command below can be used to retrieve access token and refresh token using a JWT. - ```curl -v POST -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" -k -d 'client_id=&grant_type=authorization_code&code=$CODE&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=&redirect_uri=http://localhost:8080/playground2/oauth2client" https://localhost:9443/oauth2/token``` diff --git a/component/client-handler/pom.xml b/component/client-handler/pom.xml deleted file mode 100644 index 5f94dcda..00000000 --- a/component/client-handler/pom.xml +++ /dev/null @@ -1,352 +0,0 @@ - - - - 4.0.0 - org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt - bundle - Private Key JWT client handler - http://wso2.org - 2.5.17-SNAPSHOT - - org.wso2.carbon.extension.identity.oauth.addons - identity-oauth2-extenstions - 2.5.17-SNAPSHOT - ../../pom.xml - - - - - org.wso2.carbon.identity.framework - org.wso2.carbon.idp.mgt - - - org.wso2.carbon.identity.framework - org.wso2.carbon.identity.application.common - - - org.wso2.carbon.identity.framework - org.wso2.carbon.identity.user.profile - - - org.wso2.carbon.identity.framework - org.wso2.carbon.identity.core - - - org.wso2.carbon.identity.framework - org.wso2.carbon.identity.application.authentication.framework - - - commons-collections - commons-collections - - - org.wso2.carbon.identity.framework - org.wso2.carbon.identity.notification.mgt - - - org.wso2.carbon - org.wso2.carbon.core - - - org.wso2.carbon - org.wso2.carbon.user.core - - - org.wso2.carbon.identity.framework - org.wso2.carbon.identity.application.mgt - - - org.apache.oltu.oauth2 - org.apache.oltu.oauth2.client - - - org.apache.oltu.oauth2 - org.apache.oltu.oauth2.common - - - org.wso2.carbon - org.wso2.carbon.ui - - - org.json.wso2 - json - - - javax.servlet - servlet-api - provided - - - org.apache.taglibs - taglibs-standard-impl - - - org.wso2.orbit.com.nimbusds - nimbus-jose-jwt - - - org.wso2.orbit.org.apache.oltu.oauth2 - oltu - - - org.wso2.carbon.identity.inbound.auth.oauth2 - org.wso2.carbon.identity.oauth - - - org.wso2.securevault - org.wso2.securevault - - - - - org.wso2.orbit.org.owasp.encoder - encoder - - - org.apache.felix - org.apache.felix.scr.ds-annotations - provided - - - org.wso2.eclipse.osgi - org.eclipse.osgi.services - - - org.wso2.carbon - org.wso2.carbon.utils - - - org.wso2.carbon.identity.framework - org.wso2.carbon.identity.configuration.mgt.core - - - - org.testng - testng - - - org.jacoco - org.jacoco.agent - runtime - test - - - org.powermock - powermock-module-testng - test - - - org.powermock - powermock-api-mockito - test - - - javax - javaee-web-api - test - - - com.h2database - h2 - test - - - - org.wso2.carbon.identity.framework - org.wso2.carbon.identity.testutil - test - - - - org.wso2.carbon - org.wso2.carbon.tomcat.ext - test - - - org.ops4j.pax.logging - pax-logging-api - - - - - - - org.apache.felix - maven-bundle-plugin - ${maven.bundle.plugins.version} - true - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven.plugins.version} - - ${maven.plugins.version.source} - ${maven.plugins.version.source} - - - - org.apache.felix - maven-bundle-plugin - true - - - ${project.artifactId} - ${project.artifactId} - org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal - - - org.osgi.service.*, - org.osgi.framework.*, - org.apache.oltu.oauth2.common.validators; version="${oltu.package.import.version.range}", - org.apache.oltu.oauth2.common; version="${oltu.package.import.version.range}", - org.wso2.carbon.identity.application.authentication.framework.*; - version="${carbon.identity.package.import.version.range}", - org.wso2.carbon.utils.*; version="${carbon.kernel.package.import.version.range}", - com.nimbusds.jose.*; version="${nimbusds.osgi.version.range}", - com.nimbusds.jwt; version="${nimbusds.osgi.version.range}", - org.wso2.carbon.idp.mgt.*; version="${carbon.identity.version}", - org.wso2.carbon.user.core.util; version="${carbon.kernel.package.import.version.range}", - org.wso2.carbon.user.core.service;version="${carbon.kernel.package.import.version.range}", - net.minidev.json; version="${net.minidev.json.imp.pkg.version.range}", - org.wso2.carbon.context; version="${carbon.kernel.package.import.version.range}", - org.wso2.carbon.identity.testutil.*;version="${carbon.identity.test.version}", - org.wso2.carbon.identity.common.testng.*;version="${carbon.identity.test.version}", - - - !org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal, - org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.*; - - * - - - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven.surefire.plugin.version} - - - - src/test/resources/testng.xml - - - target/jacoco.exec - - true - - - - org.jacoco - jacoco-maven-plugin - ${jacoco.version} - - - - - **/Constants.class - **/*SQLQueries.class - **/JWTServiceComponent.class - **/*JWTIDPersistingThread.class - **/JWTEntry.class - - - - - default-prepare-agent - - prepare-agent - - - - default-prepare-agent-integration - - prepare-agent-integration - - - - default-report - - report - - - - default-report-integration - - report-integration - - - - default-check - - check - - - - - BUNDLE - - - COMPLEXITY - COVEREDRATIO - 0.4 - - - - - - - - - - maven-resources-plugin - ${maven.resource.plugin.version} - - - copy-resources - - validate - - copy-resources - - - ${basedir}/target/ - - - src/test/resources/ - true - - - - - - - - - - ${basedir}/src/main/resources - - **/*.properties - - - - - diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/Constants.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/Constants.java deleted file mode 100644 index 6a94a42b..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/Constants.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2017, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License - */ -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt; - -/** - * Constants are listed here. - */ -public class Constants { - - public static final String OAUTH_JWT_BEARER_GRANT_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"; - public static final String OAUTH_JWT_ASSERTION = "client_assertion"; - public static final String OAUTH_JWT_ASSERTION_TYPE = "client_assertion_type"; - public static final int DEFAULT_VALIDITY_PERIOD_IN_MINUTES = 300; - public static final String DEFAULT_AUDIENCE = ""; - public static final boolean DEFAULT_ENABLE_JTI_CACHE = true; - public static final String UTC = "UTC"; - public static final String TOKEN_ENDPOINT_ALIAS = "TokenEndpointAlias"; - public static final String PREVENT_TOKEN_REUSE = "PreventTokenReuse"; - public static final String REJECT_BEFORE_IN_MINUTES = "RejectBeforeInMinutes"; - public static final String ISSUER = "Issuer"; - public static final String JWT_ID_CLAIM = "jti"; - public static final String EXPIRATION_TIME_CLAIM = "exp"; - public static final String AUDIENCE_CLAIM = "aud"; - public static final String SUBJECT_CLAIM = "sub"; - public static final String ISSUER_CLAIM = "iss"; - public static final String PRIVATE_KEY_JWT = "signedJWT"; - public static final String JWKS_URI = "jwksURI"; - public static final String AUTHENTICATOR_TYPE_PARAM = "authenticatorType"; - public static final String AUTHENTICATOR_TYPE_PK_JWT = "pkJWT"; - public static final String OAUTH2_PAR_URL_REF = "OAuth2ParEPUrl"; - public static final String OAUTH2_PAR_URL_CONFIG = "OAuth.OAuth2ParEPUrl"; - - //query keys - public static final String GET_JWT_ID = "GET_JWT_ID"; - public static final String GET_JWT = "GET_JWT"; - public static final String GET_JWT_DETAILS = "GET_JWT_DETAILS"; - public static final String UPSERT_MYSQL = "UPSERT_MYSQL"; - public static final String UPSERT_H2 = "UPSERT_H2"; - public static final String UPSERT_POSTGRESQL = "UPSERT_POSTGRESQL"; - public static final String UPSERT_ORACLE = "UPSERT_ORACLE"; - public static final String UPSERT_MSSQL_DB2 = "UPSERT_MSSQL_DB2"; - public static final String INSERT_JWD_ID = "INSERT_JWD_ID"; - public static final int DEFAULT_TENANT_ID = -1; - - public static class SQLQueries { - - public static final String TENANT_ID = "TENANT_ID"; - public static final String IDN_OIDC_JTI = "IDN_OIDC_JTI"; - - public static final String EXP_TIME = "EXP_TIME"; - public static final String TIME_CREATED = "TIME_CREATED"; - - public static final String GET_JWT_ID = "SELECT 1 FROM IDN_OIDC_JTI WHERE JWT_ID =?"; - - public static final String GET_TENANTED_JWT_ID = "SELECT 1 FROM IDN_OIDC_JTI WHERE JWT_ID =? AND TENANT_ID=?"; - - public static final String GET_JWT = "SELECT EXP_TIME,TIME_CREATED FROM IDN_OIDC_JTI WHERE JWT_ID =?"; - public static final String GET_TENANTED_JWT = "SELECT EXP_TIME,TIME_CREATED FROM IDN_OIDC_JTI WHERE JWT_ID =? AND TENANT_ID=?"; - - public static final String GET_JWT_DETAIL = "SELECT TENANT_ID, EXP_TIME,TIME_CREATED FROM IDN_OIDC_JTI WHERE JWT_ID =? AND TENANT_ID IN (?,?)"; - - public static final String INSERT_JWD_ID = "INSERT INTO IDN_OIDC_JTI (JWT_ID, EXP_TIME, TIME_CREATED)" + - "VALUES (?,?,?)"; - public static final String INSERT_TENANTED_JWD_ID = "INSERT INTO IDN_OIDC_JTI (JWT_ID, TENANT_ID, EXP_TIME, TIME_CREATED)" + - "VALUES (?,?,?,?)"; - public static final String INSERT_OR_UPDATE_JWT_ID_MSSQL_OR_DB2 = "MERGE INTO IDN_OIDC_JTI T USING " + - "(VALUES (?,?,?)) S (JWT_ID, EXP_TIME, TIME_CREATED) ON T.JWT_ID = S.JWT_ID WHEN MATCHED THEN " + - "UPDATE SET EXP_TIME = S.EXP_TIME, TIME_CREATED = S.TIME_CREATED WHEN NOT MATCHED THEN " + - "INSERT (JWT_ID, EXP_TIME, TIME_CREATED) VALUES (S.JWT_ID, S.EXP_TIME,S.TIME_CREATED);"; - public static final String INSERT_OR_UPDATE_TENANTED_JWT_ID_MSSQL_OR_DB2 = "MERGE INTO IDN_OIDC_JTI T USING " + - "(VALUES (?,?,?,?)) S (JWT_ID, TENANT_ID, EXP_TIME, TIME_CREATED) ON T.JWT_ID = S.JWT_ID AND " + - "T.TENANT_ID = S.TENANT_ID WHEN MATCHED THEN UPDATE SET EXP_TIME = S.EXP_TIME, " + - "TIME_CREATED = S.TIME_CREATED WHEN NOT MATCHED THEN INSERT (JWT_ID, TENANT_ID, EXP_TIME, " + - "TIME_CREATED) VALUES (S.JWT_ID, S.TENANT_ID, S.EXP_TIME,S.TIME_CREATED);"; - - public static final String INSERT_OR_UPDATE_JWT_ID_MYSQL = "INSERT INTO IDN_OIDC_JTI " + - "(JWT_ID, EXP_TIME, TIME_CREATED) VALUES (?, ?, ?) " + - "ON DUPLICATE KEY UPDATE EXP_TIME = VALUES(EXP_TIME), " + - "TIME_CREATED = VALUES(TIME_CREATED)"; - public static final String INSERT_OR_UPDATE_TENANTED_JWT_ID_MYSQL = "INSERT INTO IDN_OIDC_JTI " + - "(JWT_ID, TENANT_ID, EXP_TIME, TIME_CREATED) VALUES (?,?,?,?) ON DUPLICATE KEY UPDATE " + - "EXP_TIME = VALUES(EXP_TIME),TIME_CREATED = VALUES(TIME_CREATED);"; - - public static final String INSERT_OR_UPDATE_JWT_ID_H2 = "MERGE INTO IDN_OIDC_JTI KEY (JWT_ID) " + - "VALUES (?, ?, ?)"; - - public static final String INSERT_OR_UPDATE_TENANTED_JWT_ID_H2 = "MERGE INTO IDN_OIDC_JTI KEY (JWT_ID, TENANT_ID) " + - "VALUES (?, ?, ?, ?)"; - - public static final String INSERT_OR_UPDATE_JWT_ID_POSTGRESQL = - "INSERT INTO IDN_OIDC_JTI (JWT_ID, EXP_TIME, TIME_CREATED) VALUES (?, ?, ?) " + - "ON CONFLICT (JWT_ID) DO UPDATE SET EXP_TIME = EXCLUDED.EXP_TIME, " + - "TIME_CREATED = EXCLUDED.TIME_CREATED"; - - public static final String INSERT_OR_UPDATE_TENANTED_JWT_ID_POSTGRESQL = - "INSERT INTO IDN_OIDC_JTI (JWT_ID, TENANT_ID, EXP_TIME, TIME_CREATED) VALUES (?,?,?,?) ON CONFLICT " + - "(JWT_ID,TENANT_ID) DO UPDATE SET EXP_TIME = EXCLUDED.EXP_TIME, " + - "TIME_CREATED = EXCLUDED.TIME_CREATED;"; - - public static final String INSERT_OR_UPDATE_JWT_ID_ORACLE = "MERGE INTO IDN_OIDC_JTI USING dual ON " + - "(JWT_ID = ?) " + - "WHEN MATCHED THEN UPDATE SET EXP_TIME = ? , TIME_CREATED = ? " + - "WHEN NOT MATCHED THEN INSERT (JWT_ID, EXP_TIME, TIME_CREATED) " + - " VALUES (?, ?, ?)"; - public static final String INSERT_OR_UPDATE_TENANTED_JWT_ID_ORACLE = "MERGE INTO IDN_OIDC_JTI USING dual " + - "ON (JWT_ID = ? AND TENANT_ID = ?) " + - "WHEN MATCHED THEN UPDATE SET " + - "EXP_TIME = ? , " + - "TIME_CREATED = ? WHEN NOT MATCHED THEN INSERT (JWT_ID, TENANT_ID ,EXP_TIME, TIME_CREATED) " + - "VALUES (?,?,?,?);"; - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/PrivateKeyJWTClientAuthenticator.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/PrivateKeyJWTClientAuthenticator.java deleted file mode 100644 index 6c86be3e..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/PrivateKeyJWTClientAuthenticator.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2018, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt; - -import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.SignedJWT; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.identity.base.IdentityConstants; -import org.wso2.carbon.identity.core.util.IdentityUtil; -import org.wso2.carbon.identity.oauth.common.OAuth2ErrorCodes; -import org.wso2.carbon.identity.oauth2.bean.OAuthClientAuthnContext; -import org.wso2.carbon.identity.oauth2.client.authentication.AbstractOAuthClientAuthenticator; -import org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnException; -import org.wso2.carbon.identity.oauth2.model.ClientAuthenticationMethodModel; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal.JWTServiceDataHolder; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.validator.JWTValidator; - -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import javax.servlet.http.HttpServletRequest; - -import static org.apache.commons.lang.StringUtils.isEmpty; -import static org.apache.commons.lang.StringUtils.isNotEmpty; -import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OIDCConfigProperties.DEFAULT_VALUE_FOR_PREVENT_TOKEN_REUSE; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.AUDIENCE_CLAIM; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.DEFAULT_ENABLE_JTI_CACHE; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.DEFAULT_AUDIENCE; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.DEFAULT_VALIDITY_PERIOD_IN_MINUTES; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.EXPIRATION_TIME_CLAIM; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.ISSUER_CLAIM; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.JWT_ID_CLAIM; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.OAUTH_JWT_ASSERTION; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.OAUTH_JWT_ASSERTION_TYPE; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.OAUTH_JWT_BEARER_GRANT_TYPE; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.PREVENT_TOKEN_REUSE; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.REJECT_BEFORE_IN_MINUTES; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.PRIVATE_KEY_JWT; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.SUBJECT_CLAIM; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.TOKEN_ENDPOINT_ALIAS; - -/** - * Client Authentication handler to implement oidc private_key_jwt client authentication specDEFAULT_TOKEN_EP_ALIAS - * Reference. - */ -public class PrivateKeyJWTClientAuthenticator extends AbstractOAuthClientAuthenticator { - - private static final Log log = LogFactory.getLog(PrivateKeyJWTClientAuthenticator.class); - private static final String PRIVATE_KEY_JWT_CLIENT_AUTHENTICATOR_AUTH_METHOD = "private_key_jwt"; - private static final String PRIVATE_KEY_JWT_CLIENT_AUTHENTICATOR_DISPLAY_NAME = "Private Key JWT"; - private JWTValidator jwtValidator; - - private int rejectBeforePeriod = DEFAULT_VALIDITY_PERIOD_IN_MINUTES; - private boolean preventTokenReuse = DEFAULT_VALUE_FOR_PREVENT_TOKEN_REUSE; - private String tokenEPAlias = DEFAULT_AUDIENCE; - - public PrivateKeyJWTClientAuthenticator() { - - readServerConfig(); - jwtValidator = createJWTValidator(tokenEPAlias, preventTokenReuse, rejectBeforePeriod); - } - - private void readServerConfig(){ - - try { - if (isNotEmpty(properties.getProperty(TOKEN_ENDPOINT_ALIAS))) { - tokenEPAlias = properties.getProperty(TOKEN_ENDPOINT_ALIAS); - } - if (isNotEmpty(properties.getProperty(PREVENT_TOKEN_REUSE))) { - preventTokenReuse = Boolean.parseBoolean(properties.getProperty(PREVENT_TOKEN_REUSE)); - } - if (isNotEmpty(properties.getProperty(REJECT_BEFORE_IN_MINUTES))) { - rejectBeforePeriod = Integer.parseInt(properties.getProperty(REJECT_BEFORE_IN_MINUTES)); - } - JWTServiceDataHolder.getInstance().setPreventTokenReuse(preventTokenReuse); - } catch (NumberFormatException e) { - log.warn("Invalid PrivateKeyJWT Validity period found in the configuration. Using default value: " + - rejectBeforePeriod); - } - } - - /** - * To check whether the authentication is successful. - * - * @param httpServletRequest Http servelet request. - * @param bodyParameters Map of request body params. - * @param oAuthClientAuthnContext OAuthClientAuthnContext. - * @return true if the authentication is successful. - * @throws OAuthClientAuthnException OAuthClientAuthnException thrown with Invalid Request error code. - */ - @Override - public boolean authenticateClient(HttpServletRequest httpServletRequest, Map bodyParameters, - OAuthClientAuthnContext oAuthClientAuthnContext) throws OAuthClientAuthnException { - - oAuthClientAuthnContext.addParameter(Constants.AUTHENTICATOR_TYPE_PARAM, Constants.AUTHENTICATOR_TYPE_PK_JWT); - String requestUrl = httpServletRequest.getRequestURL().toString(); - - // Todo: remove after verification - if (log.isDebugEnabled()) { - log.debug("x-forwarded-for: " + httpServletRequest.getHeader("x-forwarded-for")); - log.debug("x-forwarded-host: " + httpServletRequest.getHeader("x-forwarded-host")); - log.debug("requestUrl: " + requestUrl); - } - - return jwtValidator.isValidAssertion(getSignedJWT(bodyParameters, oAuthClientAuthnContext), requestUrl); - } - - /** - * Returns whether the incoming request can be handled by the particular authenticator. - * - * @param httpServletRequest Http servelet request. - * @param bodyParameters Map of request body params. - * @param oAuthClientAuthnContext OAuthClientAuthnContext. - * @return true if the incoming request can be handled. - */ - @Override - public boolean canAuthenticate(HttpServletRequest httpServletRequest, Map bodyParameters, - OAuthClientAuthnContext oAuthClientAuthnContext) { - - String oauthJWTAssertionType = getBodyParameters(bodyParameters).get(OAUTH_JWT_ASSERTION_TYPE); - String oauthJWTAssertion = getBodyParameters(bodyParameters).get(OAUTH_JWT_ASSERTION); - return isValidJWTClientAssertionRequest(oauthJWTAssertionType, oauthJWTAssertion); - } - - /** - * Retrievs the client ID which is extracted from the JWT. - * - * @param httpServletRequest Http servelet request. - * @param bodyParameters Map of request body params. - * @param oAuthClientAuthnContext OAuthClientAuthnContext. - * @return jwt 'sub' value as the client id - * @throws OAuthClientAuthnException - */ - @Override - public String getClientId(HttpServletRequest httpServletRequest, Map bodyParameters, - OAuthClientAuthnContext oAuthClientAuthnContext) throws OAuthClientAuthnException { - - SignedJWT signedJWT = getSignedJWT(bodyParameters, oAuthClientAuthnContext); - JWTClaimsSet claimsSet = jwtValidator.getClaimSet(signedJWT); - return jwtValidator.resolveSubject(claimsSet); - } - - private SignedJWT getSignedJWT(Map bodyParameters, OAuthClientAuthnContext oAuthClientAuthnContext) - throws OAuthClientAuthnException { - - Object signedJWTFromContext = oAuthClientAuthnContext.getParameter(PRIVATE_KEY_JWT); - if (signedJWTFromContext != null) { - return (SignedJWT) signedJWTFromContext; - } - String assertion = getBodyParameters(bodyParameters).get(OAUTH_JWT_ASSERTION); - String errorMessage = "No Valid Assertion was found for " + Constants.OAUTH_JWT_BEARER_GRANT_TYPE; - SignedJWT signedJWT; - if (isEmpty(assertion)) { - throw new OAuthClientAuthnException(errorMessage, OAuth2ErrorCodes.INVALID_REQUEST); - } - try { - signedJWT = SignedJWT.parse(assertion); - } catch (ParseException e) { - if (log.isDebugEnabled()) { - log.debug(e.getMessage()); - } - throw new OAuthClientAuthnException("Error while parsing the JWT.", OAuth2ErrorCodes.INVALID_REQUEST); - } - if (signedJWT == null) { - throw new OAuthClientAuthnException(errorMessage, OAuth2ErrorCodes.INVALID_REQUEST); - } - oAuthClientAuthnContext.addParameter(PRIVATE_KEY_JWT, signedJWT); - return signedJWT; - } - - private boolean isValidJWTClientAssertionRequest(String clientAssertionType, String clientAssertion) { - - if (log.isDebugEnabled()) { - log.debug("Authenticate Requested with clientAssertionType : " + clientAssertionType); - if (IdentityUtil.isTokenLoggable(IdentityConstants.IdentityTokens.ACCESS_TOKEN)) { - log.debug("Authenticate Requested with clientAssertion : " + clientAssertion); - } - } - return OAUTH_JWT_BEARER_GRANT_TYPE.equals(clientAssertionType) && isNotEmpty(clientAssertion); - } - - private JWTValidator createJWTValidator(String tokenEPAlias, boolean preventTokenReuse, int rejectBefore) { - - return new JWTValidator(preventTokenReuse, tokenEPAlias, rejectBefore, null, populateMandatoryClaims(), - DEFAULT_ENABLE_JTI_CACHE); - } - - private List populateMandatoryClaims() { - - List mandatoryClaims = new ArrayList<>(); - mandatoryClaims.add(ISSUER_CLAIM); - mandatoryClaims.add(SUBJECT_CLAIM); - mandatoryClaims.add(AUDIENCE_CLAIM); - mandatoryClaims.add(EXPIRATION_TIME_CLAIM); - mandatoryClaims.add(JWT_ID_CLAIM); - return mandatoryClaims; - } - - /** - * Retrieve the authentication methods supported by the authenticator. - * - * @return Authentication methods supported by the authenticator. - */ - @Override - public List getSupportedClientAuthenticationMethods() { - - return Arrays.asList(new ClientAuthenticationMethodModel(PRIVATE_KEY_JWT_CLIENT_AUTHENTICATOR_AUTH_METHOD, - PRIVATE_KEY_JWT_CLIENT_AUTHENTICATOR_DISPLAY_NAME)); - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/cache/JWTCache.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/cache/JWTCache.java deleted file mode 100644 index c7e8ffe5..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/cache/JWTCache.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2017, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.cache; - -import org.wso2.carbon.identity.application.authentication.framework.cache.AuthenticationBaseCache; -import org.wso2.carbon.utils.CarbonUtils; - -/** - * Implements a cache to store JWT references - */ -public class JWTCache extends AuthenticationBaseCache { - public static final String PRIVATE_KEY_JWT_CACHE = "PrivateKeyJWT"; - private static volatile JWTCache instance; - - private JWTCache() { - super(PRIVATE_KEY_JWT_CACHE); - } - - public static JWTCache getInstance() { - CarbonUtils.checkSecurity(); - if (instance == null) { - synchronized (JWTCache.class) { - if (instance == null) { - instance = new JWTCache(); - } - } - } - return instance; - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/cache/JWTCacheEntry.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/cache/JWTCacheEntry.java deleted file mode 100644 index 16ed4960..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/cache/JWTCacheEntry.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.cache; - -import com.nimbusds.jwt.SignedJWT; -import org.wso2.carbon.identity.core.cache.CacheEntry; - -import java.text.ParseException; - -/** - * Cache Entry for JWT Cache - */ -public class JWTCacheEntry extends CacheEntry { - private String encodedJWT; - - public JWTCacheEntry(SignedJWT jwt) { - this.encodedJWT = jwt.serialize(); - } - - public SignedJWT getJwt() throws ParseException { - return SignedJWT.parse(this.encodedJWT); - } - - public String getEncodedJWt() { - return this.encodedJWT; - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/cache/JWTCacheKey.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/cache/JWTCacheKey.java deleted file mode 100644 index b0d19247..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/cache/JWTCacheKey.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.cache; - -import org.wso2.carbon.identity.core.cache.CacheKey; - -/** - * Cache key used to access JWT Cache Entry.. - */ -public class JWTCacheKey extends CacheKey { - - private static final long serialVersionUID = 718492345264523421L; - - private final String jti; - private final int tenantId; - - public JWTCacheKey(String jti, int tenantId) { - - this.jti = jti; - this.tenantId = tenantId; - } - - public JWTCacheKey(String jti) { - - this.jti = jti; - this.tenantId = -1; - } - - public String getJti() { - - return jti; - } - - public int getTenantId() { - - return tenantId; - } - - /** - * Equals method to compare two JWT Cache Key. - * - * @param o java.lang.Object - * @return True if both objects are same. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - if (!super.equals(o)) { - return false; - } - - JWTCacheKey that = (JWTCacheKey) o; - - if (!jti.equals(that.getJti())) { - return false; - } - return tenantId == (that.getTenantId()); - } - - /** - * This method used to derive hash value for this class. - * Idea of this hash method is return same value for same object and return different value for different object. - * Number 31 is used as common prime number to multiply result to get unique hash value. - * - * @return Hashcode. - */ - @Override - public int hashCode() { - - int result = super.hashCode(); - result = 31 * result + jti.hashCode(); - result = 31 * result + tenantId; - return result; - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/JWTClientAuthenticatorMgtService.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/JWTClientAuthenticatorMgtService.java deleted file mode 100644 index b022a09c..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/JWTClientAuthenticatorMgtService.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core; - -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.exception.JWTClientAuthenticatorServiceException; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.model.JWTClientAuthenticatorConfig; - -/** - * Service for managing the JWT Authenticator configurations of a tenant. - */ -public interface JWTClientAuthenticatorMgtService { - - /** - * Get the JWT Authenticator configurations of a tenant. - * - * @param tenantDomain The tenant domain. - * @return JWTClientAuthenticatorConfig Returns an instance of {@code JWTClientAuthenticatorConfig} belonging to the tenant. - * @throws JWTClientAuthenticatorServiceException - */ - JWTClientAuthenticatorConfig getPrivateKeyJWTClientAuthenticatorConfiguration(String tenantDomain) - throws JWTClientAuthenticatorServiceException; - - /** - * Set the JWT Authenticator configurations of a tenant. - * - * @param jwtClientAuthenticatorConfig The {@code JWTClientAuthenticatorConfig} object to be set. - * @param tenantDomain The tenant domain. - * @throws JWTClientAuthenticatorServiceException - */ - void setPrivateKeyJWTClientAuthenticatorConfiguration( - JWTClientAuthenticatorConfig jwtClientAuthenticatorConfig, String tenantDomain) - throws JWTClientAuthenticatorServiceException; -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/JWTClientAuthenticatorMgtServiceImpl.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/JWTClientAuthenticatorMgtServiceImpl.java deleted file mode 100644 index 5e5de1d0..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/JWTClientAuthenticatorMgtServiceImpl.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core; - -import org.wso2.carbon.identity.base.IdentityRuntimeException; -import org.wso2.carbon.identity.core.util.IdentityTenantUtil; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.constant.ErrorMessage; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.exception.JWTClientAuthenticatorServiceClientException; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.exception.JWTClientAuthenticatorServiceException; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.model.JWTClientAuthenticatorConfig; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal.JWTServiceDataHolder; - -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.util.ErrorUtils.handleClientException; - -/** - * Implementation of Service for managing the JWT Authenticator configurations of a tenant. - */ -public class JWTClientAuthenticatorMgtServiceImpl implements JWTClientAuthenticatorMgtService { - - /** - * {@inheritDoc} - */ - @Override - public JWTClientAuthenticatorConfig getPrivateKeyJWTClientAuthenticatorConfiguration (String tenantDomain) - throws JWTClientAuthenticatorServiceException { - - validateTenantDomain(tenantDomain); - - JWTClientAuthenticatorConfig JWTClientAuthenticatorConfig - = JWTServiceDataHolder.getInstance() - .getPrivateKeyJWTAuthenticationConfigurationDAO() - .getPrivateKeyJWTClientAuthenticationConfigurationByTenantDomain(tenantDomain); - return JWTClientAuthenticatorConfig; - } - - /** - * {@inheritDoc} - */ - @Override - public void setPrivateKeyJWTClientAuthenticatorConfiguration ( - JWTClientAuthenticatorConfig JWTClientAuthenticatorConfig, String tenantDomain) - throws JWTClientAuthenticatorServiceException { - - validateTenantDomain(tenantDomain); - JWTServiceDataHolder.getInstance().getPrivateKeyJWTAuthenticationConfigurationDAO() - .setPrivateKeyJWTClientAuthenticationConfigurationByTenantDomain - (JWTClientAuthenticatorConfig, tenantDomain); - - - } - - /** - * Validate the tenant domain. - * - * @param tenantDomain The tenant domain. - * @throws JWTClientAuthenticatorServiceClientException - */ - private void validateTenantDomain(String tenantDomain) - throws JWTClientAuthenticatorServiceClientException { - - try { - IdentityTenantUtil.getTenantId(tenantDomain); - } catch (IdentityRuntimeException e) { - throw handleClientException(ErrorMessage.ERROR_CODE_INVALID_TENANT_DOMAIN, e, tenantDomain); - } - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/constant/Constants.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/constant/Constants.java deleted file mode 100644 index 22bbdccb..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/constant/Constants.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.constant; - -/** - * Constants listed here for the Core Component. - */ -public class Constants { - - public static final String ENABLE_TOKEN_REUSE = "EnableTokenReuse"; - - /** - * Name of the {@code JWTClientAuthenticatorConfig} resource type in the Configuration Management API. - */ - public static final String JWT_CONFIGURATION_RESOURCE_TYPE_NAME = "PK_JWT_CONFIGURATION"; - - /** - * Name of the {@code JWTClientAuthenticatorConfig} resource (per tenant) in the Configuration Management API. - */ - public static final String JWT_CONFIGURATION_RESOURCE_NAME = "TENANT_PK_JWT_CONFIGURATION"; - - /** - * Description of the {@code JWTClientAuthenticatorConfig} resource type in the Configuration Management API. - */ - public static final String JWT_CONFIGURATION_RESOURCE_TYPE_DESCRIPTION = - "A resource type to keep the tenant private key jwt configuration."; -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/constant/ErrorMessage.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/constant/ErrorMessage.java deleted file mode 100644 index a0aef7fc..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/constant/ErrorMessage.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.constant; - -public enum ErrorMessage { - - /** - * Invalid tenant domain. - */ - ERROR_CODE_INVALID_TENANT_DOMAIN("60004", - "Invalid input.", - "%s is not a valid tenant domain."), - - /** - * Unable to retrieve JWT Authenticator configuration. - */ - ERROR_CODE_PK_JWT_CONFIG_RETRIEVE("65007", - "Unable to retrieve JWT Authenticator configuration.", - "Server encountered an error while retrieving the " + - "JWT Authenticator configuration of %s."); - - /** - * The error code. - */ - private final String code; - - /** - * The error message. - */ - private final String message; - - /** - * The error description. - */ - private final String description; - - - ErrorMessage(String code, String message, String description) { - this.code = code; - this.message = message; - this.description = description; - } - - /** - * Get the {@code code}. - * - * @return Returns the {@code code} to be set. - */ - public String getCode() { - - return code; - } - - /** - * Get the {@code message}. - * - * @return Returns the {@code message} to be set. - */ - public String getMessage() { - - return message; - } - - /** - * Get the {@code description}. - * - * @return Returns the {@code description} to be set. - */ - public String getDescription() { - - return description; - } - - @Override - public String toString() { - - return code + ":" + message; - } -} - diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/JWTAuthenticationConfigurationDAO.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/JWTAuthenticationConfigurationDAO.java deleted file mode 100644 index a6749506..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/JWTAuthenticationConfigurationDAO.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao; - -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.exception.JWTClientAuthenticatorServiceServerException; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.model.JWTClientAuthenticatorConfig; - -/** - * Perform CRUD operations for {@link JWTClientAuthenticatorConfig}. - */ -public interface JWTAuthenticationConfigurationDAO { - - /** - * Get priority value for the {@link JWTAuthenticationConfigurationDAO}. - * - * @return Priority value for the DAO. - */ - int getPriority(); - - /** - * Get the JWT Authenticator configuration of a tenant. - * - * @param tenantDomain The tenant domain. - * @return JWTClientAuthenticatorConfig The configuration model. - * @throws JWTClientAuthenticatorServiceServerException JWTClientAuthenticatorServiceServerException - */ - JWTClientAuthenticatorConfig getPrivateKeyJWTClientAuthenticationConfigurationByTenantDomain(String tenantDomain) - throws JWTClientAuthenticatorServiceServerException; - - /** - * Set the JWT Authenticator configuration of a tenant. - * - * @param JWTClientAuthenticatorConfig The new JWT Authenticator configuration to be set. - * @param tenantDomain The tenant domain. - * @throws JWTClientAuthenticatorServiceServerException JWTClientAuthenticatorServiceServerException - */ - void setPrivateKeyJWTClientAuthenticationConfigurationByTenantDomain(JWTClientAuthenticatorConfig JWTClientAuthenticatorConfig, String tenantDomain) - throws JWTClientAuthenticatorServiceServerException; -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/cache/JWTConfigCache.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/cache/JWTConfigCache.java deleted file mode 100644 index 21e09ff1..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/cache/JWTConfigCache.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.cache; - -import org.wso2.carbon.identity.application.authentication.framework.cache.AuthenticationBaseCache; -import org.wso2.carbon.utils.CarbonUtils; - -/** - * Implements a cache to store JWT Configurations. - */ -public class JWTConfigCache extends AuthenticationBaseCache { - public static final String PRIVATE_KEY_JWT_CONFIG_CACHE = "PrivateKeyJWTConfig"; - private static volatile JWTConfigCache instance; - - private JWTConfigCache() { - super(PRIVATE_KEY_JWT_CONFIG_CACHE); - } - - public static JWTConfigCache getInstance() { - CarbonUtils.checkSecurity(); - if (instance == null) { - synchronized (JWTConfigCache.class) { - if (instance == null) { - instance = new JWTConfigCache(); - } - } - } - return instance; - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/cache/JWTConfigCacheEntry.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/cache/JWTConfigCacheEntry.java deleted file mode 100644 index 2929835f..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/cache/JWTConfigCacheEntry.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.cache; - -import org.wso2.carbon.identity.core.cache.CacheEntry; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.model.JWTClientAuthenticatorConfig; - -/** - * Cache Entry for JWT Configuration Cache. - */ -public class JWTConfigCacheEntry extends CacheEntry { - private JWTClientAuthenticatorConfig JWTClientAuthenticatorConfig; - - public JWTConfigCacheEntry(JWTClientAuthenticatorConfig JWTClientAuthenticatorConfig) { - - this.JWTClientAuthenticatorConfig = JWTClientAuthenticatorConfig; - } - - public JWTClientAuthenticatorConfig getPrivateKeyJWTClientAuthenticatorConfig() { - - return JWTClientAuthenticatorConfig; - } - - public void setPrivateKeyJWTClientAuthenticatorConfig( - JWTClientAuthenticatorConfig JWTClientAuthenticatorConfig) { - - this.JWTClientAuthenticatorConfig = JWTClientAuthenticatorConfig; - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/cache/JWTConfigCacheKey.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/cache/JWTConfigCacheKey.java deleted file mode 100644 index 3356da71..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/cache/JWTConfigCacheKey.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.cache; - -import org.wso2.carbon.identity.core.cache.CacheKey; - -/** - * Cache key used to access JWT Configuration Cache Entry. - */ -public class JWTConfigCacheKey extends CacheKey { - - private static final long serialVersionUID = 718492345264523421L; - - private final String tenantDomain; - - public String getTenantDomain() { - - return tenantDomain; - } - - public JWTConfigCacheKey(String tenantDomain) { - - this.tenantDomain = tenantDomain; - } - - /** - * Equals method to compare two JWT Cache Key. - * - * @param o java.lang.Object - * @return True if both objects are same. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - if (!super.equals(o)) { - return false; - } - - JWTConfigCacheKey that = (JWTConfigCacheKey) o; - return tenantDomain.equals(that.getTenantDomain()); - } - - /** - * This method used to derive hash value for this class. - * Idea of this hash method is return same value for same object and return different value for different object. - * Number 31 is used as common prime number to multiply result to get unique hash value. - * - * @return Hashcode. - */ - @Override - public int hashCode() { - - int result = super.hashCode(); - result = 31 * result + tenantDomain.hashCode(); - return result; - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/impl/CacheBackedJWTConfigurationDAOImpl.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/impl/CacheBackedJWTConfigurationDAOImpl.java deleted file mode 100644 index 4a2d26db..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/impl/CacheBackedJWTConfigurationDAOImpl.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.impl; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.JWTAuthenticationConfigurationDAO; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.cache.JWTConfigCache; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.cache.JWTConfigCacheEntry; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.cache.JWTConfigCacheKey; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.exception.JWTClientAuthenticatorServiceServerException; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.model.JWTClientAuthenticatorConfig; - -/** - * Cached DAO layer for JWT Authenticator Configurations. - * All the DAO access should happen through this layer to ensure single point of caching. - */ -public class CacheBackedJWTConfigurationDAOImpl implements JWTAuthenticationConfigurationDAO { - - private static final Log log = LogFactory.getLog(CacheBackedJWTConfigurationDAOImpl.class); - - private final JWTAuthenticationConfigurationDAO privateKeyJWTAuthenticationConfigurationDAO; - - public CacheBackedJWTConfigurationDAOImpl(JWTAuthenticationConfigurationDAO - privateKeyJWTAuthenticationConfigurationDAO) { - - this.privateKeyJWTAuthenticationConfigurationDAO = privateKeyJWTAuthenticationConfigurationDAO; - } - - /** - * {@inheritDoc} - */ - @Override - public int getPriority() { - - return 5; - } - - /** - * {@inheritDoc} - */ - @Override - public JWTClientAuthenticatorConfig getPrivateKeyJWTClientAuthenticationConfigurationByTenantDomain( - String tenantDomain) - throws JWTClientAuthenticatorServiceServerException { - - JWTClientAuthenticatorConfig cachedResult = getJWTConfigurationFromCache(tenantDomain); - if (cachedResult != null) { - if (log.isDebugEnabled()) { - log.debug("JWT Authenticator configuration is not available " + - "in the cache for tenant domain: " + tenantDomain + ". Trying to get data from the database."); - } - return cachedResult; - } - - JWTClientAuthenticatorConfig JWTClientAuthenticatorConfig = privateKeyJWTAuthenticationConfigurationDAO. - getPrivateKeyJWTClientAuthenticationConfigurationByTenantDomain(tenantDomain); - - addJWTAuthenticatorConfigurationToCache(JWTClientAuthenticatorConfig, tenantDomain); - return JWTClientAuthenticatorConfig; - } - - /** - * {@inheritDoc} - */ - @Override - public void setPrivateKeyJWTClientAuthenticationConfigurationByTenantDomain( - JWTClientAuthenticatorConfig JWTClientAuthenticatorConfig, String tenantDomain) - throws JWTClientAuthenticatorServiceServerException { - - clearCaches(tenantDomain); - privateKeyJWTAuthenticationConfigurationDAO.setPrivateKeyJWTClientAuthenticationConfigurationByTenantDomain - (JWTClientAuthenticatorConfig, tenantDomain); - } - - /** - * Add JWT Authenticator configurations to the cache. - * - * @param JWTClientAuthenticatorConfig The JWT Authenticator configuration that should be added to the cache. - * @param tenantDomain The tenant domain specific to the cache entry. - */ - private void addJWTAuthenticatorConfigurationToCache( - JWTClientAuthenticatorConfig JWTClientAuthenticatorConfig, - String tenantDomain) { - - JWTConfigCacheKey cacheKey = new JWTConfigCacheKey(tenantDomain); - JWTConfigCacheEntry cacheEntry = new JWTConfigCacheEntry(JWTClientAuthenticatorConfig); - - if (log.isDebugEnabled()) { - log.debug("Adding JWT Authenticator configuration to Cache with Key: " + tenantDomain); - } - - JWTConfigCache.getInstance().addToCache(cacheKey, cacheEntry, tenantDomain); - } - - /** - * Get JWT Authenticator configuration from the cache. - * - * @param tenantDomain The tenant domain specific to the cache entry. - * @return Returns an instance of {@code JWTClientAuthenticatorConfig}(s) - * if the cached JWT Authenticator configuration is found for the tenant. Else return {@code null}. - */ - private JWTClientAuthenticatorConfig getJWTConfigurationFromCache(String tenantDomain) { - - JWTConfigCacheKey cacheKey = new JWTConfigCacheKey(tenantDomain); - JWTConfigCache cache = JWTConfigCache.getInstance(); - JWTConfigCacheEntry cacheEntry = cache.getValueFromCache(cacheKey, tenantDomain); - - if (cacheEntry != null && cacheEntry.getPrivateKeyJWTClientAuthenticatorConfig() != null) { - return cacheEntry.getPrivateKeyJWTClientAuthenticatorConfig(); - } else { - if (log.isDebugEnabled()) { - log.debug("Cache entry not found for cache key :" + tenantDomain); - } - return null; - } - } - - /** - * Clear JWT Authenticator configuration caches of a particular tenant. - * - * @param tenantDomain The domain of the tenant. - */ - private void clearCaches(String tenantDomain) { - - JWTConfigCacheKey cacheKey = new JWTConfigCacheKey(tenantDomain); - JWTConfigCache.getInstance().clearCacheEntry(cacheKey, tenantDomain); - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/impl/JWTAuthenticationConfigurationDAOImpl.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/impl/JWTAuthenticationConfigurationDAOImpl.java deleted file mode 100644 index e952c450..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/impl/JWTAuthenticationConfigurationDAOImpl.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.impl; - -import org.wso2.carbon.identity.configuration.mgt.core.ConfigurationManager; -import org.wso2.carbon.identity.configuration.mgt.core.exception.ConfigurationManagementException; -import org.wso2.carbon.identity.configuration.mgt.core.model.Resource; -import org.wso2.carbon.identity.configuration.mgt.core.model.ResourceAdd; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.JWTAuthenticationConfigurationDAO; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.exception.JWTClientAuthenticatorServiceServerException; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.model.JWTClientAuthenticatorConfig; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.util.Util; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal.JWTServiceDataHolder; - -import static org.wso2.carbon.identity.configuration.mgt.core.constant.ConfigurationConstants.ErrorMessages.ERROR_CODE_RESOURCE_DOES_NOT_EXISTS; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.constant.Constants.JWT_CONFIGURATION_RESOURCE_NAME; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.constant.Constants.JWT_CONFIGURATION_RESOURCE_TYPE_NAME; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.constant.ErrorMessage.ERROR_CODE_PK_JWT_CONFIG_RETRIEVE; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.util.ErrorUtils.handleServerException; - -/** - * DAO layer for JWT Authenticator Configurations. - */ -public class JWTAuthenticationConfigurationDAOImpl implements JWTAuthenticationConfigurationDAO { - - /** - * {@inheritDoc} - */ - @Override - public int getPriority() { - return 10; - } - - /** - * {@inheritDoc} - */ - @Override - public JWTClientAuthenticatorConfig getPrivateKeyJWTClientAuthenticationConfigurationByTenantDomain - (String tenantDomain) throws JWTClientAuthenticatorServiceServerException { - - try { - - Resource resource = getResource(JWT_CONFIGURATION_RESOURCE_TYPE_NAME, JWT_CONFIGURATION_RESOURCE_NAME); - JWTClientAuthenticatorConfig JWTClientAuthenticatorConfig; - if (resource == null) { - JWTClientAuthenticatorConfig = Util.getServerConfiguration(); - } else { - JWTClientAuthenticatorConfig = Util.parseResource(resource); - } - return JWTClientAuthenticatorConfig; - } catch (ConfigurationManagementException e) { - throw handleServerException(ERROR_CODE_PK_JWT_CONFIG_RETRIEVE, e, tenantDomain); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void setPrivateKeyJWTClientAuthenticationConfigurationByTenantDomain - (JWTClientAuthenticatorConfig jwtClientAuthenticatorConfig, String tenantDomain) - throws JWTClientAuthenticatorServiceServerException { - - try { - ResourceAdd resourceAdd = Util.parseConfig(jwtClientAuthenticatorConfig); - getConfigurationManager().replaceResource(JWT_CONFIGURATION_RESOURCE_TYPE_NAME, resourceAdd); - } catch (ConfigurationManagementException e) { - throw handleServerException(ERROR_CODE_PK_JWT_CONFIG_RETRIEVE, e, tenantDomain); - } - } - - /** - * Retrieve the ConfigurationManager instance from the JWTServiceDataHolder. - * - * @return ConfigurationManager The ConfigurationManager instance. - */ - private ConfigurationManager getConfigurationManager() { - - return JWTServiceDataHolder.getInstance().getConfigurationManager(); - } - - /** - * Configuration Management API returns a ConfigurationManagementException with the error code CONFIGM_00017 when - * resource is not found. This method wraps the original method and returns null if the resource is not found. - * - * @param resourceTypeName Resource type name. - * @param resourceName Resource name. - * @return Retrieved resource from the configuration store. Returns {@code null} if the resource is not found. - * @throws ConfigurationManagementException - */ - private Resource getResource(String resourceTypeName, String resourceName) throws ConfigurationManagementException { - - try { - return getConfigurationManager().getResource(resourceTypeName, resourceName); - } catch (ConfigurationManagementException e) { - if (ERROR_CODE_RESOURCE_DOES_NOT_EXISTS.getCode().equals(e.getErrorCode())) { - return null; - } else { - throw e; - } - } - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/exception/JWTClientAuthenticatorServiceClientException.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/exception/JWTClientAuthenticatorServiceClientException.java deleted file mode 100644 index 12a0b4d7..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/exception/JWTClientAuthenticatorServiceClientException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.exception; - -/** - * Client exception class for the JWT Authentication Service. - */ -public class JWTClientAuthenticatorServiceClientException extends JWTClientAuthenticatorServiceException { - - /** - * The default constructor. - */ - public JWTClientAuthenticatorServiceClientException() { - - } - - /** - * Constructor with {@code message} and {@code errorCode} parameters. - * - * @param message Message to be included in the exception. - * @param errorCode Error code of the exception. - */ - public JWTClientAuthenticatorServiceClientException(String message, String errorCode) { - - super(message, errorCode); - } - - /** - * Constructor with {@code message}, {@code errorCode} and {@code cause} parameters. - * - * @param message Message to be included in the exception. - * @param errorCode Error code of the exception. - * @param cause Exception to be wrapped. - */ - public JWTClientAuthenticatorServiceClientException(String message, String errorCode, Throwable cause) { - - super(message, errorCode, cause); - } - - /** - * Constructor with {@code cause} parameter. - * - * @param cause Exception to be wrapped. - */ - public JWTClientAuthenticatorServiceClientException(Throwable cause) { - - super(cause); - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/exception/JWTClientAuthenticatorServiceException.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/exception/JWTClientAuthenticatorServiceException.java deleted file mode 100644 index 60cb4362..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/exception/JWTClientAuthenticatorServiceException.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.exception; - -/** - * Base exception class for the JWT Authentication Service. - */ -public class JWTClientAuthenticatorServiceException extends Exception { - - /** - * The error code. - */ - private String errorCode; - - /** - * The default constructor. - */ - public JWTClientAuthenticatorServiceException() { - - super(); - } - - /** - * Constructor with {@code message} and {@code errorCode} parameters. - * - * @param message Message to be included in the exception. - * @param errorCode Error code of the exception. - */ - public JWTClientAuthenticatorServiceException(String message, String errorCode) { - - super(message); - this.errorCode = errorCode; - } - - /** - * Constructor with {@code message}, {@code errorCode} and {@code cause} parameters. - * - * @param message Message to be included in the exception. - * @param errorCode Error code of the exception. - * @param cause Exception to be wrapped. - */ - public JWTClientAuthenticatorServiceException(String message, String errorCode, Throwable cause) { - - super(message, cause); - this.errorCode = errorCode; - } - - /** - * Constructor with {@code cause} parameter. - * - * @param cause Exception to be wrapped. - */ - public JWTClientAuthenticatorServiceException(Throwable cause) { - - super(cause); - } - - /** - * Get the {@code errorCode}. - * - * @return Returns the {@code errorCode}. - */ - public String getErrorCode() { - - return errorCode; - } - - /** - * Set the {@code errorCode}. - * - * @param errorCode The value to be set as the {@code errorCode}. - */ - protected void setErrorCode(String errorCode) { - - this.errorCode = errorCode; - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/exception/JWTClientAuthenticatorServiceServerException.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/exception/JWTClientAuthenticatorServiceServerException.java deleted file mode 100644 index fc626702..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/exception/JWTClientAuthenticatorServiceServerException.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.exception; - -/** - * Server exception class for the JWT Authenticator Service. - */ -public class JWTClientAuthenticatorServiceServerException extends JWTClientAuthenticatorServiceException { - - /** - * The default constructor. - */ - public JWTClientAuthenticatorServiceServerException() { - - super(); - } - - /** - * Constructor with {@code message} and {@code errorCode} parameters. - * - * @param message Message to be included in the exception. - * @param errorCode Error code of the exception. - */ - public JWTClientAuthenticatorServiceServerException(String message, String errorCode) { - - super(message, errorCode); - } - - /** - * Constructor with {@code message}, {@code errorCode} and {@code cause} parameters. - * - * @param message Message to be included in the exception. - * @param errorCode Error code of the exception. - * @param cause Exception to be wrapped. - */ - public JWTClientAuthenticatorServiceServerException(String message, String errorCode, Throwable cause) { - - super(message, errorCode, cause); - } - - /** - * Constructor with {@code cause} parameter. - * - * @param cause Exception to be wrapped. - */ - public JWTClientAuthenticatorServiceServerException(Throwable cause) { - - super(cause); - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/model/JWTClientAuthenticatorConfig.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/model/JWTClientAuthenticatorConfig.java deleted file mode 100644 index 30a77c1a..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/model/JWTClientAuthenticatorConfig.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.model; - -/** - * JWT Client Authenticator Configuration Model class for DAOs. - */ -public class JWTClientAuthenticatorConfig { - - /** - * If {@code true} JTI for JWT can be reused only if previous JWT expires, - * else JTI is unique even after the expiration. - */ - private boolean enableTokenReuse; - - public boolean isEnableTokenReuse() { - - return enableTokenReuse; - } - - public void setEnableTokenReuse(boolean enableTokenReuse) { - - this.enableTokenReuse = enableTokenReuse; - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/util/ErrorUtils.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/util/ErrorUtils.java deleted file mode 100644 index 8e2bfabf..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/util/ErrorUtils.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.util; - -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.constant.ErrorMessage; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.exception.JWTClientAuthenticatorServiceClientException; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.exception.JWTClientAuthenticatorServiceServerException; - -/** - * Error utilities. - */ -public class ErrorUtils { - - /** - * Handle server exceptions. - * - * @param error The ErrorMessage. - * @param data Additional data that should be added to the error message. This is a String var-arg. - * @return JWTClientAuthenticatorServiceServerException instance. - */ - public static JWTClientAuthenticatorServiceServerException handleServerException(ErrorMessage error, - String... data) { - - return new JWTClientAuthenticatorServiceServerException - (String.format(error.getDescription(), data), error.getCode()); - } - - /** - * Handle server exceptions. - * - * @param error The ErrorMessage. - * @param e Original error. - * @param data Additional data that should be added to the error message. This is a String var-arg. - * @return JWTClientAuthenticatorServiceServerException instance. - */ - public static JWTClientAuthenticatorServiceServerException handleServerException(ErrorMessage error, - Throwable e, - String... data) { - - return new JWTClientAuthenticatorServiceServerException - (String.format(error.getDescription(), data), error.getCode(), - e); - } - - /** - * Handle client exceptions. - * - * @param error The ErrorMessage. - * @param data Additional data that should be added to the error message. This is a String var-arg. - * @return JWTClientAuthenticatorServiceClientException instance. - */ - public static JWTClientAuthenticatorServiceClientException handleClientException(ErrorMessage error, - String... data) { - - return new JWTClientAuthenticatorServiceClientException(String.format(error.getDescription(), data), - error.getCode()); - } - - /** - * Handle client exceptions. - * - * @param error The ErrorMessage. - * @param e Original error. - * @param data Additional data that should be added to the error message. This is a String var-arg. - * @return JWTClientAuthenticatorServiceClientException instance. - */ - public static JWTClientAuthenticatorServiceClientException handleClientException(ErrorMessage error, - Throwable e, - String... data) { - - return new JWTClientAuthenticatorServiceClientException(String.format(error.getDescription(), data), - error.getCode(), - e); - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/util/Util.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/util/Util.java deleted file mode 100644 index a279810e..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/util/Util.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.util; - -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang.StringUtils; -import org.wso2.carbon.identity.configuration.mgt.core.model.Attribute; -import org.wso2.carbon.identity.configuration.mgt.core.model.Resource; -import org.wso2.carbon.identity.configuration.mgt.core.model.ResourceAdd; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.model.JWTClientAuthenticatorConfig; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal.JWTServiceDataHolder; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.constant.Constants.ENABLE_TOKEN_REUSE; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.constant.Constants.JWT_CONFIGURATION_RESOURCE_NAME; - -/** - * Util class. - */ -public class Util { - - /** - * Read the default JWT Authenticator configuration properties from the Data Holder.. - * - * @return Server default {@code JWTClientAuthenticatorConfig} object. - */ - public static JWTClientAuthenticatorConfig getServerConfiguration() { - - JWTClientAuthenticatorConfig JWTClientAuthenticatorConfig = new JWTClientAuthenticatorConfig(); - - JWTClientAuthenticatorConfig. - setEnableTokenReuse(!JWTServiceDataHolder.getInstance().isPreventTokenReuse()); - return JWTClientAuthenticatorConfig; - } - - /** - * Parse Resource to JWTClientAuthenticatorConfig instance. - * - * @param resource Resource - * @return JWTClientAuthenticatorConfig Configuration instance. - */ - public static JWTClientAuthenticatorConfig parseResource(Resource resource) { - - JWTClientAuthenticatorConfig JWTClientAuthenticatorConfig = new JWTClientAuthenticatorConfig(); - - if (resource.isHasAttribute()) { - List attributes = resource.getAttributes(); - Map attributeMap = getAttributeMap(attributes); - JWTClientAuthenticatorConfig.setEnableTokenReuse( - Boolean.parseBoolean(attributeMap.get(ENABLE_TOKEN_REUSE))); - } - return JWTClientAuthenticatorConfig; - - } - - private static Map getAttributeMap(List attributes) { - - if (CollectionUtils.isNotEmpty(attributes)) { - return attributes.stream().collect(Collectors.toMap(Attribute::getKey, Attribute::getValue)); - } - - return Collections.emptyMap(); - } - - /** - * Parse JWTClientAuthenticatorConfig to Resource instance. - * - * @param jwtClientAuthenticatorConfig Configuration Instance. - * @return ResourceAdd Resource instance. - */ - public static ResourceAdd parseConfig(JWTClientAuthenticatorConfig jwtClientAuthenticatorConfig) { - - ResourceAdd resourceAdd = new ResourceAdd(); - resourceAdd.setName(JWT_CONFIGURATION_RESOURCE_NAME); - List attributes = new ArrayList<>(); - addAttribute(attributes, jwtClientAuthenticatorConfig); - resourceAdd.setAttributes(attributes); - return resourceAdd; - } - - private static void addAttribute(List attributeList, - JWTClientAuthenticatorConfig jwtClientAuthenticatorConfig) { - - String value = String.valueOf(jwtClientAuthenticatorConfig.isEnableTokenReuse()); - if (StringUtils.isNotBlank(value)) { - Attribute attribute = new Attribute(); - attribute.setKey(ENABLE_TOKEN_REUSE); - attribute.setValue(value); - attributeList.add(attribute); - } - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/dao/JWTEntry.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/dao/JWTEntry.java deleted file mode 100644 index 26a525a6..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/dao/JWTEntry.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2017, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.dao; - -/** - * A model class which is use to persist the JWT token in database as JWTEntry objects. - */ -public class JWTEntry { - - private long exp; - private long createdTime; - - private int tenantId; - - public JWTEntry(long exp, long createdTime) { - - this.exp = exp; - this.createdTime = createdTime; - } - - public JWTEntry(long exp, long createdTime, int tenantId) { - - this.exp = exp; - this.createdTime = createdTime; - this.tenantId = tenantId; - } - - public long getExp() { - - return exp; - } - - public long getCreatedTime() { - - return createdTime; - } - - public int getTenantId() { - - return tenantId; - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/dao/JWTStorageManager.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/dao/JWTStorageManager.java deleted file mode 100644 index 2cc3918b..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/dao/JWTStorageManager.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (c) 2017, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.dao; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.database.utils.jdbc.exceptions.DataAccessException; -import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil; -import org.wso2.carbon.identity.oauth.common.OAuth2ErrorCodes; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; -import org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnException; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal.JWTServiceDataHolder; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.Util; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; -import java.util.TimeZone; - -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.DEFAULT_TENANT_ID; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.GET_JWT; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.GET_JWT_DETAILS; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.INSERT_JWD_ID; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.SQLQueries.EXP_TIME; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.SQLQueries.TENANT_ID; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.SQLQueries.TIME_CREATED; - -import static org.wso2.carbon.identity.core.util.JdbcUtils.isDB2DB; -import static org.wso2.carbon.identity.core.util.JdbcUtils.isH2DB; -import static org.wso2.carbon.identity.core.util.JdbcUtils.isMSSqlDB; -import static org.wso2.carbon.identity.core.util.JdbcUtils.isMariaDB; -import static org.wso2.carbon.identity.core.util.JdbcUtils.isMySQLDB; -import static org.wso2.carbon.identity.core.util.JdbcUtils.isOracleDB; -import static org.wso2.carbon.identity.core.util.JdbcUtils.isPostgreSQLDB; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.UPSERT_H2; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.UPSERT_MSSQL_DB2; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.UPSERT_MYSQL; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.UPSERT_ORACLE; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.UPSERT_POSTGRESQL; - -/** - * JWT token persistence is managed by JWTStorageManager - * It saved JWTEntry instances in IDN_OIDC_JTI table of Identity Database. - */ -public class JWTStorageManager { - - private static final Log log = LogFactory.getLog(JWTStorageManager.class); - - /** - * Check whether a JWT Entry with given jti exists in the DB. - * - * @param jti JWT token id - * @return true if an entry is found - * @throws IdentityOAuth2Exception when exception occurs - */ - public boolean isJTIExistsInDB(String jti) throws OAuthClientAuthnException { - - Connection dbConnection = IdentityDatabaseUtil.getDBConnection(); - PreparedStatement prepStmt = null; - boolean isExists = false; - ResultSet rs = null; - try { - if (Util.isTenantIdColumnAvailableInIdnOidcAuth()) { - log.warn("Checking JWT existence with JTI only, but tenant id also required to fetch unique data." + - "This method will be deprecated soon. Use getJwtsFromDB instead."); - } else { - prepStmt = dbConnection.prepareStatement(Constants.SQLQueries.GET_JWT_ID); - prepStmt.setString(1, jti); - rs = prepStmt.executeQuery(); - int count = 0; - if (rs.next()) { - count = rs.getInt(1); - } - if (count > 0) { - isExists = true; - } - } - } catch (SQLException e) { - if (log.isDebugEnabled()) { - log.debug("Error when retrieving the JWT ID: " + jti, e); - } - throw new OAuthClientAuthnException("Error occurred while validating the JTI: " + jti + " of the " + - "assertion.", OAuth2ErrorCodes.INVALID_REQUEST); - } finally { - IdentityDatabaseUtil.closeAllConnections(dbConnection, rs, prepStmt); - } - return isExists; - } - - /** - * To get a list of persisted JWTs for a given JTI. - * - * @param jti JTI. - * @return List of JWTEntries. - * @throws OAuthClientAuthnException OAuthClientAuthnException thrown with Invalid Request error code. - */ - public List getJwtsFromDB(String jti, int tenantId) throws OAuthClientAuthnException { - - List JWTEntries = new ArrayList<>(); - - Connection dbConnection = IdentityDatabaseUtil.getDBConnection(); - PreparedStatement prepStmt = null; - ResultSet rs = null; - try { - if (Util.isTenantIdColumnAvailableInIdnOidcAuth()) { - prepStmt = dbConnection.prepareStatement(Util.getDBQuery(GET_JWT_DETAILS)); - prepStmt.setString(1, jti); - prepStmt.setInt(2, tenantId); - prepStmt.setInt(3, DEFAULT_TENANT_ID); - rs = prepStmt.executeQuery(); - while (rs.next()) { - int tenantID = rs.getInt(TENANT_ID); - long exp = rs.getTimestamp(EXP_TIME, - Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))).getTime(); - long created = rs.getTimestamp(TIME_CREATED, - Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))).getTime(); - JWTEntries.add(new JWTEntry(exp, created, tenantID)); - } - } else { - prepStmt = dbConnection.prepareStatement(Util.getDBQuery(GET_JWT)); - prepStmt.setString(1, jti); - rs = prepStmt.executeQuery(); - while (rs.next()) { - long exp = rs.getTime(EXP_TIME, - Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))).getTime(); - long created = rs.getTime(TIME_CREATED, - Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))).getTime(); - JWTEntries.add(new JWTEntry(exp, created)); - } - } - - } catch (SQLException e) { - if (log.isDebugEnabled()) { - log.debug("Error when retrieving the JWT ID: " + jti + " tenant id: " + tenantId, e); - } - throw new OAuthClientAuthnException("Error occurred while validating the JTI: " + jti + " of the " + - "assertion.", OAuth2ErrorCodes.INVALID_REQUEST); - } finally { - IdentityDatabaseUtil.closeAllConnections(dbConnection, rs, prepStmt); - } - return JWTEntries; - } - - /** - * To persist unique id for jti in the table. - * - * @param jti JTI a unique id. - * @param tenantId Tenant id. - * @param expTime Expiration time. - * @param timeCreated JTI inserted time. - * @throws IdentityOAuth2Exception - * @deprecated Use {@link #persistJWTIdInDB(String, int, long, long, boolean)} instead. - */ - public void persistJWTIdInDB(String jti, int tenantId, long expTime, long timeCreated) - throws OAuthClientAuthnException { - - persistJWTIdInDB(jti, tenantId, expTime, timeCreated, JWTServiceDataHolder.getInstance().isPreventTokenReuse()); - } - - /** - * To persist unique id for jti in the table. - * - * @param jti JTI a unique id. - * @param tenantId Tenant id. - * @param expTime Expiration time. - * @param timeCreated JTI inserted time. - * @param preventTokenReuse Whether to prevent token reuse. - * @throws IdentityOAuth2Exception - */ - public void persistJWTIdInDB(String jti, int tenantId, long expTime, long timeCreated, boolean preventTokenReuse) - throws OAuthClientAuthnException { - - Connection connection = null; - PreparedStatement preparedStatement = null; - try { - connection = IdentityDatabaseUtil.getDBConnection(); - if (preventTokenReuse) { - preparedStatement = connection.prepareStatement(Util.getDBQuery(INSERT_JWD_ID)); - preparedStatement.setString(1, jti); - if (Util.isTenantIdColumnAvailableInIdnOidcAuth()) { - preparedStatement.setInt(2, tenantId); - Timestamp timestamp = new Timestamp(timeCreated); - Timestamp expTimestamp = new Timestamp(expTime); - preparedStatement.setTimestamp(3, expTimestamp, Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))); - preparedStatement.setTimestamp(4, timestamp, - Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))); - } else { - Timestamp timestamp = new Timestamp(timeCreated); - Timestamp expTimestamp = new Timestamp(expTime); - preparedStatement.setTimestamp(2, expTimestamp, Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))); - preparedStatement.setTimestamp(3, timestamp, - Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))); - } - } else { - if (isH2DB()) { - preparedStatement = connection.prepareStatement(Util.getDBQuery(UPSERT_H2)); - } else if (isMySQLDB() || isMariaDB()) { - preparedStatement = connection.prepareStatement(Util.getDBQuery(UPSERT_MYSQL)); - } else if (isPostgreSQLDB()) { - preparedStatement = connection.prepareStatement(Util.getDBQuery(UPSERT_POSTGRESQL)); - } else if (isMSSqlDB() || isDB2DB()) { - preparedStatement = connection.prepareStatement(Util.getDBQuery(UPSERT_MSSQL_DB2)); - } else if (isOracleDB()) { - preparedStatement = connection.prepareStatement(Util.getDBQuery(UPSERT_ORACLE)); - } - - if (preparedStatement != null) { - preparedStatement.setString(1, jti); - if (Util.isTenantIdColumnAvailableInIdnOidcAuth()) { - preparedStatement.setInt(2, tenantId); - Timestamp timestamp = new Timestamp(timeCreated); - Timestamp expTimestamp = new Timestamp(expTime); - preparedStatement.setTimestamp(3, expTimestamp, Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))); - preparedStatement.setTimestamp(4, timestamp, - Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))); - if (isOracleDB()) { - preparedStatement.setString(5, jti); - preparedStatement.setInt(6, tenantId); - preparedStatement.setTimestamp(7, expTimestamp, - Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))); - preparedStatement.setTimestamp(8, timestamp, - Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))); - } - } else { - Timestamp timestamp = new Timestamp(timeCreated); - Timestamp expTimestamp = new Timestamp(expTime); - preparedStatement.setTimestamp(2, expTimestamp, Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))); - preparedStatement.setTimestamp(3, timestamp, - Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))); - if (isOracleDB()) { - preparedStatement.setString(4, jti); - preparedStatement.setTimestamp(5, expTimestamp, - Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))); - preparedStatement.setTimestamp(6, timestamp, - Calendar.getInstance(TimeZone.getTimeZone(Constants.UTC))); - } - } - } - } - if (preparedStatement != null) { - preparedStatement.executeUpdate(); - preparedStatement.close(); - connection.commit(); - } - } catch (SQLException | DataAccessException e) { - String error = "Error when storing the JWT ID: " + jti + " with exp: " + expTime; - if (log.isDebugEnabled()) { - log.debug(error, e); - } - throw new OAuthClientAuthnException("Error occurred while validating the JTI: " + jti + " of the " + - "assertion.", OAuth2ErrorCodes.INVALID_REQUEST, e); - } finally { - IdentityDatabaseUtil.closeAllConnections(connection, null, preparedStatement); - } - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/internal/JWTServiceComponent.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/internal/JWTServiceComponent.java deleted file mode 100644 index bd5f4c18..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/internal/JWTServiceComponent.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2016, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.osgi.framework.BundleContext; -import org.osgi.service.component.ComponentContext; -import org.osgi.service.component.annotations.Activate; -import org.osgi.service.component.annotations.Component; -import org.osgi.service.component.annotations.Reference; -import org.osgi.service.component.annotations.ReferenceCardinality; -import org.osgi.service.component.annotations.ReferencePolicy; -import org.wso2.carbon.identity.configuration.mgt.core.ConfigurationManager; -import org.wso2.carbon.identity.core.util.IdentityCoreInitializedEvent; -import org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthenticator; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.PrivateKeyJWTClientAuthenticator; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.JWTClientAuthenticatorMgtService; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.JWTClientAuthenticatorMgtServiceImpl; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.Util; -import org.wso2.carbon.user.core.service.RealmService; - -/** - * JwtService osgi Component.* - */ -@Component( - name = "org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt", - immediate = true -) -public class JWTServiceComponent { - - private static final Log log = LogFactory.getLog(JWTServiceComponent.class); - private BundleContext bundleContext; - - public static RealmService getRealmService() { - - return JWTServiceDataHolder.getInstance().getRealmService(); - } - - @Reference( - name = "user.realmservice.default", - service = RealmService.class, - cardinality = ReferenceCardinality.MANDATORY, - policy = ReferencePolicy.DYNAMIC, - unbind = "unsetRealmService" - ) - protected void setRealmService(RealmService realmService) { - - JWTServiceDataHolder.getInstance().setRealmService(realmService); - if (log.isDebugEnabled()) { - log.debug("RealmService is set in the custom token builder bundle."); - } - } - - @Activate - protected void activate(ComponentContext ctxt) { - - try { - PrivateKeyJWTClientAuthenticator privateKeyJWTClientAuthenticator = new PrivateKeyJWTClientAuthenticator(); - Util.checkIfTenantIdColumnIsAvailableInIdnOidcAuthTable(); - bundleContext = ctxt.getBundleContext(); - bundleContext.registerService(OAuthClientAuthenticator.class.getName(), privateKeyJWTClientAuthenticator, - null); - bundleContext.registerService(JWTClientAuthenticatorMgtService.class.getName(), - new JWTClientAuthenticatorMgtServiceImpl(), null); - if (log.isDebugEnabled()) { - log.debug("Private Key JWT client handler is activated"); - } - } catch (Throwable e) { - log.fatal("Error while activating the Private Key JWT client handler. ", e); - } - } - - protected void deactivate(ComponentContext ctxt) { - - if (log.isDebugEnabled()) { - log.debug("Private Key JWT client handler is deactivated."); - } - } - - protected void unsetRealmService(RealmService realmService) { - - JWTServiceDataHolder.getInstance().setRealmService(null); - if (log.isDebugEnabled()) { - log.debug("RealmService is unset in the custom token builder bundle."); - } - } - - protected void unsetIdentityCoreInitializedEventService(IdentityCoreInitializedEvent identityCoreInitializedEvent) { - /* reference IdentityCoreInitializedEvent service to guarantee that this component will wait until identity core - is started */ - if (log.isDebugEnabled()) { - log.debug("Unset Identity core Intialized Event Service."); - } - } - - @Reference( - name = "identityCoreInitializedEventService", - service = IdentityCoreInitializedEvent.class, - cardinality = ReferenceCardinality.MANDATORY, - policy = ReferencePolicy.DYNAMIC, - unbind = "unsetIdentityCoreInitializedEventService" - ) - protected void setIdentityCoreInitializedEventService(IdentityCoreInitializedEvent identityCoreInitializedEvent) { - /* reference IdentityCoreInitializedEvent service to guarantee that this component will wait until identity core - is started */ - if (log.isDebugEnabled()) { - log.debug("Set Identity core Intialized Event Service."); - } - } - - /** - * Set the ConfigurationManager. - * - * @param configurationManager The {@code ConfigurationManager} instance. - */ - @Reference( - name = "resource.configuration.manager", - service = ConfigurationManager.class, - cardinality = ReferenceCardinality.MANDATORY, - policy = ReferencePolicy.DYNAMIC, - unbind = "unregisterConfigurationManager" - ) - protected void registerConfigurationManager(ConfigurationManager configurationManager) { - - if (log.isDebugEnabled()) { - log.debug("Registering the ConfigurationManager in JWT Client Authenticator ManagementService."); - } - JWTServiceDataHolder.getInstance().setConfigurationManager(configurationManager); - } - - - /** - * Unset the ConfigurationManager. - * - * @param configurationManager The {@code ConfigurationManager} instance. - */ - protected void unregisterConfigurationManager(ConfigurationManager configurationManager) { - - if (log.isDebugEnabled()) { - log.debug("Unregistering the ConfigurationManager in JWT Client Authenticator ManagementService."); - } - JWTServiceDataHolder.getInstance().setConfigurationManager(null); - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/internal/JWTServiceDataHolder.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/internal/JWTServiceDataHolder.java deleted file mode 100644 index 577276d6..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/internal/JWTServiceDataHolder.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal; - -import org.wso2.carbon.identity.configuration.mgt.core.ConfigurationManager; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.JWTAuthenticationConfigurationDAO; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.impl.CacheBackedJWTConfigurationDAOImpl; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.impl.JWTAuthenticationConfigurationDAOImpl; -import org.wso2.carbon.user.core.service.RealmService; - -/** - * JWTServiceDataHolder data holder Class. - */ -public class JWTServiceDataHolder { - - private RealmService realmService = null; - public static JWTServiceDataHolder instance = new JWTServiceDataHolder(); - - public boolean preventTokenReuse = true; - private ConfigurationManager configurationManager; - - private JWTAuthenticationConfigurationDAO JWTAuthenticationConfigurationDAO = - new CacheBackedJWTConfigurationDAOImpl(new JWTAuthenticationConfigurationDAOImpl()); - - public ConfigurationManager getConfigurationManager() { - - return configurationManager; - } - - public void setConfigurationManager(ConfigurationManager configurationManager) { - - this.configurationManager = configurationManager; - } - - public boolean isPreventTokenReuse() { - - return preventTokenReuse; - } - - public void setPreventTokenReuse(boolean preventTokenReuse) { - - this.preventTokenReuse = preventTokenReuse; - } - - public static JWTServiceDataHolder getInstance() { - - return instance; - } - - public RealmService getRealmService() { - - return realmService; - } - - public void setRealmService(RealmService realmService) { - - this.realmService = realmService; - } - - public JWTAuthenticationConfigurationDAO getPrivateKeyJWTAuthenticationConfigurationDAO() { - - return JWTAuthenticationConfigurationDAO; - } - - public void setJWTAuthenticationConfigurationDAO - (JWTAuthenticationConfigurationDAO JWTAuthenticationConfigurationDAO) { - - this.JWTAuthenticationConfigurationDAO = JWTAuthenticationConfigurationDAO; - } - -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/util/Util.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/util/Util.java deleted file mode 100644 index b3053f39..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/util/Util.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util; - -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.SQLQueries; - -import java.util.HashMap; -import java.util.Map; - -import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils.isTableColumnExists; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.GET_JWT; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.GET_JWT_ID; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.GET_JWT_DETAILS; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.INSERT_JWD_ID; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.UPSERT_H2; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.UPSERT_MSSQL_DB2; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.UPSERT_MYSQL; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.UPSERT_ORACLE; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.UPSERT_POSTGRESQL; - - -/** - * Util method for jwt token handler component. - */ -public class Util { - - private static boolean isTenantIdColumnIsAvailableInIdnOidcAuthTable = false; - private static Map queries = new HashMap<>(); - - public static boolean isTenantIdColumnAvailableInIdnOidcAuth() { - - return isTenantIdColumnIsAvailableInIdnOidcAuthTable; - } - - public static String getDBQuery(String key) { - - return queries.get(key); - } - - /** - * Checking whether the tenant id column is available in the IDN_OIDC_JTI table. - */ - public static void checkIfTenantIdColumnIsAvailableInIdnOidcAuthTable() { - - isTenantIdColumnIsAvailableInIdnOidcAuthTable = isTableColumnExists(SQLQueries.IDN_OIDC_JTI, - SQLQueries.TENANT_ID); - buildQueryMapping(); - } - - private static void buildQueryMapping() { - - if (isTenantIdColumnIsAvailableInIdnOidcAuthTable) { - queries.put(GET_JWT_ID, SQLQueries.GET_TENANTED_JWT_ID); - queries.put(GET_JWT, SQLQueries.GET_TENANTED_JWT); - queries.put(GET_JWT_DETAILS, SQLQueries.GET_JWT_DETAIL); - queries.put(INSERT_JWD_ID, SQLQueries.INSERT_TENANTED_JWD_ID); - queries.put(UPSERT_MSSQL_DB2, SQLQueries.INSERT_OR_UPDATE_TENANTED_JWT_ID_MSSQL_OR_DB2); - queries.put(UPSERT_MYSQL, SQLQueries.INSERT_OR_UPDATE_TENANTED_JWT_ID_MYSQL); - queries.put(UPSERT_H2, SQLQueries.INSERT_OR_UPDATE_TENANTED_JWT_ID_H2); - queries.put(UPSERT_POSTGRESQL, SQLQueries.INSERT_OR_UPDATE_TENANTED_JWT_ID_POSTGRESQL); - queries.put(UPSERT_ORACLE, SQLQueries.INSERT_OR_UPDATE_TENANTED_JWT_ID_ORACLE); - } else { - queries.put(GET_JWT_ID, SQLQueries.GET_JWT_ID); - queries.put(GET_JWT, SQLQueries.GET_JWT); - queries.put(INSERT_JWD_ID, SQLQueries.INSERT_JWD_ID); - queries.put(UPSERT_MSSQL_DB2, SQLQueries.INSERT_OR_UPDATE_JWT_ID_MSSQL_OR_DB2); - queries.put(UPSERT_MYSQL, SQLQueries.INSERT_OR_UPDATE_JWT_ID_MYSQL); - queries.put(UPSERT_H2, SQLQueries.INSERT_OR_UPDATE_JWT_ID_H2); - queries.put(UPSERT_POSTGRESQL, SQLQueries.INSERT_OR_UPDATE_JWT_ID_POSTGRESQL); - queries.put(UPSERT_ORACLE, SQLQueries.INSERT_OR_UPDATE_JWT_ID_ORACLE); - } - } -} diff --git a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/validator/JWTValidator.java b/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/validator/JWTValidator.java deleted file mode 100644 index 4726b4f0..00000000 --- a/component/client-handler/src/main/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/validator/JWTValidator.java +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Copyright (c) 2017, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.validator; - -import com.nimbusds.jose.JOSEException; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jose.JWSVerifier; -import com.nimbusds.jose.crypto.RSASSAVerifier; -import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.SignedJWT; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.base.MultitenantConstants; -import org.wso2.carbon.core.util.KeyStoreManager; -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.ServiceProviderProperty; -import org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants; -import org.wso2.carbon.identity.application.common.util.IdentityApplicationManagementUtil; -import org.wso2.carbon.identity.core.ServiceURLBuilder; -import org.wso2.carbon.identity.core.URLBuilderException; -import org.wso2.carbon.identity.core.util.IdentityTenantUtil; -import org.wso2.carbon.identity.core.util.IdentityUtil; -import org.wso2.carbon.identity.oauth.common.OAuth2ErrorCodes; -import org.wso2.carbon.identity.oauth.common.exception.InvalidOAuthClientException; -import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; -import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; -import org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnException; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.cache.JWTCache; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.cache.JWTCacheEntry; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.cache.JWTCacheKey; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.exception.JWTClientAuthenticatorServiceServerException; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.dao.JWTEntry; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.dao.JWTStorageManager; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal.JWTServiceComponent; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal.JWTServiceDataHolder; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.Util; -import org.wso2.carbon.identity.oauth2.util.OAuth2Util; -import org.wso2.carbon.identity.oauth2.validators.jwt.JWKSBasedJWTValidator; -import org.wso2.carbon.idp.mgt.IdentityProviderManagementException; -import org.wso2.carbon.idp.mgt.IdentityProviderManager; -import org.wso2.carbon.user.api.UserStoreException; - -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.PublicKey; -import java.security.cert.X509Certificate; -import java.security.interfaces.RSAPublicKey; -import java.text.ParseException; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.apache.commons.lang.StringUtils.isEmpty; -import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OAuth20Endpoints.OAUTH2_TOKEN_EP_URL; -import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OAuth20Endpoints.OAUTH2_PAR_EP_URL; -import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OIDCConfigProperties.DEFAULT_VALUE_FOR_PREVENT_TOKEN_REUSE; - -/** - * This class is used to validate the JWT which is coming along with the request. - */ -public class JWTValidator { - - private static final Log log = LogFactory.getLog(JWTValidator.class); - public static final String FULLSTOP_DELIMITER = "."; - public static final String DASH_DELIMITER = "-"; - public static final String KEYSTORE_FILE_EXTENSION = ".jks"; - public static final String RS = "RS"; - public static final String PS = "PS"; - private static final String IDP_ENTITY_ID = "IdPEntityId"; - private static final String PROP_ID_TOKEN_ISSUER_ID = "OAuth.OpenIDConnect.IDTokenIssuerID"; - private static final String FAPI_SIGNATURE_ALG_CONFIGURATION = "OAuth.OpenIDConnect.FAPI." + - "AllowedSignatureAlgorithms.AllowedSignatureAlgorithm"; - private static final String MTLS_ALIASES_ENABLED = "OAuth.MutualTLSAliases.Enabled"; - private static final String MTLS_ALIASES_HOSTNAME = "OAuth.MutualTLSAliases.Hostname"; - private boolean preventTokenReuse; - private String validAudience; - private String validIssuer; - private int rejectBeforeInMinutes; - List mandatoryClaims; - private JWTCache jwtCache; - private boolean enableJTICache; - - private JWTStorageManager jwtStorageManager; - - public JWTValidator(boolean preventTokenReuse, String validAudience, int rejectBefore, String validIssuer, - List mandatoryClaims, boolean enableJTICache) { - - this.preventTokenReuse = preventTokenReuse; - this.validAudience = validAudience; - this.validIssuer = validIssuer; - this.jwtStorageManager = new JWTStorageManager(); - this.mandatoryClaims = mandatoryClaims; - this.rejectBeforeInMinutes = rejectBefore; - this.enableJTICache = enableJTICache; - this.jwtCache = JWTCache.getInstance(); - } - - /** - * To validate the JWT assertion. - * - * @param signedJWT Validate the token - * @param requestUrl The request URL. - * @return true if the jwt is valid. - * @throws OAuthClientAuthnException OAuthClientAuthnException thrown with Invalid Request error code. - */ - public boolean isValidAssertion(SignedJWT signedJWT, String requestUrl) throws OAuthClientAuthnException { - - String errorMessage; - - if (signedJWT == null) { - errorMessage = "No valid JWT assertion found for " + Constants.OAUTH_JWT_BEARER_GRANT_TYPE; - return logAndThrowException(errorMessage); - } - try { - JWTClaimsSet claimsSet = getClaimSet(signedJWT); - - if (claimsSet == null) { - errorMessage = "Claim set is missing in the JWT assertion"; - throw new OAuthClientAuthnException(errorMessage, OAuth2ErrorCodes.INVALID_REQUEST); - } - - String jwtIssuer = claimsSet.getIssuer(); - String jwtSubject = resolveSubject(claimsSet); - List audience = claimsSet.getAudience(); - Date expirationTime = claimsSet.getExpirationTime(); - String jti = claimsSet.getJWTID(); - Date nbf = claimsSet.getNotBeforeTime(); - Date issuedAtTime = claimsSet.getIssueTime(); - long currentTimeInMillis = System.currentTimeMillis(); - long timeStampSkewMillis = OAuthServerConfiguration.getInstance().getTimeStampSkewInSeconds() * 1000; - OAuthAppDO oAuthAppDO = getOAuthAppDO(jwtSubject); - String consumerKey = oAuthAppDO.getOauthConsumerKey(); - String tenantDomain = oAuthAppDO.getUser().getTenantDomain(); - int tenantId = JWTServiceComponent.getRealmService().getTenantManager().getTenantId(tenantDomain); - if (!validateMandatoryFeilds(mandatoryClaims, claimsSet)) { - return false; - } - - //Validate issuer and subject. - if (!validateIssuer(jwtIssuer, consumerKey) || !validateSubject(jwtSubject, consumerKey)) { - return false; - } - - /* A list of valid audiences (issuer identifier, token endpoint URL or pushed authorization request - endpoint URL) should be supported for PAR and not just a single valid audience. - https://datatracker.ietf.org/doc/html/rfc9126 */ - List acceptedAudienceList = getValidAudiences(tenantDomain, requestUrl); - - long expTime = 0; - long issuedTime = 0; - if (expirationTime != null) { - expTime = expirationTime.getTime(); - } - if (issuedAtTime != null) { - issuedTime = issuedAtTime.getTime(); - } - - // Obtain the signing algorithm used to sign the JWT in the request. - String requestSigningAlgorithm = signedJWT.getHeader().getAlgorithm().getName(); - if (!isValidSignatureAlgorithm(requestSigningAlgorithm, consumerKey)) { - throw new OAuthClientAuthnException("Signature algorithm used in the request is invalid.", - OAuth2ErrorCodes.INVALID_CLIENT); - } - - /* Check whether the request signing algorithm is an allowed algorithm as per the FAPI specification. - https://openid.net/specs/openid-financial-api-part-2-1_0.html#algorithm-considerations */ - try { - if (OAuth2Util.isFapiConformantApp(consumerKey)) { - // Mandating FAPI specified JWT signing algorithms. - List fapiAllowedSigningAlgorithms = IdentityUtil - .getPropertyAsList(FAPI_SIGNATURE_ALG_CONFIGURATION); - if (!fapiAllowedSigningAlgorithms.contains(requestSigningAlgorithm)) { - throw new OAuthClientAuthnException("FAPI unsupported signing algorithm " + requestSigningAlgorithm - + " is used to sign the JWT.", OAuth2ErrorCodes.INVALID_CLIENT); - } - } - } catch (InvalidOAuthClientException e) { - throw new OAuthClientAuthnException("Could not find an existing app for clientId: " + consumerKey, - OAuth2ErrorCodes.INVALID_CLIENT); - } catch (IdentityOAuth2Exception e) { - throw new OAuthClientAuthnException("Error while obtaining the service provider for client_id: " + - consumerKey, OAuth2ErrorCodes.SERVER_ERROR); - } - - if (oAuthAppDO.isTokenEndpointAllowReusePvtKeyJwt() != null) { - preventTokenReuse = !oAuthAppDO.isTokenEndpointAllowReusePvtKeyJwt(); - } - - //Validate signature validation, audience, nbf,exp time, jti. - if (!validateAudience(acceptedAudienceList, audience) - || !validateJWTWithExpTime(expirationTime, currentTimeInMillis, timeStampSkewMillis) - || !validateNotBeforeClaim(currentTimeInMillis, timeStampSkewMillis, nbf) - || !validateAgeOfTheToken(issuedAtTime, currentTimeInMillis, timeStampSkewMillis) - || !isValidSignature(consumerKey, signedJWT, tenantDomain, jwtSubject, tenantId) - || !validateJTI(signedJWT, jti, currentTimeInMillis, timeStampSkewMillis, expTime, - issuedTime, tenantId)) { - return false; - } - - return true; - - } catch (IdentityOAuth2Exception e) { - return logAndThrowException(e.getMessage(), e.getErrorCode()); - } catch (UserStoreException e) { - return logAndThrowException(e.getMessage()); - } - } - - /** - * To validate the JWT assertion. - * - * @param signedJWT Validate the token - * @return true if the jwt is valid. - * @throws OAuthClientAuthnException OAuthClientAuthnException thrown with Invalid Request error code. - */ - public boolean isValidAssertion(SignedJWT signedJWT) throws OAuthClientAuthnException { - - return isValidAssertion(signedJWT, null); - } - - private boolean validateMandatoryFeilds(List mandatoryClaims, JWTClaimsSet claimsSet) throws OAuthClientAuthnException { - - for (String mandatoryClaim : mandatoryClaims) { - if (claimsSet.getClaim(mandatoryClaim) == null) { - String errorMessage = "Mandatory field :" + mandatoryClaim + " is missing in the JWT assertion."; - return logAndThrowException(errorMessage); - } - } - return true; - } - - // "REQUIRED. sub. This MUST contain the client_id of the OAuth Client." - public boolean validateSubject(String jwtSubject, String consumerKey) throws OAuthClientAuthnException { - - String errorMessage = String.format("Invalid Subject '%s' is found in the JWT. It should be equal to the '%s'", - jwtSubject, consumerKey); - if (!jwtSubject.trim().equals(consumerKey)) { - if (log.isDebugEnabled()) { - log.debug(errorMessage); - } - throw new OAuthClientAuthnException("Invalid Subject: " + jwtSubject + " is found in the JWT", OAuth2ErrorCodes. - INVALID_REQUEST); - } - return true; - } - - // "REQUIRED. iss. This MUST contain the client_id of the OAuth Client." when a valid issuer is not specified in the - // jwtValidator. - private boolean validateIssuer(String issuer, String consumerKey) throws OAuthClientAuthnException { - - String errorMessage = String.format("Invalid issuer '%s' is found in the JWT. It should be equal to the '%s'" - , issuer, consumerKey); - String error = String.format("Invalid issuer '%s' is found in the JWT. ", issuer); - //check whether the issuer is client_id - if (isEmpty(validIssuer)) { - if (!issuer.trim().equals(consumerKey)) { - if (log.isDebugEnabled()) { - log.debug(errorMessage); - } - throw new OAuthClientAuthnException(error, OAuth2ErrorCodes.INVALID_REQUEST); - } - return true; - } else if (!validIssuer.equals(issuer)) { - if (log.isDebugEnabled()) { - log.debug(errorMessage); - } - throw new OAuthClientAuthnException(error, OAuth2ErrorCodes.INVALID_REQUEST); - } - return true; - } - - // The valid audience value should either be the issuer identifier or the token endpoint URL or the pushed authorization - // request endpoint URL - private boolean validateAudience(List expectedAudiences, List audience) throws OAuthClientAuthnException { - - for (String aud : audience) { - if (expectedAudiences.contains(aud)) { - return true; - } - } - if (log.isDebugEnabled()) { - log.debug("None of the audience values : " + audience + " matched the expected audiences : " + expectedAudiences); - } - throw new OAuthClientAuthnException("Failed to match audience values.", OAuth2ErrorCodes.INVALID_REQUEST); - } - - // "REQUIRED. JWT ID. A unique identifier for the token, which can be used to prevent reuse of the token. These tokens - // MUST only be used once, unless conditions for reuse were negotiated between the parties; any such negotiation is - // beyond the scope of this specification." - private boolean validateJTI(SignedJWT signedJWT, String jti, long currentTimeInMillis, - long timeStampSkewMillis, long expTime, long issuedTime, int tenantId) - throws OAuthClientAuthnException { - - if (enableJTICache) { - JWTCacheKey jwtCacheKey; - if (Util.isTenantIdColumnAvailableInIdnOidcAuth()) { - jwtCacheKey = new JWTCacheKey(jti, tenantId); - } else { - jwtCacheKey = new JWTCacheKey(jti); - } - JWTCacheEntry entry = jwtCache.getValueFromCache(jwtCacheKey); - if (!validateJTIInCache(jti, signedJWT, entry, currentTimeInMillis, timeStampSkewMillis, this.jwtCache, - tenantId)) { - return false; - } - } - // Check JWT ID in DB - if (!validateJWTInDataBase(jti, currentTimeInMillis, timeStampSkewMillis, tenantId)) { - return false; - } - persistJWTID(jti, expTime, issuedTime, tenantId); - return true; - } - - private boolean validateJWTInDataBase(String jti, long currentTimeInMillis, - long timeStampSkewMillis, int tenantId) throws OAuthClientAuthnException { - - JWTEntry jwtEntry = getJTIfromDB(jti, tenantId); - if (jwtEntry == null) { - if (log.isDebugEnabled()) { - log.debug("JWT id: " + jti + " not found in the Storage the JWT has been validated successfully."); - } - return true; - } else if (preventTokenReuse) { - String message = "JWT Token with JTI: " + jti + " has been replayed."; - return logAndThrowException(message); - } - // Token reuse is allowed. Here we are logging whether the token is reused within the allowed expiry time. - if (currentTimeInMillis + timeStampSkewMillis < jwtEntry.getExp()) { - if (log.isDebugEnabled()) { - log.debug("JWT Token with jti: " + jti + "has been reused with in the allowed expiry time: " + - jwtEntry.getExp()); - } - } - return true; - } - - /** - * This method is to get JTI from the DB. - * For the migration purposes (preserve existing behaviour), - * We are searching for the current tenant and default tenant. - * - * @param jti JTI. - * @param tenantId Tenant id. - * @return JWT entry if exists. - * @throws OAuthClientAuthnException OAuthClientAuthnException. - */ - private JWTEntry getJTIfromDB(String jti, final int tenantId) throws OAuthClientAuthnException { - - List jwtEntries = jwtStorageManager.getJwtsFromDB(jti, tenantId); - - if (jwtEntries.isEmpty()) { - return null; - } - // If there is only one entry return it. - if (jwtEntries.size() == 1) { - return jwtEntries.get(0); - } - return jwtEntries.stream().filter(e -> e.getTenantId() == tenantId).findFirst().orElse(null); - } - - private void persistJWTID(final String jti, long expiryTime, long issuedTime, int tenantId) - throws OAuthClientAuthnException { - - jwtStorageManager.persistJWTIdInDB(jti, tenantId, expiryTime, issuedTime, this.preventTokenReuse); - } - - private OAuthAppDO getOAuthAppDO(String jwtSubject) throws OAuthClientAuthnException { - - OAuthAppDO oAuthAppDO = null; - String message = String.format("Error while retrieving OAuth application with provided JWT information with " + - "subject '%s' ", jwtSubject); - try { - oAuthAppDO = OAuth2Util.getAppInformationByClientId(jwtSubject); - if (oAuthAppDO == null) { - logAndThrowException(message); - } - } catch (InvalidOAuthClientException | IdentityOAuth2Exception e) { - logAndThrowException(message); - } - return oAuthAppDO; - } - - private boolean logAndThrowException(String detailedMessage) throws OAuthClientAuthnException { - - return logAndThrowException(detailedMessage, OAuth2ErrorCodes.INVALID_REQUEST); - } - - private boolean logAndThrowException(String detailedMessage, String errorCode) throws OAuthClientAuthnException { - - if (log.isDebugEnabled()) { - log.debug(detailedMessage); - } - throw new OAuthClientAuthnException(detailedMessage, errorCode); - } - - private boolean validateJWTWithExpTime(Date expTime, long currentTimeInMillis, long timeStampSkewMillis) - throws OAuthClientAuthnException { - - long expirationTime = expTime.getTime(); - if (currentTimeInMillis + timeStampSkewMillis > expirationTime) { - String errorMessage = "JWT Token is expired. Expired Time: " + expTime; - if (log.isDebugEnabled()) { - log.debug(errorMessage); - } - throw new OAuthClientAuthnException(errorMessage, OAuth2ErrorCodes.INVALID_REQUEST); - } else { - return true; - } - } - - // "The JWT MAY contain an "nbf" (not before) claim that identifies - // the time before which the token MUST NOT be accepted for - // processing." - private boolean validateNotBeforeClaim(long currentTimeInMillis, long timeStampSkewMillis, Date nbf) throws OAuthClientAuthnException { - - if (nbf != null) { - - if (currentTimeInMillis + timeStampSkewMillis - nbf.getTime() <= 0) { - String message = "The token is used before the nbf claim value."; - if (log.isDebugEnabled()) { - log.debug(message); - } - throw new OAuthClientAuthnException(message, OAuth2ErrorCodes.INVALID_REQUEST); - } - } - return true; - } - - private boolean isValidSignature(String clientId, SignedJWT signedJWT, String tenantDomain, - String alias, int tenantId) throws OAuthClientAuthnException { - - X509Certificate cert = null; - String jwksUri = ""; - boolean isValidSignature = false; - try { - cert = (X509Certificate) OAuth2Util.getX509CertOfOAuthApp(clientId, tenantDomain); - } catch (IdentityOAuth2Exception e) { - if (log.isDebugEnabled()) { - String message = "Unable to retrieve the certificate for the service provider"; - log.debug(message, e); - } - } - // If cert is null check whether a jwks endpoint is configured for the service provider. - if (cert == null) { - try { - ServiceProviderProperty[] spProperties = OAuth2Util.getServiceProvider(clientId).getSpProperties(); - for (ServiceProviderProperty spProperty : spProperties) { - if (Constants.JWKS_URI.equals(spProperty.getName())) { - jwksUri = spProperty.getValue(); - break; - } - } - // Validate the signature of the assertion using the jwks end point. - if (StringUtils.isNotBlank(jwksUri)) { - if (log.isDebugEnabled()) { - String message = "Found jwks end point for service provider " + jwksUri; - log.debug(message); - } - String jwtString = signedJWT.getParsedString(); - String alg = signedJWT.getHeader().getAlgorithm().getName(); - Map options = new HashMap(); - isValidSignature = new JWKSBasedJWTValidator().validateSignature(jwtString, jwksUri, alg, options); - } - } catch (IdentityOAuth2Exception e) { - String errorMessage = "Error occurred while validating signature using jwks "; - log.error(errorMessage, e); - return false; - } - } - // If certificate is not configured in service provider, it will throw an error. - // For the existing clients need to handle that error and get from truststore. - if (StringUtils.isBlank(jwksUri) && cert == null) { - cert = getCertificate(tenantDomain, alias, tenantId); - } - if (StringUtils.isBlank(jwksUri) && cert != null) { - try { - isValidSignature = validateSignature(signedJWT, cert); - } catch (JOSEException e) { - String message = "Error while validating the signature"; - throw new OAuthClientAuthnException(message, OAuth2ErrorCodes.INVALID_REQUEST, e); - } - } - return isValidSignature; - } - - private List getValidAudiences(String tenantDomain, String requestUrl) throws OAuthClientAuthnException { - - List validAudiences = new ArrayList<>(); - String tokenEndpoint = null; - String parEndpoint = null; - IdentityProvider residentIdP; - try { - residentIdP = IdentityProviderManager.getInstance() - .getResidentIdP(tenantDomain); - FederatedAuthenticatorConfig oidcFedAuthn = IdentityApplicationManagementUtil - .getFederatedAuthenticator(residentIdP.getFederatedAuthenticatorConfigs(), - IdentityApplicationConstants.Authenticator.OIDC.NAME); - Property idpEntityId = IdentityApplicationManagementUtil.getProperty(oidcFedAuthn.getProperties(), - IDP_ENTITY_ID); - Property parEndpointFromResidentIdp = IdentityApplicationManagementUtil.getProperty(oidcFedAuthn - .getProperties(), Constants.OAUTH2_PAR_URL_REF); - if (idpEntityId != null) { - tokenEndpoint = idpEntityId.getValue(); - } - if (parEndpointFromResidentIdp != null) { - parEndpoint = parEndpointFromResidentIdp.getValue(); - } - } catch (IdentityProviderManagementException e) { - String message = "Error while loading OAuth2TokenEPUrl and ParEPUrl of the resident IDP of tenant: " - + tenantDomain; - if (log.isDebugEnabled()) { - log.debug(message); - } - throw new OAuthClientAuthnException(message, OAuth2ErrorCodes.INVALID_REQUEST); - } - - /* If the request is from the mTLS gateway, then the token and PAR endpoints should be set to the mTLS - endpoints.*/ - if (requestUrl != null && Boolean.parseBoolean(IdentityUtil.getProperty(MTLS_ALIASES_ENABLED)) && - requestUrl.contains(IdentityUtil.getProperty(MTLS_ALIASES_HOSTNAME))) { - String mtlsHostname = IdentityUtil.getProperty(MTLS_ALIASES_HOSTNAME); - try { - tokenEndpoint = ServiceURLBuilder.create().addPath(OAUTH2_TOKEN_EP_URL).build(mtlsHostname) - .getAbsolutePublicURL(); - parEndpoint = ServiceURLBuilder.create().addPath(OAUTH2_PAR_EP_URL).build(mtlsHostname) - .getAbsolutePublicURL(); - } catch (URLBuilderException e) { - String errorMsg = String.format("Error while building the absolute url of the context: '%s', for the" + - " tenant domain: '%s'", OAUTH2_TOKEN_EP_URL, tenantDomain); - throw new OAuthClientAuthnException(errorMsg, OAuth2ErrorCodes.INVALID_REQUEST, e); - } - } - - if (StringUtils.isEmpty(tokenEndpoint)) { - tokenEndpoint = IdentityUtil.getProperty(PROP_ID_TOKEN_ISSUER_ID); - } - if (StringUtils.isEmpty(parEndpoint)) { - parEndpoint = IdentityUtil.getProperty(Constants.OAUTH2_PAR_URL_CONFIG); - } - - if (StringUtils.isNotEmpty(validAudience)) { - validAudiences.add(validAudience); - } - validAudiences.add(tokenEndpoint); - validAudiences.add(parEndpoint); - return validAudiences; - } - - /** - * To retreive the processed JWT claimset. - * - * @param signedJWT signedJWT - * @return JWT claim set - * @throws OAuthClientAuthnException OAuthClientAuthnException thrown with Invalid Request error code. - */ - public JWTClaimsSet getClaimSet(SignedJWT signedJWT) throws OAuthClientAuthnException { - - JWTClaimsSet claimsSet; - String errorMessage; - if (signedJWT == null) { - errorMessage = "No Valid Assertion was found for " + Constants.OAUTH_JWT_BEARER_GRANT_TYPE; - throw new OAuthClientAuthnException(errorMessage, OAuth2ErrorCodes.INVALID_REQUEST); - } - try { - claimsSet = signedJWT.getJWTClaimsSet(); - if (claimsSet == null) { - errorMessage = "Claim values are empty in the given JSON Web Token."; - throw new OAuthClientAuthnException(errorMessage, OAuth2ErrorCodes.INVALID_REQUEST); - } - } catch (ParseException e) { - String errorMsg = "Error when trying to retrieve claimsSet from the JWT."; - if (log.isDebugEnabled()) { - log.debug(errorMsg); - } - throw new OAuthClientAuthnException(errorMsg, OAuth2ErrorCodes.INVALID_REQUEST); - } - return claimsSet; - } - - /** - * The default implementation which creates the subject from the 'sub' attribute. - * - * @param claimsSet all the JWT claims - * @return The subject, to be used - */ - public String resolveSubject(JWTClaimsSet claimsSet) { - - return claimsSet.getSubject(); - } - - private static X509Certificate getCertificate(String tenantDomain, String alias, int tenantId) - throws OAuthClientAuthnException { - - KeyStoreManager keyStoreManager; - // get an instance of the corresponding Key Store Manager instance - keyStoreManager = KeyStoreManager.getInstance(tenantId); - KeyStore keyStore; - try { - if (tenantId != MultitenantConstants.SUPER_TENANT_ID) {// for tenants, load key from their generated key store - keyStore = keyStoreManager.getKeyStore(generateKSNameFromDomainName(tenantDomain)); - } else { - // for super tenant, load the default pub. cert using the config. in carbon.xml - keyStore = keyStoreManager.getPrimaryKeyStore(); - } - return (X509Certificate) keyStore.getCertificate(alias); - - } catch (KeyStoreException e) { - String errorMsg = "Error instantiating an X509Certificate object for the certificate alias: " + alias + - " in tenant:" + tenantDomain; - if (log.isDebugEnabled()) { - log.debug(errorMsg); - } - throw new OAuthClientAuthnException(errorMsg, OAuth2ErrorCodes.INVALID_REQUEST); - } catch (Exception e) { - String message = "Unable to load key store manager for the tenant domain: " + tenantDomain; - //keyStoreManager throws Exception - if (log.isDebugEnabled()) { - log.debug(message); - } - throw new OAuthClientAuthnException(message, OAuth2ErrorCodes.INVALID_REQUEST); - } - } - - private static String generateKSNameFromDomainName(String tenantDomain) { - - String ksName = tenantDomain.trim().replace(FULLSTOP_DELIMITER, DASH_DELIMITER); - return ksName + KEYSTORE_FILE_EXTENSION; - } - - private boolean validateSignature(SignedJWT signedJWT, X509Certificate x509Certificate) - throws JOSEException, OAuthClientAuthnException { - - JWSVerifier verifier; - JWSHeader header = signedJWT.getHeader(); - if (x509Certificate == null) { - throw new OAuthClientAuthnException("Unable to locate certificate for JWT " + header.toString(), - OAuth2ErrorCodes.INVALID_REQUEST); - } - - String alg = signedJWT.getHeader().getAlgorithm().getName(); - if (isEmpty(alg)) { - throw new OAuthClientAuthnException("Signature validation failed. No algorithm is found in the JWT header.", - OAuth2ErrorCodes.INVALID_REQUEST); - } else { - if (log.isDebugEnabled()) { - log.debug("Signature Algorithm found in the JWT Header: " + alg); - } - if (alg.indexOf(RS) == 0 || alg.indexOf(PS) == 0) { - // At this point 'x509Certificate' will never be null. - PublicKey publicKey = x509Certificate.getPublicKey(); - if (publicKey instanceof RSAPublicKey) { - verifier = new RSASSAVerifier((RSAPublicKey) publicKey); - } else { - throw new OAuthClientAuthnException("Signature validation failed. Public key is not an RSA public key.", - OAuth2ErrorCodes.INVALID_REQUEST); - } - } else { - throw new OAuthClientAuthnException("Signature Algorithm not supported : " + alg, - OAuth2ErrorCodes.INVALID_REQUEST); - } - } - // At this point 'verifier' will never be null. - return signedJWT.verify(verifier); - } - - private boolean validateAgeOfTheToken(Date issuedAtTime, long currentTimeInMillis, long timeStampSkewMillis) throws - OAuthClientAuthnException { - - if (issuedAtTime == null) { - return true; - } - if (rejectBeforeInMinutes > 0) { - long issuedAtTimeMillis = issuedAtTime.getTime(); - long rejectBeforeMillis = 1000L * 60 * rejectBeforeInMinutes; - if (currentTimeInMillis + timeStampSkewMillis - issuedAtTimeMillis > - rejectBeforeMillis) { - String logMsg = getTokenTooOldMessage(currentTimeInMillis, timeStampSkewMillis, issuedAtTimeMillis, - rejectBeforeMillis); - if (log.isDebugEnabled()) { - log.debug(logMsg); - } - throw new OAuthClientAuthnException("The jwt is too old to use.", OAuth2ErrorCodes.INVALID_REQUEST); - } - } - return true; - } - - private String getTokenTooOldMessage(long currentTimeInMillis, long timeStampSkewMillis, long issuedAtTimeMillis, - long rejectBeforeMillis) { - - StringBuilder tmp = new StringBuilder(); - tmp.append("JSON Web Token is issued before the allowed time."); - tmp.append(" Issued At Time(ms) : "); - tmp.append(issuedAtTimeMillis); - tmp.append(", Reject before limit(ms) : "); - tmp.append(rejectBeforeMillis); - tmp.append(", TimeStamp Skew : "); - tmp.append(timeStampSkewMillis); - tmp.append(", Current Time : "); - tmp.append(currentTimeInMillis); - tmp.append(". JWT Rejected and validation terminated"); - return tmp.toString(); - } - - private boolean validateJTIInCache(String jti, SignedJWT signedJWT, JWTCacheEntry entry, long currentTimeInMillis, - long timeStampSkewMillis, JWTCache jwtCache, int tenantId) - throws OAuthClientAuthnException { - - if (entry == null) { - // Update the cache with the new JWT for the same JTI. - JWTCacheKey jwtCacheKey; - if (Util.isTenantIdColumnAvailableInIdnOidcAuth()) { - jwtCacheKey = new JWTCacheKey(jti, tenantId); - } else { - jwtCacheKey = new JWTCacheKey(jti); - } - jwtCache.addToCache(jwtCacheKey, new JWTCacheEntry(signedJWT)); - } else if (preventTokenReuse) { - throw new OAuthClientAuthnException("JWT Token with jti: " + jti + " has been replayed", - OAuth2ErrorCodes.INVALID_REQUEST); - } else { - try { - SignedJWT cachedJWT = entry.getJwt(); - long cachedJWTExpiryTimeMillis = cachedJWT.getJWTClaimsSet().getExpirationTime().getTime(); - // Token reuse is allowed. Here we are logging whether the token is reused within the allowed expiry time. - if (currentTimeInMillis + timeStampSkewMillis < cachedJWTExpiryTimeMillis) { - if (log.isDebugEnabled()) { - log.debug("JWT Token with jti: " + jti + "has been reused with in the allowed expiry time: " + - cachedJWTExpiryTimeMillis); - } - } - // Update the cache with the new JWT for the same JTI. - JWTCacheKey jwtCacheKey; - if (Util.isTenantIdColumnAvailableInIdnOidcAuth()) { - jwtCacheKey = new JWTCacheKey(jti, tenantId); - } else { - jwtCacheKey = new JWTCacheKey(jti); - } - jwtCache.addToCache(jwtCacheKey, new JWTCacheEntry(signedJWT)); - } catch (ParseException e) { - if (log.isDebugEnabled()) { - log.debug("Unable to parse the cached jwt assertion : " + entry.getEncodedJWt()); - } - throw new OAuthClientAuthnException("JTI validation failed.", OAuth2ErrorCodes.INVALID_REQUEST); - } - } - if (log.isDebugEnabled()) { - log.debug("JWT id: " + jti + " for tenant id: " + tenantId + " not found in the cache " + - "and the JWT has been validated successfully in cache."); - } - return true; - } - - /** - * Validate whether the request signing algorithm is configured for the application. - * - * @param requestSigningAlgorithm The request signed algorithm. - * @param clientId Client ID of the application. - * @return whether the request signing algorithm is configured for the application. - * @throws OAuthClientAuthnException OAuth Client Authentication Exception. - */ - private boolean isValidSignatureAlgorithm(String requestSigningAlgorithm, String clientId) - throws OAuthClientAuthnException { - - // Obtain the signing algorithm configured for the application. - List configuredSigningAlgorithms = getConfiguredSigningAlgorithm(clientId); - // Validate whether the JWT signing algorithm is configured for the application. - if (configuredSigningAlgorithms.isEmpty() || configuredSigningAlgorithms.contains(requestSigningAlgorithm)) { - return true; - } else { - if (log.isDebugEnabled()) { - log.debug("JWT signed algorithm: " + requestSigningAlgorithm + " does not match with the configured algorithms: " + - configuredSigningAlgorithms); - } - return false; - } - } - - /** - * Obtain the request signing algorithms configured for the application. - * - * @param clientId Client ID of the application. - * @throws OAuthClientAuthnException OAuth Client Authentication Exception. - */ - private List getConfiguredSigningAlgorithm(String clientId) throws OAuthClientAuthnException { - - List configuredSigningAlgorithms = new ArrayList<>(); - String tenantDomain = IdentityTenantUtil.resolveTenantDomain(); - try { - OAuthAppDO oAuthAppDO = OAuth2Util.getAppInformationByClientId(clientId, tenantDomain); - String tokenEndpointAuthSignatureAlgorithm = oAuthAppDO.getTokenEndpointAuthSignatureAlgorithm(); - if (StringUtils.isNotBlank(tokenEndpointAuthSignatureAlgorithm)) { - configuredSigningAlgorithms = Arrays.asList(tokenEndpointAuthSignatureAlgorithm); - } - } catch (IdentityOAuth2Exception | InvalidOAuthClientException e) { - throw new OAuthClientAuthnException("Error occurred while retrieving app information for client id: " + - clientId + " of tenantDomain: " + tenantDomain, OAuth2ErrorCodes.INVALID_REQUEST, e); - } - return configuredSigningAlgorithms; - } - -} diff --git a/component/client-handler/src/main/resources/jwt.properties b/component/client-handler/src/main/resources/jwt.properties deleted file mode 100644 index 63cfeaaf..00000000 --- a/component/client-handler/src/main/resources/jwt.properties +++ /dev/null @@ -1,5 +0,0 @@ -#Time period to reject the token which is issued before the allowed time. -JwtValidityPeriod=30 - -#Whether cache used to store the jWT -EnableCacheForJTI=false \ No newline at end of file diff --git a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/PrivateKeyJWTClientAuthenticatorTest.java b/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/PrivateKeyJWTClientAuthenticatorTest.java deleted file mode 100644 index 073c2bf1..00000000 --- a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/PrivateKeyJWTClientAuthenticatorTest.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt; - -import org.mockito.Mock; -import org.mockito.Mockito; -import org.powermock.reflect.internal.WhiteboxImpl; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.wso2.carbon.base.CarbonBaseConstants; -import org.wso2.carbon.context.PrivilegedCarbonContext; -import org.wso2.carbon.identity.base.IdentityConstants; -import org.wso2.carbon.identity.common.testng.WithAxisConfiguration; -import org.wso2.carbon.identity.common.testng.WithCarbonHome; -import org.wso2.carbon.identity.common.testng.WithH2Database; -import org.wso2.carbon.identity.common.testng.WithKeyStore; -import org.wso2.carbon.identity.common.testng.WithRealmService; -import org.wso2.carbon.identity.core.util.IdentityTenantUtil; -import org.wso2.carbon.identity.core.util.IdentityUtil; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; -import org.wso2.carbon.identity.oauth2.bean.OAuthClientAuthnContext; -import org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnException; -import org.wso2.carbon.identity.oauth2.model.ClientAuthenticationMethodModel; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.JWTAuthenticationConfigurationDAO; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.model.JWTClientAuthenticatorConfig; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal.JWTServiceComponent; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal.JWTServiceDataHolder; -import org.wso2.carbon.idp.mgt.internal.IdpMgtServiceComponentHolder; -import org.wso2.carbon.user.api.UserRealm; -import org.wso2.carbon.user.core.service.RealmService; - -import java.security.Key; -import java.security.KeyStore; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.servlet.http.HttpServletRequest; - -import static org.testng.Assert.assertEquals; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.OAUTH_JWT_ASSERTION; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.OAUTH_JWT_ASSERTION_TYPE; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.OAUTH_JWT_BEARER_GRANT_TYPE; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.JWTTestUtil.buildJWT; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.JWTTestUtil.getKeyStoreFromFile; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.validator.JWTValidatorTest.TEST_CLIENT_ID_1; -import static org.wso2.carbon.utils.multitenancy.MultitenantConstants.SUPER_TENANT_DOMAIN_NAME; -import static org.wso2.carbon.utils.multitenancy.MultitenantConstants.SUPER_TENANT_ID; - -@WithCarbonHome -@WithAxisConfiguration -@WithH2Database(jndiName = "jdbc/WSO2CarbonDB", files = {"dbscripts/identity.sql"}) -@WithRealmService(tenantId = SUPER_TENANT_ID, tenantDomain = SUPER_TENANT_DOMAIN_NAME, - injectToSingletons = {JWTServiceComponent.class}) -@WithKeyStore -public class PrivateKeyJWTClientAuthenticatorTest { - - PrivateKeyJWTClientAuthenticator privateKeyJWTClientAuthenticator; - HttpServletRequest httpServletRequest = Mockito.mock(HttpServletRequest.class); - - OAuthClientAuthnContext oAuthClientAuthnContext =new OAuthClientAuthnContext(); - - KeyStore clientKeyStore; - Key key1; - String audience; - - @BeforeClass - public void setUp() throws Exception { - - clientKeyStore = getKeyStoreFromFile("testkeystore.jks", "wso2carbon", - System.getProperty(CarbonBaseConstants.CARBON_HOME)); - key1 = clientKeyStore.getKey("wso2carbon", "wso2carbon".toCharArray()); - audience = IdentityUtil.getServerURL(IdentityConstants.OAuth.TOKEN, true, false); - privateKeyJWTClientAuthenticator = new PrivateKeyJWTClientAuthenticator(); - } - - @Test - public void testGetClientId() throws Exception { - - Map bodyContent = new HashMap<>(); - List assertion = new ArrayList<>(); - assertion.add(buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3000", audience, "RSA265", key1, 0)); - bodyContent.put(OAUTH_JWT_ASSERTION, assertion); - String clientId = privateKeyJWTClientAuthenticator.getClientId(httpServletRequest, bodyContent, - oAuthClientAuthnContext); - assertEquals(clientId, "KrVLov4Bl3natUksF2HmWsdw684a", "The expected client id is the jwt subject."); - - } - - @Test - public void testcanAuthenticate() throws IdentityOAuth2Exception { - - Map bodyContent = new HashMap<>(); - List assertion = new ArrayList<>(); - List assertionType = new ArrayList<>(); - assertion.add(buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3000", audience, "RSA265", key1, 0)); - assertionType.add(OAUTH_JWT_BEARER_GRANT_TYPE); - bodyContent.put(OAUTH_JWT_ASSERTION, assertion); - - bodyContent.put(OAUTH_JWT_ASSERTION_TYPE, assertionType); - boolean received = privateKeyJWTClientAuthenticator.canAuthenticate(httpServletRequest, bodyContent, - oAuthClientAuthnContext); - assertEquals(received, true, "A valid request refused to authenticate."); - } - - @Test - public void testPrivateKeyJWTFlagAdded() throws Exception { - - Map bodyContent = new HashMap<>(); - List assertionType = new ArrayList<>(); - assertionType.add(OAUTH_JWT_BEARER_GRANT_TYPE); - List assertion = new ArrayList<>(); - assertion.add(buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3000", audience, "RSA265", key1, 0)); - bodyContent.put(OAUTH_JWT_ASSERTION, assertion); - bodyContent.put(OAUTH_JWT_ASSERTION_TYPE, assertionType); - RealmService realmService = IdentityTenantUtil.getRealmService(); - UserRealm userRealm = realmService.getTenantUserRealm(SUPER_TENANT_ID); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setUserRealm(userRealm); - JWTServiceDataHolder.getInstance().setRealmService(realmService); - IdpMgtServiceComponentHolder.getInstance().setRealmService(realmService); - Map configuration = new HashMap<>(); - configuration.put("OAuth.OpenIDConnect.IDTokenIssuerID", "http://localhost:9443/oauth2/token"); - WhiteboxImpl.setInternalState(IdentityUtil.class, "configuration", configuration); - JWTClientAuthenticatorConfig jwtClientAuthenticatorConfig = new JWTClientAuthenticatorConfig(); - jwtClientAuthenticatorConfig.setEnableTokenReuse(true); - JWTAuthenticationConfigurationDAO mockDAO = Mockito.mock(JWTAuthenticationConfigurationDAO - .class); - Mockito.when(mockDAO.getPrivateKeyJWTClientAuthenticationConfigurationByTenantDomain(Mockito.anyString())) - .thenReturn(jwtClientAuthenticatorConfig); - JWTServiceDataHolder.getInstance() - .setJWTAuthenticationConfigurationDAO(mockDAO); - Mockito.when(httpServletRequest.getRequestURL()) - .thenReturn(new StringBuffer("http://localhost:9443/oauth2/token")); - - try { - privateKeyJWTClientAuthenticator.authenticateClient(httpServletRequest, bodyContent, - oAuthClientAuthnContext); - assertEquals(Constants.AUTHENTICATOR_TYPE_PK_JWT, oAuthClientAuthnContext.getParameter( - Constants.AUTHENTICATOR_TYPE_PARAM)); - } catch (OAuthClientAuthnException e) { - assertEquals(Constants.AUTHENTICATOR_TYPE_PK_JWT, oAuthClientAuthnContext.getParameter( - Constants.AUTHENTICATOR_TYPE_PARAM)); - } - } - - @Test - public void testGetSupportedClientAuthenticationMethods() { - - List supportedAuthMethods = new ArrayList<>(); - for (ClientAuthenticationMethodModel clientAuthenticationMethodModel : privateKeyJWTClientAuthenticator - .getSupportedClientAuthenticationMethods()) { - supportedAuthMethods.add(clientAuthenticationMethodModel.getName()); - } - Assert.assertTrue(supportedAuthMethods.contains("private_key_jwt")); - assertEquals(supportedAuthMethods.size(), 1); - } -} diff --git a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/cache/JWTCacheTest.java b/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/cache/JWTCacheTest.java deleted file mode 100644 index 68aaf27d..00000000 --- a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/cache/JWTCacheTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2017, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.cache; - -import com.nimbusds.jwt.SignedJWT; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.wso2.carbon.base.CarbonBaseConstants; -import org.wso2.carbon.identity.common.testng.WithCarbonHome; -import org.wso2.carbon.identity.common.testng.WithKeyStore; - -import java.security.Key; -import java.security.KeyStore; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.JWTTestUtil.buildJWT; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.JWTTestUtil.getKeyStoreFromFile; - -@WithCarbonHome -@WithKeyStore -public class JWTCacheTest { - - private JWTCache jwtCache; - private JWTCacheEntry cacheEntry; - private SignedJWT signedJWT; - private JWTCacheKey jwtCacheKey; - - @BeforeClass - public void setUp() throws Exception { - KeyStore clientKeyStore = getKeyStoreFromFile("testkeystore.jks", "wso2carbon", - System.getProperty(CarbonBaseConstants.CARBON_HOME)); - jwtCache = JWTCache.getInstance(); - Key key1 = clientKeyStore.getKey("wso2carbon", "wso2carbon".toCharArray()); - - String privateKeyJWT1 = buildJWT("some-issuer", "some-subject", "some-jti", "some-audience", "RSA265", key1, 0); - signedJWT = SignedJWT.parse(privateKeyJWT1); - cacheEntry = new JWTCacheEntry(signedJWT); - jwtCacheKey = new JWTCacheKey("some-key", -1234); - } - - @Test() - public void testAddToCache() throws Exception { - jwtCache.addToCache(jwtCacheKey, cacheEntry); - - } - - @Test(dependsOnMethods = {"testAddToCache"}) - public void testGetValueFromCache() throws Exception { - assertEquals(jwtCache.getValueFromCache(jwtCacheKey), cacheEntry); - } - - @Test(dependsOnMethods = {"testGetValueFromCache"}) - public void testClearCacheEntry() throws Exception { - jwtCache.clearCacheEntry(jwtCacheKey); - assertNull(jwtCache.getValueFromCache(jwtCacheKey)); - - } -} diff --git a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/JWTClientAuthenticatorMgtServiceTest.java b/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/JWTClientAuthenticatorMgtServiceTest.java deleted file mode 100644 index 1045dfe2..00000000 --- a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/JWTClientAuthenticatorMgtServiceTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core; - -import org.mockito.Mockito; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.wso2.carbon.identity.common.testng.WithCarbonHome; -import org.wso2.carbon.identity.common.testng.WithKeyStore; -import org.wso2.carbon.identity.configuration.mgt.core.ConfigurationManager; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.cache.JWTConfigCache; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.cache.JWTConfigCacheEntry; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.cache.JWTConfigCacheKey; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.impl.CacheBackedJWTConfigurationDAOImpl; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.impl.JWTAuthenticationConfigurationDAOImpl; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.model.JWTClientAuthenticatorConfig; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal.JWTServiceDataHolder; - -import static org.testng.AssertJUnit.assertFalse; -import static org.testng.AssertJUnit.assertNotNull; -import static org.testng.AssertJUnit.assertTrue; - -@WithCarbonHome -@WithKeyStore -public class JWTClientAuthenticatorMgtServiceTest { - - private JWTAuthenticationConfigurationDAOImpl jwtAuthenticationConfigurationDAO; - - private CacheBackedJWTConfigurationDAOImpl cacheBackedJWTConfigurationDAO; - - private ConfigurationManager mockConfigurationManager; - - private JWTClientAuthenticatorMgtService jwtClientAuthenticatorMgtService; - - - @BeforeClass - public void setUp() throws Exception { - - jwtAuthenticationConfigurationDAO = new JWTAuthenticationConfigurationDAOImpl(); - cacheBackedJWTConfigurationDAO = new CacheBackedJWTConfigurationDAOImpl(jwtAuthenticationConfigurationDAO); - JWTServiceDataHolder.getInstance().setJWTAuthenticationConfigurationDAO(cacheBackedJWTConfigurationDAO); - jwtClientAuthenticatorMgtService = new JWTClientAuthenticatorMgtServiceImpl(); - mockConfigurationManager = Mockito.mock(ConfigurationManager.class); - JWTServiceDataHolder.getInstance() - .setConfigurationManager(mockConfigurationManager); - } - - @Test() - private void testGetConfig() throws Exception { - - JWTConfigCacheKey jwtCacheKey = new JWTConfigCacheKey("sampleTenant"); - JWTClientAuthenticatorConfig jwtClientAuthenticatorConfig = new JWTClientAuthenticatorConfig(); - jwtClientAuthenticatorConfig.setEnableTokenReuse(true); - JWTConfigCacheEntry jwtConfigCacheEntry = new JWTConfigCacheEntry(jwtClientAuthenticatorConfig); - - JWTConfigCache.getInstance().addToCache(jwtCacheKey, jwtConfigCacheEntry); - JWTClientAuthenticatorConfig jwtClientAuthenticatorConfig1 = JWTServiceDataHolder - .getInstance().getPrivateKeyJWTAuthenticationConfigurationDAO() - .getPrivateKeyJWTClientAuthenticationConfigurationByTenantDomain("sampleTenant"); - - assertNotNull(jwtClientAuthenticatorConfig1); - assertFalse(jwtClientAuthenticatorConfig1.isEnableTokenReuse()); - } -} diff --git a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/constant/ErrorMessageTest.java b/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/constant/ErrorMessageTest.java deleted file mode 100644 index ba3790c4..00000000 --- a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/constant/ErrorMessageTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.constant; - -import org.testng.annotations.Test; - -import static org.testng.Assert.assertEquals; - -public class ErrorMessageTest { - - @Test() - public void testErrorMessageAttributes() { - - ErrorMessage errorMessage = ErrorMessage.ERROR_CODE_INVALID_TENANT_DOMAIN; - assertEquals(errorMessage.getCode(), "60004"); - assertEquals(errorMessage.getMessage(), "Invalid input."); - assertEquals(errorMessage.getDescription() , "%s is not a valid tenant domain."); - assertEquals(errorMessage.toString(),"60004:Invalid input."); - } -} diff --git a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/cache/JWTConfigCacheTest.java b/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/cache/JWTConfigCacheTest.java deleted file mode 100644 index 76ba1841..00000000 --- a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/dao/cache/JWTConfigCacheTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.dao.cache; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.wso2.carbon.identity.common.testng.WithCarbonHome; -import org.wso2.carbon.identity.common.testng.WithKeyStore; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.model.JWTClientAuthenticatorConfig; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; - -@WithCarbonHome -@WithKeyStore -public class JWTConfigCacheTest { - - private JWTConfigCache jwtConfigCache; - private JWTConfigCacheKey jwtCacheKey; - - private JWTConfigCacheEntry jwtConfigCacheEntry; - - @BeforeClass - public void setUp() throws Exception { - - jwtConfigCache = JWTConfigCache.getInstance(); - jwtCacheKey = new JWTConfigCacheKey("sampleTenant"); - JWTClientAuthenticatorConfig jwtClientAuthenticatorConfig = new JWTClientAuthenticatorConfig(); - jwtClientAuthenticatorConfig.setEnableTokenReuse(true); - jwtConfigCacheEntry = new JWTConfigCacheEntry(jwtClientAuthenticatorConfig); - } - - @Test() - public void testCache() throws Exception { - - assertNotNull(jwtConfigCache); - } - - @Test() - public void testAddToCache() throws Exception { - jwtConfigCache.addToCache(jwtCacheKey, jwtConfigCacheEntry); - - } - - @Test(dependsOnMethods = {"testAddToCache"}) - public void testGetValueFromCache() throws Exception { - assertEquals(jwtConfigCache.getValueFromCache(jwtCacheKey), jwtConfigCacheEntry); - } - - @Test(dependsOnMethods = {"testGetValueFromCache"}) - public void testClearCacheEntry() throws Exception { - jwtConfigCache.clearCacheEntry(jwtCacheKey); - assertNull(jwtConfigCache.getValueFromCache(jwtCacheKey)); - - } -} diff --git a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/util/UtilTest.java b/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/util/UtilTest.java deleted file mode 100644 index 56072d5e..00000000 --- a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/core/util/UtilTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.util; - -import org.apache.commons.lang.StringUtils; -import org.testng.annotations.Test; -import org.wso2.carbon.identity.configuration.mgt.core.model.Attribute; -import org.wso2.carbon.identity.configuration.mgt.core.model.Resource; -import org.wso2.carbon.identity.configuration.mgt.core.model.ResourceAdd; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.model.JWTClientAuthenticatorConfig; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal.JWTServiceDataHolder; - -import java.util.ArrayList; -import java.util.List; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertTrue; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.constant.Constants.ENABLE_TOKEN_REUSE; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.constant.Constants.JWT_CONFIGURATION_RESOURCE_NAME; - -public class UtilTest { - - @Test() - public void testServerConfig() throws Exception { - - JWTServiceDataHolder.getInstance().setPreventTokenReuse(true); - assertFalse(Util.getServerConfiguration().isEnableTokenReuse()); - } - - @Test() - public void testResource() throws Exception { - - Resource resourceAdd = new Resource(); - resourceAdd.setResourceName(JWT_CONFIGURATION_RESOURCE_NAME); - List attributes = new ArrayList<>(); - addAttribute(attributes, ENABLE_TOKEN_REUSE, - String.valueOf(true)); - resourceAdd.setAttributes(attributes); - resourceAdd.setHasAttribute(true); - - JWTClientAuthenticatorConfig jwtClientAuthenticatorConfig = Util.parseResource(resourceAdd); - assertNotNull(jwtClientAuthenticatorConfig); - assertTrue(jwtClientAuthenticatorConfig.isEnableTokenReuse()); - } - - private void addAttribute(List attributeList, String key, String value) { - - if (StringUtils.isNotBlank(value)) { - Attribute attribute = new Attribute(); - attribute.setKey(key); - attribute.setValue(value); - attributeList.add(attribute); - } - } - - @Test() - public void testConfig() throws Exception { - - JWTClientAuthenticatorConfig jwtClientAuthenticatorConfig = new JWTClientAuthenticatorConfig(); - jwtClientAuthenticatorConfig.setEnableTokenReuse(true); - ResourceAdd resourceAdd = Util.parseConfig(jwtClientAuthenticatorConfig); - assertEquals(resourceAdd.getAttributes().get(0).getKey(), ENABLE_TOKEN_REUSE); - assertTrue(Boolean.parseBoolean(resourceAdd.getAttributes().get(0).getValue())); - } -} diff --git a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/storage/JWTStorageManagerTest.java b/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/storage/JWTStorageManagerTest.java deleted file mode 100644 index 134b08e8..00000000 --- a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/storage/JWTStorageManagerTest.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2017, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.storage; - -import org.mockito.Mockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.testng.PowerMockTestCase; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; -import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils; -import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil; -import org.wso2.carbon.identity.core.util.IdentityUtil; -import org.wso2.carbon.identity.core.util.JdbcUtils; -import org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnException; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.dao.JWTEntry; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.dao.JWTStorageManager; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal.JWTServiceDataHolder; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.JWTTestUtil; - -import java.util.List; - -import static org.testng.Assert.assertEquals; -import java.sql.Connection; - -import static org.powermock.api.mockito.PowerMockito.mockStatic; -import static org.powermock.api.mockito.PowerMockito.when; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.JWTTestUtil.closeH2Base; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.JWTTestUtil.initiateH2Base; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.JWTTestUtil.spyConnection; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.Util.checkIfTenantIdColumnIsAvailableInIdnOidcAuthTable; - - -@PrepareForTest({IdentityUtil.class, JdbcUtils.class, IdentityDatabaseUtil.class, FrameworkUtils.class}) -public class JWTStorageManagerTest extends PowerMockTestCase { - - private JWTStorageManager JWTStorageManager; - private Connection spyConnection; - - - @BeforeClass - public void setUp() throws Exception { - - initiateH2Base(); - JWTStorageManager = new JWTStorageManager(); - } - - @BeforeMethod - public void init() throws Exception { - - mockStatic(IdentityDatabaseUtil.class); - spyConnection = spyConnection(JWTTestUtil.getConnection()); - Mockito.when(IdentityDatabaseUtil.getDBConnection()).thenReturn(spyConnection); - mockStatic(JdbcUtils.class); - mockStatic(FrameworkUtils.class); - Mockito.when(FrameworkUtils.isTableColumnExists(Constants.SQLQueries.IDN_OIDC_JTI, - Constants.SQLQueries.TENANT_ID)).thenReturn(true); - checkIfTenantIdColumnIsAvailableInIdnOidcAuthTable(); - - } - - @AfterClass - public void tearDown() throws Exception { - - closeH2Base(); - } - - @Test() - public void testIsJTIExistsInDB() throws Exception { - - assertFalse(JWTStorageManager.isJTIExistsInDB("2000")); - } - - @Test() - public void testPersistJWTIdInDB() throws Exception { - - JWTServiceDataHolder.getInstance().setPreventTokenReuse(true); - JWTStorageManager.persistJWTIdInDB("2023", -1234, 10000000, 10000000,true); - } - - @Test(expectedExceptions = OAuthClientAuthnException.class) - public void testPersistJWTIdInDBExceptionCase() throws Exception { - - JWTStorageManager.persistJWTIdInDB("2000", -1234, 10000000, 10000000, true); - } - - @Test - public void testDefaultPersistJWTIdInDB() throws Exception { - - JWTStorageManager.persistJWTIdInDB("2026", -1234, 10000000, 10000000); - } - - @Test() - public void testGetJwtsFromDB() throws Exception { - - List jwtEntryList = JWTStorageManager.getJwtsFromDB("10010010", 1); - assertNotNull(jwtEntryList); - JWTEntry jwtEntry = jwtEntryList.get(0); - assertEquals(1, jwtEntry.getTenantId()); - } - - @Test() - public void testPersistJWTIdInDBWithoutTokenReuse() throws Exception { - - JWTServiceDataHolder.getInstance().setPreventTokenReuse(false); - when(JdbcUtils.isH2DB()).thenReturn(true); - when(JdbcUtils.isOracleDB()).thenReturn(false); - // Insert a JTI entry with Expired Date. - JWTStorageManager.persistJWTIdInDB("2023", 12, 10000000, 10000000, false); - when(JdbcUtils.isH2DB()).thenReturn(true); - when(JdbcUtils.isOracleDB()).thenReturn(false); - // Update a JTI entry again. - JWTStorageManager.persistJWTIdInDB("2023", 12, 10001000, 10000100, false); - } - - @Test(dependsOnMethods = {"testPersistJWTIdInDBWithoutTokenReuse"}) - public void testUpdatedJTIEntry() throws Exception { - - JWTServiceDataHolder.getInstance().setPreventTokenReuse(false); - JWTEntry jwtEntry = JWTStorageManager.getJwtsFromDB("2023",12).get(0); - assertEquals(jwtEntry.getExp(), 10001000); - assertEquals(jwtEntry.getCreatedTime(), 10000100); - } -} diff --git a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/util/JWTTestUtil.java b/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/util/JWTTestUtil.java deleted file mode 100644 index 51998c1a..00000000 --- a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/util/JWTTestUtil.java +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util; - -import com.nimbusds.jose.JOSEException; -import com.nimbusds.jose.JWSAlgorithm; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jose.JWSSigner; -import com.nimbusds.jose.crypto.RSASSASigner; -import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.PlainJWT; -import com.nimbusds.jwt.SignedJWT; -import org.apache.commons.dbcp.BasicDataSource; -import org.apache.commons.lang.StringUtils; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.validator.JWTValidator; - -import java.io.FileInputStream; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.security.Key; -import java.security.KeyStore; -import java.security.interfaces.RSAPrivateKey; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.spy; -import static org.wso2.carbon.identity.oauth.common.OAuthConstants.OIDCConfigProperties.DEFAULT_VALUE_FOR_PREVENT_TOKEN_REUSE; - -public class JWTTestUtil { - - public static final String H2_SCRIPT_NAME = "identity.sql"; - private static final String DB_NAME = "Identity"; - public static Map dataSourceMap = new HashMap<>(); - - public static void initiateH2Base() throws Exception { - - BasicDataSource dataSource = new BasicDataSource(); - dataSource.setDriverClassName("org.h2.Driver"); - dataSource.setUsername("username"); - dataSource.setPassword("password"); - dataSource.setUrl("jdbc:h2:mem:test" + DB_NAME); - try (Connection connection = dataSource.getConnection()) { - connection.createStatement().executeUpdate("RUNSCRIPT FROM '" + getFilePath(H2_SCRIPT_NAME) + "'"); - } - dataSourceMap.put(DB_NAME, dataSource); - } - - public static String getFilePath(String fileName) { - - if (StringUtils.isNotBlank(fileName)) { - return Paths.get(System.getProperty("user.dir"), "src", "test", "resources", "dbscripts", - fileName).toString(); - } - throw new IllegalArgumentException("DB Script file name cannot be empty."); - } - - public static Connection getConnection() throws SQLException { - - if (dataSourceMap.get(DB_NAME) != null) { - return dataSourceMap.get(DB_NAME).getConnection(); - } - throw new RuntimeException("No data source initiated for database: " + DB_NAME); - } - - public static Connection spyConnection(Connection connection) throws SQLException { - - Connection spy = spy(connection); - doNothing().when(spy).close(); - return spy; - } - - public static void closeH2Base() throws Exception { - - BasicDataSource dataSource = dataSourceMap.get(DB_NAME); - if (dataSource != null) { - dataSource.close(); - } - } - public static String buildJWT(String issuer, String subject, String jti, String audience, String algorithm, - Key privateKey, long notBeforeMillis) - throws IdentityOAuth2Exception { - - long lifetimeInMillis = 3600 * 1000; - long curTimeInMillis = Calendar.getInstance().getTimeInMillis(); - - // Set claims to jwt token. - JWTClaimsSet.Builder jwtClaimsSetBuilder = new JWTClaimsSet.Builder(); - jwtClaimsSetBuilder.issuer(issuer); - jwtClaimsSetBuilder.subject(subject); - jwtClaimsSetBuilder.audience(Arrays.asList(audience)); - jwtClaimsSetBuilder.jwtID(jti); - jwtClaimsSetBuilder.expirationTime(new Date(curTimeInMillis + lifetimeInMillis)); - jwtClaimsSetBuilder.issueTime(new Date(curTimeInMillis)); - - if (notBeforeMillis > 0) { - jwtClaimsSetBuilder.notBeforeTime(new Date(curTimeInMillis + notBeforeMillis)); - } - JWTClaimsSet jwtClaimsSet = jwtClaimsSetBuilder.build(); - if (JWSAlgorithm.NONE.getName().equals(algorithm)) { - return new PlainJWT(jwtClaimsSet).serialize(); - } else if (JWSAlgorithm.RS512.getName().equals(algorithm)) { - return signJWTWithRSA512(jwtClaimsSet, privateKey); - } - - return signJWTWithRSA(jwtClaimsSet, privateKey); - } - - public static String buildJWT(String issuer, String subject, String jti, String audience, String algorythm, - Key privateKey, long notBeforeMillis, long lifetimeInMillis, long issuedTime) - throws IdentityOAuth2Exception { - - long curTimeInMillis = Calendar.getInstance().getTimeInMillis(); - if (issuedTime < 0) { - issuedTime = curTimeInMillis; - } - if (lifetimeInMillis <= 0) { - lifetimeInMillis = 3600 * 1000; - } - // Set claims to jwt token. - JWTClaimsSet.Builder jwtClaimsSetBuilder = new JWTClaimsSet.Builder(); - jwtClaimsSetBuilder.issuer(issuer); - jwtClaimsSetBuilder.subject(subject); - jwtClaimsSetBuilder.audience(Arrays.asList(audience)); - jwtClaimsSetBuilder.jwtID(jti); - jwtClaimsSetBuilder.expirationTime(new Date(issuedTime + lifetimeInMillis)); - jwtClaimsSetBuilder.issueTime(new Date(issuedTime)); - jwtClaimsSetBuilder.notBeforeTime(new Date(notBeforeMillis)); - - if (notBeforeMillis > 0) { - jwtClaimsSetBuilder.notBeforeTime(new Date(issuedTime + notBeforeMillis)); - } - JWTClaimsSet jwtClaimsSet = jwtClaimsSetBuilder.build(); - if (JWSAlgorithm.NONE.getName().equals(algorythm)) { - return new PlainJWT(jwtClaimsSet).serialize(); - } - - return signJWTWithRSA(jwtClaimsSet, privateKey); - } - - public static String buildExpiredJWT(String issuer, String subject, String jti, String audience, String algorythm, - Key privateKey, long notBeforeMillis, long lifetimeInMillis, long issuedTime) - throws IdentityOAuth2Exception { - - long curTimeInMillis = Calendar.getInstance().getTimeInMillis(); - if (issuedTime < 0) { - issuedTime = curTimeInMillis; - } - if (lifetimeInMillis <= 0) { - lifetimeInMillis = 3600 * 1000; - } - // Set claims to jwt token. - JWTClaimsSet.Builder jwtClaimsSetBuilder = new JWTClaimsSet.Builder(); - jwtClaimsSetBuilder.issuer(issuer); - jwtClaimsSetBuilder.subject(subject); - jwtClaimsSetBuilder.audience(Arrays.asList(audience)); - jwtClaimsSetBuilder.jwtID(jti); - jwtClaimsSetBuilder.expirationTime(new Date(issuedTime - lifetimeInMillis)); - jwtClaimsSetBuilder.issueTime(new Date(issuedTime)); - jwtClaimsSetBuilder.notBeforeTime(new Date(notBeforeMillis)); - - if (notBeforeMillis > 0) { - jwtClaimsSetBuilder.notBeforeTime(new Date(issuedTime + notBeforeMillis)); - } - JWTClaimsSet jwtClaimsSet = jwtClaimsSetBuilder.build(); - if (JWSAlgorithm.NONE.getName().equals(algorythm)) { - return new PlainJWT(jwtClaimsSet).serialize(); - } - - return signJWTWithRSA(jwtClaimsSet, privateKey); - } - - /** - * sign JWT token from RSA algorithm - * - * @param jwtClaimsSet contains JWT body - * @param privateKey - * @return signed JWT token - * @throws IdentityOAuth2Exception - */ - public static String signJWTWithRSA(JWTClaimsSet jwtClaimsSet, Key privateKey) - throws IdentityOAuth2Exception { - - try { - JWSSigner signer = new RSASSASigner((RSAPrivateKey) privateKey); - SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256), jwtClaimsSet); - signedJWT.sign(signer); - return signedJWT.serialize(); - } catch (JOSEException e) { - throw new IdentityOAuth2Exception("Error occurred while signing JWT", e); - } - } - - /** - * Sign JWT using the RS512 algorithm. - * - * @param jwtClaimsSet Set of claims to be included in the JWT. - * @param privateKey Private key used to sign the JWT. - * @return Signed JWT value. - * @throws IdentityOAuth2Exception An exception is thrown if an error occurs while signing the JWT. - */ - public static String signJWTWithRSA512(JWTClaimsSet jwtClaimsSet, Key privateKey) - throws IdentityOAuth2Exception { - - try { - JWSSigner signer = new RSASSASigner((RSAPrivateKey) privateKey); - SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS512), jwtClaimsSet); - signedJWT.sign(signer); - return signedJWT.serialize(); - } catch (JOSEException e) { - throw new IdentityOAuth2Exception("Error occurred while signing JWT.", e); - } - } - - /** - * Read Keystore from the file identified by given keystorename, password - * - * @param keystoreName - * @param password - * @param home - * @return - * @throws Exception - */ - public static KeyStore getKeyStoreFromFile(String keystoreName, String password, - String home) throws Exception { - - Path tenantKeystorePath = Paths.get(home, "repository", - "resources", "security", keystoreName); - FileInputStream file = new FileInputStream(tenantKeystorePath.toString()); - KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); - keystore.load(file, password.toCharArray()); - return keystore; - } - - /** - * Create and return a JWTValidator instance with given properties - * - * @param properties - * @return - */ - public static JWTValidator getJWTValidator(Properties properties) { - - int rejectBeforePeriod; - boolean cacheUsedJTI = true; - String validAudience = null; - String validIssuer = null; - boolean preventTokenReuse = DEFAULT_VALUE_FOR_PREVENT_TOKEN_REUSE; - List mandatoryClaims = new ArrayList<>(); - try { - - String rejectBeforePeriodConfigVal = properties.getProperty(Constants.REJECT_BEFORE_IN_MINUTES); - if (StringUtils.isNotEmpty(rejectBeforePeriodConfigVal)) { - rejectBeforePeriod = Integer.parseInt(rejectBeforePeriodConfigVal); - } else { - rejectBeforePeriod = Constants.DEFAULT_VALIDITY_PERIOD_IN_MINUTES; - } - - String cacheUsedJTIConfigVal = properties.getProperty("EnableCacheForJTI"); - if (StringUtils.isNotEmpty(cacheUsedJTIConfigVal)) { - cacheUsedJTI = Boolean.parseBoolean(cacheUsedJTIConfigVal); - } else { - cacheUsedJTI = Constants.DEFAULT_ENABLE_JTI_CACHE; - } - - String validAudienceConfigVal = properties.getProperty("ValidAudience"); - if (StringUtils.isNotEmpty(validAudienceConfigVal)) { - validAudience = validAudienceConfigVal; - } else { - validAudience = null; - } - - String validIssuerConfigVal = properties.getProperty("ValidIssuer"); - if (StringUtils.isNotEmpty(validIssuerConfigVal)) { - validIssuer = validIssuerConfigVal; - } else { - validIssuer = null; - } - - String preventTokenReuseProperty = properties.getProperty("PreventTokenReuse"); - if (StringUtils.isNotEmpty(preventTokenReuseProperty)) { - preventTokenReuse = Boolean.parseBoolean(preventTokenReuseProperty); - } - - String mandatory = properties.getProperty("mandatory"); - if (StringUtils.isNotEmpty(mandatory)) { - mandatoryClaims.add(mandatory); - } - - } catch (NumberFormatException e) { - rejectBeforePeriod = Constants.DEFAULT_VALIDITY_PERIOD_IN_MINUTES; - } - - return new JWTValidator(preventTokenReuse, validAudience, rejectBeforePeriod, validIssuer, mandatoryClaims - , cacheUsedJTI); - } -} diff --git a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/validator/JWTValidatorTest.java b/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/validator/JWTValidatorTest.java deleted file mode 100644 index 0c5a00d8..00000000 --- a/component/client-handler/src/test/java/org/wso2/carbon/identity/oauth2/token/handler/clientauth/jwt/validator/JWTValidatorTest.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (c) 2017, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.validator; - -import com.nimbusds.jwt.SignedJWT; -import org.apache.commons.codec.binary.Base64; -import org.mockito.Mockito; -import org.powermock.reflect.internal.WhiteboxImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import org.wso2.carbon.base.CarbonBaseConstants; -import org.wso2.carbon.context.PrivilegedCarbonContext; -import org.wso2.carbon.core.util.KeyStoreManager; -import org.wso2.carbon.identity.application.common.model.ServiceProvider; -import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; -import org.wso2.carbon.identity.common.testng.WithAxisConfiguration; -import org.wso2.carbon.identity.common.testng.WithCarbonHome; -import org.wso2.carbon.identity.common.testng.WithH2Database; -import org.wso2.carbon.identity.common.testng.WithKeyStore; -import org.wso2.carbon.identity.common.testng.WithRealmService; -import org.wso2.carbon.identity.core.util.IdentityTenantUtil; -import org.wso2.carbon.identity.core.util.IdentityUtil; -import org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnException; -import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal.JWTServiceComponent; -import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.internal.JWTServiceDataHolder; -import org.wso2.carbon.identity.testutil.ReadCertStoreSampleUtil; -import org.wso2.carbon.idp.mgt.internal.IdpMgtServiceComponentHolder; -import org.wso2.carbon.user.api.UserRealm; -import org.wso2.carbon.user.core.service.RealmService; - -import java.io.ByteArrayInputStream; -import java.security.Key; -import java.security.KeyStore; -import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; - -import static org.mockito.Matchers.anyString; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.Constants.REJECT_BEFORE_IN_MINUTES; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.JWTTestUtil.buildJWT; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.JWTTestUtil.getJWTValidator; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.JWTTestUtil.getKeyStoreFromFile; -import static org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.util.Util.checkIfTenantIdColumnIsAvailableInIdnOidcAuthTable; -import static org.wso2.carbon.utils.multitenancy.MultitenantConstants.SUPER_TENANT_DOMAIN_NAME; -import static org.wso2.carbon.utils.multitenancy.MultitenantConstants.SUPER_TENANT_ID; - -@WithCarbonHome -@WithAxisConfiguration -@WithH2Database(jndiName = "jdbc/WSO2CarbonDB", files = {"dbscripts/identity.sql"}, dbName = "testdb2") -@WithRealmService(tenantId = SUPER_TENANT_ID, tenantDomain = SUPER_TENANT_DOMAIN_NAME, - injectToSingletons = {JWTServiceComponent.class}) -@WithKeyStore -public class JWTValidatorTest { - - public static final String TEST_CLIENT_ID_1 = "KrVLov4Bl3natUksF2HmWsdw684a"; - public static final String TEST_FAPI_CLIENT_ID_1 = "KrVLov4Bl3natUksF2HmWsdw684b"; - public static final String TEST_FAPI_CLIENT_ID_2 = "KrVLov4Bl3natUksF2HmWsdw684c"; - public static final String TEST_SECRET_1 = "testSecret1"; - public static final String VALID_ISSUER_VAL = "valid-issuer"; - public static final String VALID_ISSUER = "ValidIssuer"; - public static final String VALID_AUDIENCE = "ValidAudience"; - public static final String SOME_VALID_AUDIENCE = "some-valid-audience"; - public static final String PREVENT_TOKEN_REUSE = "PreventTokenReuse"; - public static final String JWT_VALIDITY_PERIOD = "JwtValidityPeriod"; - public static final String ENABLE_CACHE_FOR_JTI = "EnableCacheForJTI"; - public static final String MANDATORY = "mandatory"; - public static final String ID_TOKEN_ISSUER_ID = "http://localhost:9443/oauth2/token"; - public static final String PAR_ENDPOINT = "https://localhost:9443/oauth2/par"; - private KeyStore clientKeyStore; - private KeyStore serverKeyStore; - private X509Certificate cert; - - private static final String CERTIFICATE = - "MIIDVzCCAj+gAwIBAgIEN+6m4zANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQGEwJGUjEMMAoGA1UE\n" + - "CBMDTVBMMQwwCgYDVQQHEwNNUEwxDTALBgNVBAoTBHRlc3QxDTALBgNVBAsTBHRlc3QxEzARBgNV\n" + - "BAMMCioudGVzdC5jb20wHhcNMTcxMTIzMTI1MDEyWhcNNDcxMTE2MTI1MDEyWjBcMQswCQYDVQQG\n" + - "EwJGUjEMMAoGA1UECBMDTVBMMQwwCgYDVQQHEwNNUEwxDTALBgNVBAoTBHRlc3QxDTALBgNVBAsT\n" + - "BHRlc3QxEzARBgNVBAMMCioudGVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\n" + - "AQCITPQCt3fPuVWCLFBnPfslWAIrh8H/sEx+I/mCscfAGMzBr/aKgtSr+6fcCvJgpj31D9Lp5ZY+\n" + - "WbpccxeLDDaV4hwAx8P1yi+0xwip8x5UIzjRcJ+n5E/9rjev3QnbynaFzgieyE784BfvO/4fgVTQ\n" + - "hAE4ZGdqbm1nD0Ic1qptOs7WCXMyjBy5JvqOD74HD7vSOwC4ySFVTOC8ENyF9i9gtx25+zH2FreJ\n" + - "gHkmLoiEUJMoCZ+ShH0tl8LoFVM5CTxWb6iNj28bYqgLAjVkOSO1G2GbOV8XzdaIj1m5ECksdQqf\n" + - "770UDjrGNM5VmzxMDDEKjB6/qhs6q4HeCZuzicbhAgMBAAGjITAfMB0GA1UdDgQWBBTiJxYPvJcZ\n" + - "3XlcnaZVFpOFbfj5ujANBgkqhkiG9w0BAQsFAAOCAQEAfbtzvY81vgNz5M1MwG78KdOEiSwNU6/y\n" + - "RqWBUsa5aB7w6vFdsgZ1D/J2v5VnVwXHrmWHCiIkXk70kD0gFJhDa4gNPsuAs0acMcZumEzjY8P2\n" + - "0s4LP5TOfCHraPMElFWmHwZI4/SaR5xGgzRxehqJ+KP6UKHWkhf/NP+SBetVAdXfNFp/hO+67XFe\n" + - "aFr3vXKegooXrm58vCvg/J1nJapbhWiTDvgeNF5EhnLDNs04oBsOcjzrGDihv4F+Vl1yx/RelAwv\n" + - "W/bQM+jWUllR4Qpwx6R1mVy3pFRl0+4npUr17XOGEoP9Xm/5kMvsiNOTqryR5p3xEPBQcXBJES8K\n" + - "oQon6A=="; - - @BeforeClass - public void setUp() throws Exception { - - Map publicCerts = new ConcurrentHashMap<>(); - publicCerts.put(SUPER_TENANT_ID, ReadCertStoreSampleUtil.createKeyStore(getClass()) - .getCertificate("wso2carbon")); - clientKeyStore = getKeyStoreFromFile("testkeystore.jks", "wso2carbon", - System.getProperty(CarbonBaseConstants.CARBON_HOME)); - serverKeyStore = getKeyStoreFromFile("wso2carbon.jks", "wso2carbon", - System.getProperty(CarbonBaseConstants.CARBON_HOME)); - - KeyStoreManager keyStoreManager = Mockito.mock(KeyStoreManager.class); - ConcurrentHashMap mtKeyStoreManagers = new ConcurrentHashMap(); - mtKeyStoreManagers.put(String.valueOf(SUPER_TENANT_ID), keyStoreManager); - WhiteboxImpl.setInternalState(KeyStoreManager.class, "mtKeyStoreManagers", mtKeyStoreManagers); - cert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate( - new ByteArrayInputStream(Base64.decodeBase64(CERTIFICATE))); - Mockito.when(keyStoreManager.getDefaultPrimaryCertificate()).thenReturn(cert); - Mockito.when(keyStoreManager.getPrimaryKeyStore()).thenReturn(serverKeyStore); - Mockito.when(keyStoreManager.getKeyStore("wso2carbon.jks")).thenReturn(serverKeyStore); - - RealmService realmService = IdentityTenantUtil.getRealmService(); - UserRealm userRealm = realmService.getTenantUserRealm(SUPER_TENANT_ID); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setUserRealm(userRealm); - JWTServiceDataHolder.getInstance().setRealmService(realmService); - IdpMgtServiceComponentHolder.getInstance().setRealmService(realmService); - - Map configuration = new HashMap<>(); - configuration.put("OAuth.OpenIDConnect.IDTokenIssuerID", ID_TOKEN_ISSUER_ID); - configuration.put(Constants.OAUTH2_PAR_URL_CONFIG, PAR_ENDPOINT); - // Assuming that the FAPI allowed signature algorithms are the below algorithms. - configuration.put("OAuth.OpenIDConnect.FAPI.AllowedSignatureAlgorithms.AllowedSignatureAlgorithm", - Arrays.asList("PS256", "ES256", "RS512")); - configuration.put("OAuth.MutualTLSAliases.Enabled", "false"); - WhiteboxImpl.setInternalState(IdentityUtil.class, "configuration", configuration); - } - - @DataProvider(name = "provideJWT") - public Object[][] createJWT() throws Exception { - - Properties properties1 = new Properties(); - Properties properties2 = new Properties(); - Properties properties3 = new Properties(); - Properties properties4 = new Properties(); - Properties properties5 = new Properties(); - Properties properties6 = new Properties(); - Properties properties7 = new Properties(); - Properties properties8 = new Properties(); - Properties properties9 = new Properties(); - - properties1.setProperty(ENABLE_CACHE_FOR_JTI, "true"); - properties1.setProperty(JWT_VALIDITY_PERIOD, "30"); - properties2.setProperty(VALID_ISSUER, VALID_ISSUER_VAL); - properties4.setProperty(VALID_AUDIENCE, SOME_VALID_AUDIENCE); - properties6.setProperty(ENABLE_CACHE_FOR_JTI, "false"); - properties6.setProperty(REJECT_BEFORE_IN_MINUTES, "1"); - properties7.setProperty(MANDATORY, "some_claim"); - properties8.setProperty(VALID_ISSUER, "some_issuer"); - properties9.setProperty(ENABLE_CACHE_FOR_JTI, "false"); - properties9.setProperty(REJECT_BEFORE_IN_MINUTES, "1"); - - - Key key1 = clientKeyStore.getKey("wso2carbon", "wso2carbon".toCharArray()); - String audience = ID_TOKEN_ISSUER_ID; - String jsonWebToken0 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3000", audience, "RSA265", key1, 0); - String jsonWebToken1 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3001", audience, "RSA265", key1, 0); - String jsonWebToken2 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3002", audience, "RSA265", key1, - 6000000); - String jsonWebToken3 = buildJWT("some-issuer", TEST_CLIENT_ID_1, "3003", audience, "RSA265", key1, - 6000000); - String jsonWebToken4 = buildJWT(TEST_CLIENT_ID_1, "some-client-id", "3004", audience, "RSA265", key1, 0); - String jsonWebToken5 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3005", audience, "RSA265", key1, 0); - String jsonWebToken6 = buildJWT(VALID_ISSUER_VAL, TEST_CLIENT_ID_1, "3006", audience, "RSA265", key1, 0); - String jsonWebToken7 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3006", audience, "RSA265", key1, 0); - String jsonWebToken9 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3009", audience, "RSA265", key1, - Calendar.getInstance().getTimeInMillis()); - String jsonWebToken10 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3010", SOME_VALID_AUDIENCE, - "RSA265", key1, 0); - String jsonWebToken11 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3011", audience, "RSA265", key1, - 0, 0, Calendar.getInstance().getTimeInMillis() - (1000L * 60 * 2 * - Constants.DEFAULT_VALIDITY_PERIOD_IN_MINUTES)); - - String jsonWebToken12 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3012", audience, "RSA265", key1, 0); - String jsonWebToken13 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3012", audience, "RSA265", key1, 0); - String jsonWebToken15 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3015", audience, "RSA265", key1, - 600000000); - - String jsonWebToken16 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3016", "some_audience", - "RSA265", key1, 0); - String jsonWebToken17 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3017", audience, "RSA265", key1, 0); - String jsonWebToken18 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3018", audience, "RSA265", key1, 0); - String jsonWebToken19 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3019", audience, "RSA265", key1, 0); - String jsonWebToken21 = buildJWT(TEST_FAPI_CLIENT_ID_1, TEST_FAPI_CLIENT_ID_1, "3021", audience, "RS512", key1, 0); - String jsonWebToken22 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3022", audience, "RSA265", key1, 0); - String jsonWebToken23 = buildJWT(TEST_CLIENT_ID_1, TEST_CLIENT_ID_1, "3023", PAR_ENDPOINT, "RSA265", key1, 0); - // String jsonWebToken24 = buildJWT(TEST_FAPI_CLIENT_ID_2, TEST_FAPI_CLIENT_ID_2, "3024", audience, "RSA265", key1, 0); - - return new Object[][]{ - {jsonWebToken0, properties8, false, "Correct authentication request is failed."}, - {jsonWebToken1, properties1, true, "Correct authentication request is failed."}, - {jsonWebToken2, properties1, false, "The JWT is used before the nbf claim value should fail."}, - {jsonWebToken3, properties3, false, "JWT with Invalid field Issuer must be fail."}, - {jsonWebToken4, properties3, false, "Request with non existing SP client-id should fail."}, - {jsonWebToken5, properties5, true, "JWT not-expired is not failed"}, - {jsonWebToken6, properties2, true, "Valid JWT token with custom issuer validation should pass."}, - {jsonWebToken7, properties3, false, "JWT persisted in database with preventTokenReuse " + - "enabled is not failed."}, - {jsonWebToken9, properties1, false, "The token is used before the nbf claim value should fail."}, - {jsonWebToken10, properties4, true, "Valid JWT token with custom audience validation should pass."}, - {jsonWebToken11, properties1, false, ""}, - {jsonWebToken12, properties5, true, ""}, - {jsonWebToken12, properties5, false, "Reuse of same JWT when preventTokenReuse is enabled should fail."}, - {jsonWebToken13, properties1, false, "Reuse of same JTI when preventTokenReuse is enabled should fail."}, - {jsonWebToken15, properties1, false, ""}, - {jsonWebToken16, properties4, false, ""}, - {jsonWebToken17, properties6, false, ""}, - {jsonWebToken18, properties7, false, ""}, - {jsonWebToken19, properties1, true, "Unable to use same JTI across tenants."}, - {jsonWebToken23, properties1, true, "JWT with valid audience from the accepted value list should pass."}, - {jsonWebToken22, properties1, true, "JWT with registered signing algorithm should pass."}, - {jsonWebToken22, properties1, false, "JWT with unregistered signing algorithm should fail."}, - /* When using PS256 it causes unit test issues unless BouncyCastleProviderSingleton is being used. Therefore - the unit tests were written assuming that RS512 is a FAPI allowed signing algorithm because that issue - only exists when running unit tests and what we really need to check is the logic within the methods. */ - {jsonWebToken21, properties1, true, "JWT with registered signing algorithm and FAPI compliant signing " + - "algorithm should pass."}, - {jsonWebToken21, properties1, true, "JWT with preventTokenReuse disabled should pass."}, - // Todo: Re-onboard the test case by adding changes to the FAPI property configs. - // {jsonWebToken24, properties1, false, "JWT with registered signing algorithm and FAPI non-compliant " + - // "signing algorithm should fail."} - }; - } - - @Test(dataProvider = "provideJWT") - public void testValidateToken(String jwt, Object properties, boolean expected, String errorMsg) throws Exception { - - ServiceProvider mockedServiceProvider = Mockito.mock(ServiceProvider.class); - Mockito.when(mockedServiceProvider.getCertificateContent()).thenReturn(CERTIFICATE); - ApplicationManagementService mockedApplicationManagementService = Mockito.mock(ApplicationManagementService - .class); - Mockito.when(mockedApplicationManagementService.getServiceProviderByClientId(anyString(), anyString(), - anyString())).thenReturn(mockedServiceProvider); - OAuth2ServiceComponentHolder.setApplicationMgtService(mockedApplicationManagementService); - try { - checkIfTenantIdColumnIsAvailableInIdnOidcAuthTable(); - JWTValidator jwtValidator = getJWTValidator((Properties) properties); - SignedJWT signedJWT = SignedJWT.parse(jwt); - assertEquals(jwtValidator.isValidAssertion(signedJWT), - expected, errorMsg); - if (((Properties) properties).getProperty(MANDATORY) != null) { - assertEquals(jwtValidator.isValidAssertion(null), - expected, errorMsg); - } - - } catch (OAuthClientAuthnException e) { - assertFalse(expected, errorMsg); - } - } - - @Test - public void testValidateNullToken() throws Exception { - - try { - JWTValidator jwtValidator = getJWTValidator(new Properties()); - jwtValidator.isValidAssertion(null); - } catch (OAuthClientAuthnException e) { - assertFalse(false, "Validation should fail when token is null"); - } - - } - - @Test(dependsOnMethods = "testValidateToken") - public void testValidateTokenSignedByHmac() throws Exception { - - JWTValidator jwtValidator = getJWTValidator(new Properties()); - String hsSignedJWT = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" + - ".eyJzdWIiOiJLclZMb3Y0QmwzbmF0VWtzRjJIbVdzZHc2ODRhIiwibmFtZSI6IkpvaG4gRG9lIiwiaXNzdWVyIjoiS3JWTG92NEJsM2" + - "5hdFVrc0YySG1Xc2R3Njg0YSIsImp0aSI6MTAwOCwiZXhwIjoiMjU1NDQ0MDEzMjAwMCIsImF1ZCI6WyJzb21lLWF1ZGllbmNlIl19." + - "m0RrVUrZHr1M7R4I_4dzpoWD8jNA2fKkOadEsFg9Wj4"; - SignedJWT signedJWT = SignedJWT.parse(hsSignedJWT); - } -} diff --git a/component/client-handler/src/test/resources/dbscripts/identity.sql b/component/client-handler/src/test/resources/dbscripts/identity.sql deleted file mode 100644 index a7070448..00000000 --- a/component/client-handler/src/test/resources/dbscripts/identity.sql +++ /dev/null @@ -1,207 +0,0 @@ -CREATE TABLE IF NOT EXISTS IDN_BASE_TABLE ( - PRODUCT_NAME VARCHAR (20), - PRIMARY KEY (PRODUCT_NAME) -); - -INSERT INTO IDN_BASE_TABLE values ('WSO2 Identity Server'); - -CREATE TABLE IF NOT EXISTS IDN_OAUTH_CONSUMER_APPS ( - ID INTEGER NOT NULL AUTO_INCREMENT, - CONSUMER_KEY VARCHAR(255), - CONSUMER_SECRET VARCHAR(2048), - USERNAME VARCHAR(255), - TENANT_ID INTEGER DEFAULT 0, - USER_DOMAIN VARCHAR(50), - APP_NAME VARCHAR(255), - OAUTH_VERSION VARCHAR(128), - CALLBACK_URL VARCHAR(1024), - GRANT_TYPES VARCHAR (1024), - PKCE_MANDATORY CHAR(1) DEFAULT '0', - PKCE_SUPPORT_PLAIN CHAR(1) DEFAULT '0', - APP_STATE VARCHAR (25) DEFAULT 'ACTIVE', - USER_ACCESS_TOKEN_EXPIRE_TIME BIGINT DEFAULT 3600, - APP_ACCESS_TOKEN_EXPIRE_TIME BIGINT DEFAULT 3600, - REFRESH_TOKEN_EXPIRE_TIME BIGINT DEFAULT 84600, - ID_TOKEN_EXPIRE_TIME BIGINT DEFAULT 3600, - CONSTRAINT CONSUMER_KEY_CONSTRAINT UNIQUE (CONSUMER_KEY), - PRIMARY KEY (ID) -); - -CREATE TABLE IF NOT EXISTS IDN_OPENID_USER_RPS ( - USER_NAME VARCHAR(255) NOT NULL, - TENANT_ID INTEGER DEFAULT 0, - RP_URL VARCHAR(255) NOT NULL, - TRUSTED_ALWAYS VARCHAR(128) DEFAULT 'FALSE', - LAST_VISIT DATE NOT NULL, - VISIT_COUNT INTEGER DEFAULT 0, - DEFAULT_PROFILE_NAME VARCHAR(255) DEFAULT 'DEFAULT', - PRIMARY KEY (USER_NAME, TENANT_ID, RP_URL) -); - -CREATE TABLE IF NOT EXISTS IDP ( - ID INTEGER AUTO_INCREMENT, - TENANT_ID INTEGER, - NAME VARCHAR(254) NOT NULL, - IS_ENABLED CHAR(1) NOT NULL DEFAULT '1', - IS_PRIMARY CHAR(1) NOT NULL DEFAULT '0', - HOME_REALM_ID VARCHAR(254), - IMAGE MEDIUMBLOB, - CERTIFICATE BLOB, - ALIAS VARCHAR(254), - INBOUND_PROV_ENABLED CHAR(1) NOT NULL DEFAULT '0', - INBOUND_PROV_USER_STORE_ID VARCHAR(254), - USER_CLAIM_URI VARCHAR(254), - ROLE_CLAIM_URI VARCHAR(254), - DESCRIPTION VARCHAR(1024), - DEFAULT_AUTHENTICATOR_NAME VARCHAR(254), - DEFAULT_PRO_CONNECTOR_NAME VARCHAR(254), - PROVISIONING_ROLE VARCHAR(128), - IS_FEDERATION_HUB CHAR(1) NOT NULL DEFAULT '0', - IS_LOCAL_CLAIM_DIALECT CHAR(1) NOT NULL DEFAULT '0', - DISPLAY_NAME VARCHAR(255), - IMAGE_URL VARCHAR(1024), - UUID CHAR(36) NOT NULL, - PRIMARY KEY (ID), - UNIQUE (TENANT_ID, NAME), - UNIQUE (UUID) -); - -CREATE TABLE IF NOT EXISTS IDP_AUTHENTICATOR ( - ID INTEGER AUTO_INCREMENT, - TENANT_ID INTEGER, - IDP_ID INTEGER, - NAME VARCHAR(255) NOT NULL, - IS_ENABLED CHAR (1) DEFAULT '1', - DISPLAY_NAME VARCHAR(255), - PRIMARY KEY (ID), - UNIQUE (TENANT_ID, IDP_ID, NAME), - FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); - -CREATE TABLE IF NOT EXISTS IDP_AUTHENTICATOR_PROPERTY ( - ID INTEGER AUTO_INCREMENT, - TENANT_ID INTEGER, - AUTHENTICATOR_ID INTEGER, - PROPERTY_KEY VARCHAR(255) NOT NULL, - PROPERTY_VALUE VARCHAR(2047), - IS_SECRET CHAR (1) DEFAULT '0', - PRIMARY KEY (ID), - UNIQUE (TENANT_ID, AUTHENTICATOR_ID, PROPERTY_KEY), - FOREIGN KEY (AUTHENTICATOR_ID) REFERENCES IDP_AUTHENTICATOR(ID) ON DELETE CASCADE); - -CREATE TABLE IF NOT EXISTS IDP_CLAIM ( - ID INTEGER AUTO_INCREMENT, - IDP_ID INTEGER, - TENANT_ID INTEGER, - CLAIM VARCHAR(254), - PRIMARY KEY (ID), - UNIQUE (IDP_ID, CLAIM), - FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); - -CREATE TABLE IF NOT EXISTS IDP_CLAIM_MAPPING ( - ID INTEGER AUTO_INCREMENT, - IDP_CLAIM_ID INTEGER, - TENANT_ID INTEGER, - LOCAL_CLAIM VARCHAR(253), - DEFAULT_VALUE VARCHAR(255), - IS_REQUESTED VARCHAR(128) DEFAULT '0', - PRIMARY KEY (ID), - UNIQUE (IDP_CLAIM_ID, TENANT_ID, LOCAL_CLAIM), - FOREIGN KEY (IDP_CLAIM_ID) REFERENCES IDP_CLAIM(ID) ON DELETE CASCADE); - -CREATE TABLE IF NOT EXISTS IDP_PROVISIONING_CONFIG ( - ID INTEGER AUTO_INCREMENT, - TENANT_ID INTEGER, - IDP_ID INTEGER, - PROVISIONING_CONNECTOR_TYPE VARCHAR(255) NOT NULL, - IS_ENABLED CHAR (1) DEFAULT '0', - IS_BLOCKING CHAR (1) DEFAULT '0', - IS_RULES_ENABLED CHAR (1) DEFAULT '0', - PRIMARY KEY (ID), - UNIQUE (TENANT_ID, IDP_ID, PROVISIONING_CONNECTOR_TYPE), - FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); - -CREATE TABLE IF NOT EXISTS IDP_ROLE ( - ID INTEGER AUTO_INCREMENT, - IDP_ID INTEGER, - TENANT_ID INTEGER, - ROLE VARCHAR(254), - PRIMARY KEY (ID), - UNIQUE (IDP_ID, ROLE), - FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); - -CREATE TABLE IF NOT EXISTS IDP_ROLE_MAPPING ( - ID INTEGER AUTO_INCREMENT, - IDP_ROLE_ID INTEGER, - TENANT_ID INTEGER, - USER_STORE_ID VARCHAR (253), - LOCAL_ROLE VARCHAR(253), - PRIMARY KEY (ID), - UNIQUE (IDP_ROLE_ID, TENANT_ID, USER_STORE_ID, LOCAL_ROLE), - FOREIGN KEY (IDP_ROLE_ID) REFERENCES IDP_ROLE(ID) ON DELETE CASCADE); - -CREATE TABLE IF NOT EXISTS IDP_METADATA ( - ID INTEGER AUTO_INCREMENT, - IDP_ID INTEGER, - NAME VARCHAR(255) NOT NULL, - `VALUE` VARCHAR(255) NOT NULL, - DISPLAY_NAME VARCHAR(255), - TENANT_ID INTEGER DEFAULT -1, - PRIMARY KEY (ID), - CONSTRAINT IDP_METADATA_CONSTRAINT UNIQUE (IDP_ID, NAME), - FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); - -INSERT INTO IDP (TENANT_ID, NAME, CERTIFICATE, UUID) VALUES (-1234, 'LOCAL', '4d4949434e544343415a3667417749424167494553333433676a414e42676b71686b69473977304241515546414442564d517377435159445651514745774a56557a454c4d416b47413155454341774351304578466a415542674e564241634d445531766457353059576c7549465a705a5863784454414c42674e5642416f4d42466454547a4978456a415142674e5642414d4d43577876593246736147397a64444165467730784d4441794d546b774e7a41794d6a5a614677307a4e5441794d544d774e7a41794d6a5a614d465578437a414a42674e5642415954416c56544d517377435159445651514944414a44515445574d425147413155454277774e54573931626e526861573467566d6c6c647a454e4d417347413155454367774556314e504d6a45534d424147413155454177774a6247396a5957786f62334e304d4947664d413047435371475349623344514542415155414134474e4144434269514b4267514355702f6f5631765763382f546b5153694176546f75734d7a4f4d3461734232696c747232514b6f7a6e6935615646753831384d704f4c5a4972384c4d6e547a576c6c4a76766141355241416470624543622b3438466a6242653068736555644e35487077766e482f4457385a636347766b353349364f727137684c4376315a4874754f436f6b67687a2f415472687950712b516b744d66586e52533448724b474a547a7861436355374f514944415141426f7849774544414f42674e56485138424166384542414d43425041774451594a4b6f5a496876634e4151454642514144675945415735775052376372314c4164712b497252343469516c5247354954435a5859396849305079674c50327248414e682b505966546d7862754f6e796b4e4779684d36466a464c625732755a48515459316a4d725070726a4f726d794b35736a4a524f34643144654748542f596e496a73394a6f67524b763458484543774c744956644162496457484574565a4a794d536b7463797973466376756850514b3851632f452f577138754853436f3d', '5de2f2d2-674f-4e5b-a1ef-de1ebcb5c1d5'); -INSERT INTO IDP_AUTHENTICATOR (TENANT_ID, IDP_ID, NAME) VALUES (-1234, 1, 'authenticator_name'); - -INSERT INTO IDP_AUTHENTICATOR_PROPERTY (TENANT_ID, AUTHENTICATOR_ID, PROPERTY_KEY, PROPERTY_VALUE) VALUES - (-1234, 1, 'IdPEntityId', 'LOCAL'); - -CREATE TABLE IF NOT EXISTS IDN_OIDC_JTI (JWT_ID VARCHAR(255), TENANT_ID INTEGER, EXP_TIME TIMESTAMP DEFAULT 0, -TIME_CREATED TIMESTAMP DEFAULT 0, PRIMARY KEY (JWT_ID, TENANT_ID)); - -INSERT INTO IDN_OIDC_JTI (JWT_ID,TENANT_ID,EXP_TIME,TIME_CREATED)VALUES ('2000', -1234, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO IDN_OIDC_JTI (JWT_ID,TENANT_ID,EXP_TIME,TIME_CREATED)VALUES ('2001', -1234, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO IDN_OIDC_JTI (JWT_ID,TENANT_ID,EXP_TIME,TIME_CREATED)VALUES ('2002', -1234, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO IDN_OIDC_JTI (JWT_ID,TENANT_ID,EXP_TIME,TIME_CREATED)VALUES ('10010010', 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); - - -INSERT INTO IDN_OAUTH_CONSUMER_APPS (ID, CONSUMER_KEY, CONSUMER_SECRET, USERNAME, TENANT_ID, USER_DOMAIN, APP_NAME, - OAUTH_VERSION, CALLBACK_URL, GRANT_TYPES, APP_STATE) VALUES - (2, 'KrVLov4Bl3natUksF2HmWsdw684a', 'testSecret1', 'testUser', -1234, 'PRIMARY', - 'myApp', 'OAuth-2.0', 'http://localhost:8080/redirect', - 'refresh_token password iwa:ntlm client_credentials', 'ACTIVE'); -INSERT INTO IDN_OAUTH_CONSUMER_APPS (ID, CONSUMER_KEY, CONSUMER_SECRET, USERNAME, TENANT_ID, USER_DOMAIN, APP_NAME, - OAUTH_VERSION, CALLBACK_URL, GRANT_TYPES, APP_STATE) VALUES - (3, 'KrVLov4Bl3natUksF2HmWsdw684b', 'testSecret1', 'testUser', -1234, 'PRIMARY', - 'myApp', 'OAuth-2.0', 'http://localhost:8080/redirect', - 'refresh_token password iwa:ntlm client_credentials', 'ACTIVE'); -INSERT INTO IDN_OAUTH_CONSUMER_APPS (ID, CONSUMER_KEY, CONSUMER_SECRET, USERNAME, TENANT_ID, USER_DOMAIN, APP_NAME, - OAUTH_VERSION, CALLBACK_URL, GRANT_TYPES, APP_STATE) VALUES - (4, 'KrVLov4Bl3natUksF2HmWsdw684c', 'testSecret1', 'testUser', -1234, 'PRIMARY', - 'myApp', 'OAuth-2.0', 'http://localhost:8080/redirect', - 'refresh_token password iwa:ntlm client_credentials', 'ACTIVE'); - -CREATE TABLE IF NOT EXISTS IDN_OIDC_PROPERTY ( - ID INTEGER NOT NULL AUTO_INCREMENT, - TENANT_ID INTEGER, - CONSUMER_KEY VARCHAR(255) , - PROPERTY_KEY VARCHAR(255) NOT NULL, - PROPERTY_VALUE VARCHAR(2047) , - PRIMARY KEY (ID), - FOREIGN KEY (CONSUMER_KEY) REFERENCES IDN_OAUTH_CONSUMER_APPS(CONSUMER_KEY) ON DELETE CASCADE); - -CREATE TABLE IF NOT EXISTS IDN_OAUTH2_SCOPE_VALIDATORS ( - APP_ID INTEGER NOT NULL, - SCOPE_VALIDATOR VARCHAR (128) NOT NULL, - PRIMARY KEY (APP_ID,SCOPE_VALIDATOR), - FOREIGN KEY (APP_ID) REFERENCES IDN_OAUTH_CONSUMER_APPS(ID) ON DELETE CASCADE); - -INSERT INTO IDN_OIDC_PROPERTY (TENANT_ID,CONSUMER_KEY,PROPERTY_KEY,PROPERTY_VALUE) VALUES (-1234, 'KrVLov4Bl3natUksF2HmWsdw684a', 'tokenEndpointAuthSigningAlg', 'RS256'); -INSERT INTO IDN_OIDC_PROPERTY (TENANT_ID,CONSUMER_KEY,PROPERTY_KEY,PROPERTY_VALUE) VALUES (-1234, 'KrVLov4Bl3natUksF2HmWsdw684a', 'isFAPIConformant', 'false'); -INSERT INTO IDN_OIDC_PROPERTY (TENANT_ID,CONSUMER_KEY,PROPERTY_KEY,PROPERTY_VALUE) VALUES (-1234, 'KrVLov4Bl3natUksF2HmWsdw684a', 'tokenEndpointAllowReusePvtKeyJwt', 'false'); -INSERT INTO IDN_OIDC_PROPERTY (TENANT_ID,CONSUMER_KEY,PROPERTY_KEY,PROPERTY_VALUE) VALUES (-1234, 'KrVLov4Bl3natUksF2HmWsdw684b', 'tokenEndpointAuthSigningAlg', 'RS512'); -INSERT INTO IDN_OIDC_PROPERTY (TENANT_ID,CONSUMER_KEY,PROPERTY_KEY,PROPERTY_VALUE) VALUES (-1234, 'KrVLov4Bl3natUksF2HmWsdw684b', 'isFAPIConformant', 'true'); -INSERT INTO IDN_OIDC_PROPERTY (TENANT_ID,CONSUMER_KEY,PROPERTY_KEY,PROPERTY_VALUE) VALUES (-1234, 'KrVLov4Bl3natUksF2HmWsdw684b', 'tokenEndpointAllowReusePvtKeyJwt', 'true'); -INSERT INTO IDN_OIDC_PROPERTY (TENANT_ID,CONSUMER_KEY,PROPERTY_KEY,PROPERTY_VALUE) VALUES (-1234, 'KrVLov4Bl3natUksF2HmWsdw684c', 'tokenEndpointAuthSigningAlg', 'RS256'); -INSERT INTO IDN_OIDC_PROPERTY (TENANT_ID,CONSUMER_KEY,PROPERTY_KEY,PROPERTY_VALUE) VALUES (-1234, 'KrVLov4Bl3natUksF2HmWsdw684c', 'isFAPIConformant', 'true'); -INSERT INTO IDN_OIDC_PROPERTY (TENANT_ID,CONSUMER_KEY,PROPERTY_KEY,PROPERTY_VALUE) VALUES (-1234, 'KrVLov4Bl3natUksF2HmWsdw684c', 'tokenEndpointAllowReusePvtKeyJwt', 'false'); diff --git a/component/client-handler/src/test/resources/repository/conf/axis2/axis2.xml b/component/client-handler/src/test/resources/repository/conf/axis2/axis2.xml deleted file mode 100644 index 27ef5741..00000000 --- a/component/client-handler/src/test/resources/repository/conf/axis2/axis2.xml +++ /dev/null @@ -1,725 +0,0 @@ - - - - - - - - - - - - - true - true - optional - true - work/mtom - 4000 - - ${childfirstCL} - - - true - - - true - - - - false - - inmemory - - - - - - - services - - - axis2services - - - axis2modules - - - WSO2 Identity Server-5.3.0 - - - WSO2 Identity Server-5.3.0 - - - - - - - false - - - - - - false - - - true - - - - ./repository/deployment/server/synapse-configs - - - - . - - - . - - - WSO2 Carbon Server - - - - - - - ${jaxwsparam} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 9763 - - - - - - - - - - - - 9443 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HTTP/1.1 - chunked - - true - - - HTTP/1.1 - chunked - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - multicast - - - - - wso2.carbon.domain - - - - - - 45564 - - 100 - - 60 - - - - - - 127.0.0.1 - - - - - - 4000 - - - - - - - - - - - - - - - - - - 127.0.0.1 - 4000 - - - - - - - - - diff --git a/component/client-handler/src/test/resources/repository/conf/carbon.xml b/component/client-handler/src/test/resources/repository/conf/carbon.xml deleted file mode 100644 index 142295ce..00000000 --- a/component/client-handler/src/test/resources/repository/conf/carbon.xml +++ /dev/null @@ -1,684 +0,0 @@ - - - - - - - - WSO2 Identity Server - - - IS - - - 5.3.0 - - - localhost - - - localhost - - - local:/${carbon.context}/services/ - - - - - - - IdentityServer - - - - - - - org.wso2.carbon - - - / - - - - - - - - - 15 - - - - - - - - - 0 - - - - - 9999 - - 11111 - - - - - - 10389 - - 8000 - - - - - - 10500 - - - - - - - - - org.wso2.carbon.tomcat.jndi.CarbonJavaURLContextFactory - - - - - - - - - java - - - - - - - - - - false - - - false - - - 600 - - - - false - - - - - - - - 30 - - - - - - - - - 15 - - - - - - ${carbon.home}/repository/deployment/server/ - - - 15 - - - ${carbon.home}/repository/conf/axis2/axis2.xml - - - 30000 - - - ${carbon.home}/repository/deployment/client/ - - ${carbon.home}/repository/conf/axis2/axis2_client.xml - - false - - - - - - - - - - admin - Default Administrator Role - - - user - Default User Role - - - - - false - - - - - - - ${carbon.home}/repository/resources/security/wso2carbon.jks - - JKS - - wso2carbon - - wso2carbon - - wso2carbon - - - - - - ${carbon.home}/repository/resources/security/client-truststore.jks - - JKS - - wso2carbon - - - - - - - - - - - - - - - - - - - UserManager - - - false - - org.wso2.carbon.identity.provider.AttributeCallbackHandler - - - org.wso2.carbon.identity.sts.store.DBTokenStore - - - true - allow - - - - - - -claim_mgt_menu -identity_mgt_emailtemplate_menu -identity_security_questions_menu - - - - ${carbon.home}/tmp/work - - - - - - true - - - 10 - - - 30 - - - - - - 100 - - - - keystore - certificate - * - - org.wso2.carbon.ui.transports.fileupload.AnyFileUploadExecutor - - - - - jarZip - - org.wso2.carbon.ui.transports.fileupload.JarZipUploadExecutor - - - - dbs - - org.wso2.carbon.ui.transports.fileupload.DBSFileUploadExecutor - - - - tools - - org.wso2.carbon.ui.transports.fileupload.ToolsFileUploadExecutor - - - - toolsAny - - org.wso2.carbon.ui.transports.fileupload.ToolsAnyFileUploadExecutor - - - - - - - - - - info - org.wso2.carbon.core.transports.util.InfoProcessor - - - wsdl - org.wso2.carbon.core.transports.util.Wsdl11Processor - - - wsdl2 - org.wso2.carbon.core.transports.util.Wsdl20Processor - - - xsd - org.wso2.carbon.core.transports.util.XsdProcessor - - - - - - false - false - true - svn - http://svnrepo.example.com/repos/ - username - password - true - - - - - - - - - - - - - - - ${require.carbon.servlet} - - - - - true - - - - - - - default repository - http://product-dist.wso2.com/p2/carbon/releases/wilkes/ - - - - - - - - true - - - - - - true - - diff --git a/component/client-handler/src/test/resources/repository/conf/identity/identity.xml b/component/client-handler/src/test/resources/repository/conf/identity/identity.xml deleted file mode 100644 index d355dd21..00000000 --- a/component/client-handler/src/test/resources/repository/conf/identity/identity.xml +++ /dev/null @@ -1,533 +0,0 @@ - - - - - - - - - jdbc/WSO2CarbonDB - - - - - true - true - 0 - - true - 20160 - 1140 - - - true - 720 - - - - - - - 15 - 20160 - - - - - - ${carbon.home}/conf/keystores - SunX509 - SunX509 - - - - SelfAndManaged - CertValidate - - - - - - - - - - - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/openidserver - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/openid - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/openid_login.do - - - false - - 7200 - - false - - - - - - - - - - - - - - - - - - - - - - -1 - -1 - -1 - -1 - - - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth/request-token - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth/authorize-url - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth/access-token - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/authorize - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/token - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/revoke - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/introspect - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/userinfo - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oidc/checksession - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oidc/logout - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_authz.do - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_error.do - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_consent.do - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_logout_consent.do - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_logout.do - - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/.well-known/webfinger - - - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/identity/connect/register - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/jwks - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/oidcdiscovery - - - 300 - - 3600 - - 3600 - - 84600 - - 300 - - false - - true - - org.wso2.carbon.identity.oauth.tokenprocessor.PlainTextPersistenceProcessor - - - - false - 60 - true - some-audience - client_id - client_id - true - SP - - - - - - token - org.wso2.carbon.identity.oauth2.authz.handlers.TokenResponseTypeHandler - - - code - org.wso2.carbon.identity.oauth2.authz.handlers.CodeResponseTypeHandler - - - id_token - org.wso2.carbon.identity.oauth2.authz.handlers.TokenResponseTypeHandler - - - id_token token - org.wso2.carbon.identity.oauth2.authz.handlers.TokenResponseTypeHandler - - - - - - authorization_code - org.wso2.carbon.identity.oauth2.token.handlers.grant.AuthorizationCodeGrantHandler - org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.validator.grant.JWTAuthorizationCodeGrantValidator - - - password - org.wso2.carbon.identity.oauth2.token.handlers.grant.PasswordGrantHandler - - - refresh_token - org.wso2.carbon.identity.oauth2.token.handlers.grant.RefreshGrantHandler - - - client_credentials - org.wso2.carbon.identity.oauth2.token.handlers.grant.ClientCredentialsGrantHandler - org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.validator.grant.JWTClientCredentialGrantValidator - - - urn:ietf:params:oauth:grant-type:saml2-bearer - org.wso2.carbon.identity.oauth2.token.handlers.grant.saml.SAML2BearerGrantHandler - - - iwa:ntlm - org.wso2.carbon.identity.oauth2.token.handlers.grant.iwa.ntlm.NTLMAuthenticationGrantHandler - - - - - - - - - false - - - - false - - - - false - org.wso2.carbon.identity.oauth2.authcontext.JWTTokenGenerator - org.wso2.carbon.identity.oauth2.authcontext.DefaultClaimsRetriever - http://wso2.org/claims - SHA256withRSA - 15 - - - - - - org.wso2.carbon.identity.openidconnect.DefaultIDTokenBuilder - SHA256withRSA - - - - - - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/token - org.wso2.carbon.identity.openidconnect.SAMLAssertionClaimsCallback - 3600 - org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInfoUserStoreClaimRetriever - org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInforRequestDefaultValidator - org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInfoISAccessTokenValidator - org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInfoJSONResponseBuilder - false - - - - - - - - gtalk - talk.google.com - 5222 - gmail.com - multifactor1@gmail.com - wso2carbon - - - - - - 157680000 - 157680000 - ${carbon.host} - - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/samlsso - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/samlsso_logout.do - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/samlsso_notification.do - 5 - 60000 - - false - http://wso2.org/claims - - org.wso2.carbon.identity.sso.saml.builders.assertion.DefaultSAMLAssertionBuilder - org.wso2.carbon.identity.sso.saml.builders.encryption.DefaultSSOEncrypter - org.wso2.carbon.identity.sso.saml.builders.signature.DefaultSSOSigner - org.wso2.carbon.identity.sso.saml.validators.SAML2HTTPRedirectDeflateSignatureValidator - - - - 5 - false - http://www.w3.org/2000/09/xmldsig#rsa-sha1 - http://www.w3.org/2000/09/xmldsig#sha1 - true - - - - - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/services/wso2carbon-sts - - - - - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/passivests - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/retry.do - org.wso2.carbon.identity.sts.passive.utils.NoPersistenceTokenStore - true - - - - - false - ${Ports.ThriftEntitlementReceivePort} - 10000 - - ${carbon.home}/repository/resources/security/wso2carbon.jks - wso2carbon - - - ${carbon.host} - - - - - - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/wso2/scim/Users - ${carbon.protocol}://${carbon.host}:${carbon.management.port}/wso2/scim/Groups - - - 5 - - - 10 - local://services - - - - - - - - - - - - - - org.wso2.carbon.identity.governance.store.JDBCIdentityDataStore - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /permission/admin/manage/identity/applicationmgt/delete - - - /permission/admin/manage/identity/applicationmgt/create - - - /permission/admin/manage/identity/applicationmgt/view - - - /permission/admin/manage/identity/pep - - - - - - - - - - /api/identity/user/v0.9 - /api/identity/recovery/v0.9 - /oauth2 - /api/identity/entitlement - - - /identity/(.*) - - - - - 300 - diff --git a/component/client-handler/src/test/resources/repository/resources/security/foo-com.jks b/component/client-handler/src/test/resources/repository/resources/security/foo-com.jks deleted file mode 100644 index 1c3eb532..00000000 Binary files a/component/client-handler/src/test/resources/repository/resources/security/foo-com.jks and /dev/null differ diff --git a/component/client-handler/src/test/resources/repository/resources/security/testkeystore.jks b/component/client-handler/src/test/resources/repository/resources/security/testkeystore.jks deleted file mode 100644 index 1472e693..00000000 Binary files a/component/client-handler/src/test/resources/repository/resources/security/testkeystore.jks and /dev/null differ diff --git a/component/client-handler/src/test/resources/repository/resources/security/wso2carbon.jks b/component/client-handler/src/test/resources/repository/resources/security/wso2carbon.jks deleted file mode 100644 index 3b4e10d0..00000000 Binary files a/component/client-handler/src/test/resources/repository/resources/security/wso2carbon.jks and /dev/null differ diff --git a/component/client-handler/src/test/resources/testng.xml b/component/client-handler/src/test/resources/testng.xml deleted file mode 100644 index 06a9b66e..00000000 --- a/component/client-handler/src/test/resources/testng.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/component/org.wso2.carbon.identity.dpop/README.md b/component/org.wso2.carbon.identity.dpop/README.md deleted file mode 100644 index 45671ce3..00000000 --- a/component/org.wso2.carbon.identity.dpop/README.md +++ /dev/null @@ -1,121 +0,0 @@ -##

⚠️ Deprecation Notice

- -**This component has been moved to a new standalone repository.All the future development will be -continued in the new repository and this repository will no longer be maintained.** - -**You can find the new repository here: [identity-oauth-dpop](https://github.com/wso2-extensions/identity-oauth-dpop)** - - -
- -# DPoP component - -DPoP ( Demonstrating Proof of Possession ) is an additional security mechanism for the token -generation which overcomes the issue of bearer token which will not validate between who is -requested token and who is actually using the token for the access of a particular resource.The specification defines a mechanism to prevent illegal API calls from succeeding only with a stolen access token. In the traditional mechanism, API access is allowed only if the access token presented by the client application is valid - -## Specification -https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop-02 - -## Design - -### Sequence Diagram. - -1. DPoP token request -![Screenshot from 2021-10-25 23-06-12](https://user-images.githubusercontent.com/26603378/138743329-5cc54271-08a6-44ec-938e-d675bdd24717.png) - - -2. Invoking protected APIs with DPoP token and DPoP proof. -![Invoke API(2)](https://user-images.githubusercontent.com/26603378/138742776-3d2c2714-c87e-4f77-9dce-24fde3df600e.jpeg) - -### Sample client application to create dpop proof -PR : [wso2 /samples-is#302 ](https://github.com/wso2/samples-is/pull/302 ) - -### Deployment Instructions - -1. Build the project using mvn clean install. -2. Add the org.wso2.carbon.identity.dpop-2.4.3-SNAPSHOT.jar JAR into the /repository/components/dropins folder. -3. Add the below configuration to deployment.toml file. - - ``` -[[event_listener]] -id = "dpop_listener" -type = "org.wso2.carbon.identity.core.handler.AbstractIdentityHandler" -name="org.wso2.carbon.identity.dpop.listener.OauthDPoPInterceptorHandlerProxy" -order = 13 -enable = true -properties.header_validity_period = 90 -properties.skip_dpop_validation_in_revoke = "true" - -[[oauth.custom_token_validator]] -type = "dpop" -class = "org.wso2.carbon.identity.dpop.validators.DPoPTokenValidator" -``` -4. Restart the Identity Server. -5. Sign in to the Management Console and navigate to - ```Service Providers -> List -> Edit -> Inbound Authentication Configuration ->OAuth OpenID Connect Configuration -> Edit``` -6. Enable DPoP Based Access token binding type and Validate token bindings. - -![Screenshot from 2021-10-25 23-08-05](https://user-images.githubusercontent.com/26603378/138743547-c6d71a23-e654-463b-9650-2cebdf37268d.png) - -### Sample Usage Instructions - -1. Access Token from Password : - -``` -curl --location --request POST 'https://localhost:9443/oauth2/token' \ ---header 'Content-Type: application/x-www-form-urlencoded' \ ---header 'dpop: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IlJTMzg0IiwiandrIjp7Imt0eSI6IlJTQSIsImUiOiJBUUFCIiwibiI6ImgyNlFBSUQtQWhyTmdac2FyX1pmUzM2aUtrTVQ0ZWR2YVJ3eHBheVFSVUlyV29qdENtZ0tCUnRXSllzSmJfQmJ5ZWJnb3gxVXhnaHRjMWNGVFFueVF6aDNHTHRfZXh5ajJ5Y2lFRHhUVTgyTHllT2ZaTnpVQTF0cjBPOFNtdVp4NWxSNnZKYTlMSFFYLXNYdFRsNVBMOWpHNDJVeENnZ3VETG5EZzJUcUMtWmNmdnItMER0OXFJNS1CdVo0TmZTQmE3WlBFeGZ0d2RuemVnRHJOemlfbEFDM0drRUs4dmdHYjFDc0hVS0dUdXZsX0MzX2JtVU50ZzdVdURYdEVyQmRxOHlxc0NHQ3lzSGs5YlBodkZ1bXJaQS1lU0pEQTlpMFYzOUJnaTZUYUpqNU5PZ0hkUFVET0lmUzF6aXE5WlVNR0NRdlJuN3hsN2N2X01MTUNTVElhdyJ9fQ.eyJodG0iOiJQT1NUIiwic3ViIjoic3ViIiwibmJmIjoxNjMyNzUzODQwLCJpc3MiOiJpc3N1ZXIiLCJodHUiOiJodHRwczpcL1wvbG9jYWxob3N0Ojk0NDNcL29hdXRoMlwvdG9rZW4iLCJpYXQiOjE2MzI3NTM4NDAsImp0aSI6IjE2MGVlYjIwLTVjN2EtNDM4ZC05YmI2LTY5ZTY0ZmU2N2ZjYiJ9.IMTqfcHtrlyJM9NqSuVulN2n2yWDgHkzRroxDF764HZrfThoJHp6YAx9PnSRjb652I5agZy48UZehKUiQ-tIXvW-vU8-C_3oeaOIMbTrXKDPHh41_1udw3B_zNkdwOPlyyNgFFRk_vzcV7yV7JdLaJVmMKmbNcqWE5zj7SbvorXhIzhVTL0XKhC1RzcuGImJYwzEUsAp0EWKHmD5Io46WQgY_Qauqzlyat2NYp797yySjfsIXxtFhlv_dsnMwBG4_-qWuwKCWLbUS1dEctwpv3cRqmt3L1ICQK7-t6CorhKy3MxWn7uM0viM7Jm0tjZbz3PYl5aDA55bqUAst9IlsQ' \ ---header 'Authorization: Basic ajdPOWVqbmpUSUN1VFl4cGMwamQ4MjJvU2FjYTpmREJzSXB5djlYS1lOVUxfQWs1QTM0NFh6cUVh' \ ---data-urlencode 'grant_type=password' \ ---data-urlencode 'username=admin' \ ---data-urlencode 'password=admin' \ ---data-urlencode 'scope=openid internal_user_mgt_list' -``` - -  Sample Response: - -``` -{ - "access_token": "1ce0fc0a-c830-307a-aafc-d25fdc4063ee", - "refresh_token": "ff7a6adb-116d-3a6f-83ff-3f61c7fa8b2f", - "scope": "internal_user_mgt_list openid", - "id_token": "eyJ4NXQiOiJNell4TW1Ga09HWXdNV0kwWldObU5EY3hOR1l3WW1NNFpUQTNNV0kyTkRBelpHUXpOR00wWkdSbE5qSmtPREZrWkRSaU9URmtNV0ZoTXpVMlpHVmxOZyIsImtpZCI6Ik16WXhNbUZrT0dZd01XSTBaV05tTkRjeE5HWXdZbU00WlRBM01XSTJOREF6WkdRek5HTTBaR1JsTmpKa09ERmtaRFJpT1RGa01XRmhNelUyWkdWbE5nX1JTMjU2IiwiYWxnIjoiUlMyNTYifQ.eyJhdF9oYXNoIjoiUGw2ZjJvdWNmY3RnQ2ZLazJZOEZ5USIsImF1ZCI6IjVEb09HWkFHQV9sQUdnSDB2WkJSRTgzTl9sQWEiLCJzdWIiOiJhZG1pbiIsIm5iZiI6MTY1Mjc2ODc5MiwiYXpwIjoiNURvT0daQUdBX2xBR2dIMHZaQlJFODNOX2xBYSIsImFtciI6WyJwYXNzd29yZCJdLCJpc3MiOiJodHRwczpcL1wvbG9jYWxob3N0Ojk0NDNcL29hdXRoMlwvdG9rZW4iLCJleHAiOjE2NTI3NzIzOTIsImlhdCI6MTY1Mjc2ODc5Mn0.dCwn5ln-iROxbVVOJicQFFqLse8NOYXc_HVnhCiQPoBLShaXKi-NbnTvXwoFL1NxQhv96YgyUhjrkLoQDEmzxQnFMkgq3hJV0MH68SBpsCaKIIzg3Z0KT_5VFSvDC-bQGHfmGS-Gxf5TWkKT7FGke-OYUw_x940qy_PMfZOM-q4A9gBiPTazjXbGo0dkIOINnEfz6TQvrE2opJxV7dj3bGV4NT-3Vqj3ooNbruQrK-c6ir_LLoyA71yuPJhkmtT8Ae_mXSDBjuH-TxcXp_htoGbCb_xDgA3zRyRmvc8OSlaHAO-OhtNK_d6x-wiUjM-n0hMdvGNS4oPn1yHyy5WEsg", - "token_type": "DPoP", - "expires_in": 3600 -} -``` - -2. Access Token from Refresh Token : - -``` -curl --location --request POST 'https://localhost:9443/oauth2/token' \ ---header 'Content-Type: application/x-www-form-urlencoded' \ ---header 'dpop: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoibkNmX3lscldjMTVtejVJZWxSQmJ2TGhLbFV1em4zd1dDSW9ReHVOUThlVSIsInkiOiJhMmU3OTU3S2c3aTVxTUE5UHVpandmSE9nMk95QlRsZ0pVaEhzWGtNaGZnIn19.eyJodG0iOiJQT1NUIiwic3ViIjoic3ViIiwibmJmIjoxNjUyMzY5ODE5LCJpc3MiOiJpc3N1ZXIiLCJodHUiOiJodHRwczpcL1wvbG9jYWxob3N0Ojk0NDNcL29hdXRoMlwvdG9rZW4iLCJpYXQiOjE2NTIzNjk4MTksImp0aSI6IjVhOWY0NDI5LWU2ZDMtNGE3NS1iZTU4LTViOTZhZGY4MTcyZiJ9.DIwqvVuG_JZYM1dOGha6CANCM4RUC-5MQQkYsbTDKJfMpgR8akYoOSQigDpPMJqbrQFqXq6FXQoPOEJVqlMiqA' \ ---header 'Authorization: Basic NURvT0daQUdBX2xBR2dIMHZaQlJFODNOX2xBYTpaZjl5U3pCUzRPZ3M0eWtuMWJaZmxVZkExTXNh' \ ---data-urlencode 'grant_type=refresh_token' \ ---data-urlencode 'refresh_token=a8dcd0c4-7272-3901-ade2-d24cb8bae241' -``` - -3. Access Protected Resource : - -``` -curl --location --request GET 'https://localhost:9443/scim2/Users' \ ---header 'accept: application/scim+json' \ ---header 'DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoibkNmX3lscldjMTVtejVJZWxSQmJ2TGhLbFV1em4zd1dDSW9ReHVOUThlVSIsInkiOiJhMmU3OTU3S2c3aTVxTUE5UHVpandmSE9nMk95QlRsZ0pVaEhzWGtNaGZnIn19.eyJodG0iOiJHRVQiLCJzdWIiOiJzdWIiLCJuYmYiOjE2NTI3Njg4MzEsImlzcyI6Imlzc3VlciIsImh0dSI6Imh0dHBzOlwvXC9sb2NhbGhvc3Q6OTQ0M1wvc2NpbTJcL1VzZXJzIiwiaWF0IjoxNjUyNzY4ODMxLCJqdGkiOiJlYjExOWZhYS02OGM2LTQ2ZGYtYTE2Ny1iZDAwNTJhYzRhYWEifQ.h5oujqZugEANfOnEWM23z6AGpcckic4fphkcjGqrizy9_K7pybYtadGBxYlrU81d0bP5LKbkZCKXWtdvYXLqXg' \ ---header 'Authorization: DPoP 1ce0fc0a-c830-307a-aafc-d25fdc4063ee' -``` -  Here, **Authorization Header Value = DPoP {access-token}** - -4. Revoke Token : - -``` -curl --location --request POST 'https://localhost:9443/oauth2/revoke' \ ---header 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' \ ---header 'DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoibkNmX3lscldjMTVtejVJZWxSQmJ2TGhLbFV1em4zd1dDSW9ReHVOUThlVSIsInkiOiJhMmU3OTU3S2c3aTVxTUE5UHVpandmSE9nMk95QlRsZ0pVaEhzWGtNaGZnIn19.eyJodG0iOiJQT1NUIiwic3ViIjoic3ViIiwibmJmIjoxNjUyNzY4NjczLCJpc3MiOiJpc3N1ZXIiLCJodHUiOiJodHRwczpcL1wvbG9jYWxob3N0Ojk0NDNcL29hdXRoMlwvcmV2b2tlIiwiaWF0IjoxNjUyNzY4NjczLCJqdGkiOiI4OGIzNzBjNS1kYWVmLTQyOWItOTJjNS1iMGFhOTMzOGU1NTQifQ.6qa7IwHY1_xwykRSHRgxABOtBdPkp_nKDKSvCZ_C9GRWZaNtwKJsIwBmlFOYwnzh_yM3HsZj9HaGCBrNZfJ5fQ' \ ---header 'Authorization: Basic NURvT0daQUdBX2xBR2dIMHZaQlJFODNOX2xBYTpaZjl5U3pCUzRPZ3M0eWtuMWJaZmxVZkExTXNh' \ ---data-urlencode 'token=1ce0fc0a-c830-307a-aafc-d25fdc4063ee' \ ---data-urlencode 'token_type_hint=access_token' -``` - - diff --git a/component/org.wso2.carbon.identity.dpop/pom.xml b/component/org.wso2.carbon.identity.dpop/pom.xml deleted file mode 100644 index 9c0c946f..00000000 --- a/component/org.wso2.carbon.identity.dpop/pom.xml +++ /dev/null @@ -1,149 +0,0 @@ - - - - - identity-oauth2-extenstions - org.wso2.carbon.extension.identity.oauth.addons - 2.5.17-SNAPSHOT - ../../pom.xml - - 4.0.0 - - org.wso2.carbon.identity.dpop - bundle - - - - org.wso2.carbon.utils - org.wso2.carbon.database.utils - - - org.wso2.eclipse.osgi - org.eclipse.osgi.services - - - org.wso2.orbit.com.nimbusds - nimbus-jose-jwt - - - org.wso2.carbon.identity.inbound.auth.oauth2 - org.wso2.carbon.identity.oauth - - - org.wso2.carbon.identity.inbound.auth.oauth2 - org.wso2.carbon.identity.oauth.common - - - org.wso2.carbon.identity.framework - org.wso2.carbon.identity.event - - - org.wso2.carbon.identity.framework - org.wso2.carbon.identity.base - - - com.googlecode.json-simple.wso2 - json-simple - provided - - - org.json.wso2 - json - provided - - - org.wso2.carbon.identity.framework - org.wso2.carbon.identity.core - - - org.wso2.carbon.identity.auth.rest - org.wso2.carbon.identity.auth.service - - - org.wso2.carbon - org.wso2.carbon.core.common - - - org.apache.felix - org.apache.felix.scr.ds-annotations - - - - - - - org.apache.felix - maven-bundle-plugin - true - - - org.wso2.carbon.identity.dpop - ${project.artifactId} - - org.wso2.carbon.identity.dpop.internal, - - - com.nimbusds.jose.*; version="${nimbusds.osgi.version.range}", - com.nimbusds.jwt; version="${nimbusds.osgi.version.range}", - javax.servlet.http; version="${javax.servlet.http.package.import.version.range}", - org.osgi.framework; version="${osgi.framework.package.import.version.range}", - - org.json, - org.json.simple, - org.json.simple.parser, - - org.osgi.service.component; - version="${osgi.service.component.package.import.version.range}", - org.apache.commons.logging; - version="${apache.commons.logging.package.import.version.range}", - org.wso2.carbon.identity.oauth.*; - version="${identity.inbound.auth.oauth.imp.pkg.version}", - org.wso2.carbon.identity.oauth2.*; - version="${identity.inbound.auth.oauth.imp.pkg.version}", - org.wso2.carbon.identity.auth.service.*; - version="${identity.carbon.auth.rest.imp.pkg.version}", - org.wso2.carbon.identity.base; - version="${carbon.identity.package.import.version.range}", - org.wso2.carbon.identity.core.*; - version="${carbon.identity.package.import.version.range}", - org.wso2.carbon.user.core.*; - version="${carbon.kernel.package.import.version.range}", - org.wso2.carbon.identity.application.common.*; - version="${carbon.identity.package.import.version.range}", - org.wso2.carbon.utils.multitenancy; - version="${carbon.kernel.package.import.version.range}", - org.apache.catalina.*;version="${apache.catalina.version}", - org.wso2.carbon.database.utils.*; - version="${org.wso2.carbon.database.utils.version.range}", - org.apache.axiom.om.*; version="${axiom.osgi.version.range}", - org.wso2.carbon.idp.mgt; - version="${carbon.identity.package.import.version.range}", - org.wso2.carbon.context.*; version="${carbon.kernel.imp.pkg.version.range}", - net.minidev.json.*; version="${net.minidev.json.imp.pkg.version.range}" - - - !org.wso2.carbon.identity.dpop.internal, - org.wso2.carbon.identity.dpop.*; version="${project.version}" - - - - - - - diff --git a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/constant/DPoPConstants.java b/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/constant/DPoPConstants.java deleted file mode 100644 index 77dcfa6f..00000000 --- a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/constant/DPoPConstants.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License - */ - -package org.wso2.carbon.identity.dpop.constant; - -/** - * This class defines constants for Oauth2 DPoP validation. - */ -public class DPoPConstants { - - public static final String VALIDITY_PERIOD = "header_validity_period"; - public static final int DEFAULT_HEADER_VALIDITY = 60000; - public static final String DPOP_ISSUED_AT = "iat"; - public static final String DPOP_HTTP_URI = "htu"; - public static final String DPOP_HTTP_METHOD = "htm"; - public static final String DPOP_ACCESS_TOKEN_HASH = "ath"; - public static final String DPOP_JWT_TYPE = "dpop+jwt"; - public static final String DPOP_TOKEN_TYPE = "DPoP"; - public static final String INVALID_DPOP_PROOF = "invalid_dpop_proof"; - public static final String INVALID_DPOP_ERROR = "Invalid DPoP Proof"; - public static final String INVALID_CLIENT = "invalid_client"; - public static final String INVALID_CLIENT_ERROR = "Invalid Client"; - public static final String ECDSA_ENCRYPTION = "EC"; - public static final String RSA_ENCRYPTION = "RSA"; - public static final String HTTP_METHOD ="httpMethod"; - public static final String HTTP_URL ="httpUrl"; - public static final String JTI = "jti"; - public static final String OAUTH_DPOP_HEADER = "DPoP"; - public static final String CNF = "cnf"; - public static final String TOKEN_TYPE = "token_type"; - public static final String JWK_THUMBPRINT = "jkt"; - public static final String AUTHORIZATION_HEADER = "authorization"; - public static final String OAUTH_REVOKE_ENDPOINT = "/oauth2/revoke"; - public static final String SKIP_DPOP_VALIDATION_IN_REVOKE = "skip_dpop_validation_in_revoke"; - public static final boolean DEFAULT_SKIP_DPOP_VALIDATION_IN_REVOKE_VALUE = true; - - /** - * This class defines SQLQueries. - */ - public static class SQLQueries { - - public static final String RETRIEVE_TOKEN_BINDING_BY_REFRESH_TOKEN = - "SELECT BINDING.TOKEN_BINDING_TYPE,BINDING.TOKEN_BINDING_VALUE,BINDING.TOKEN_BINDING_REF " + - "FROM IDN_OAUTH2_ACCESS_TOKEN TOKEN LEFT JOIN IDN_OAUTH2_TOKEN_BINDING BINDING ON " + - "TOKEN.TOKEN_ID=BINDING.TOKEN_ID WHERE TOKEN.REFRESH_TOKEN = ? " + - "AND BINDING.TOKEN_BINDING_TYPE = ?"; - } -} diff --git a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/dao/DPoPTokenManagerDAO.java b/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/dao/DPoPTokenManagerDAO.java deleted file mode 100644 index a2ffa21b..00000000 --- a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/dao/DPoPTokenManagerDAO.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com). - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.dpop.dao; - -import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; -import org.wso2.carbon.identity.oauth2.token.bindings.TokenBinding; - -/** - * This interface defines methods to access the database for DPoP token purposes. - */ -public interface DPoPTokenManagerDAO { - - /** - * Returns the binding type using the refresh token and checking Hash is enabled or not. - * - * @param refreshToken Refresh token. - * @return TokenBinding from the refresh token. - * @throws IdentityOAuth2Exception If an error occurs while retrieving the binding type. - */ - TokenBinding getTokenBinding(String refreshToken, boolean isHashedToken) throws IdentityOAuth2Exception; -} diff --git a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/dao/DPoPTokenManagerDAOImpl.java b/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/dao/DPoPTokenManagerDAOImpl.java deleted file mode 100644 index 49e9dc8d..00000000 --- a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/dao/DPoPTokenManagerDAOImpl.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com). - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.dpop.dao; - -import org.wso2.carbon.database.utils.jdbc.JdbcTemplate; -import org.wso2.carbon.database.utils.jdbc.exceptions.DataAccessException; -import org.wso2.carbon.identity.dpop.constant.DPoPConstants; -import org.wso2.carbon.identity.dpop.util.Utils; -import org.wso2.carbon.identity.oauth.tokenprocessor.HashingPersistenceProcessor; -import org.wso2.carbon.identity.oauth.tokenprocessor.TokenPersistenceProcessor; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; -import org.wso2.carbon.identity.oauth2.token.bindings.TokenBinding; - -import java.util.List; - -/** - * This class implements {@link DPoPTokenManagerDAO} interface. - */ -public class DPoPTokenManagerDAOImpl implements DPoPTokenManagerDAO { - - private static TokenPersistenceProcessor hashingPersistenceProcessor; - - public DPoPTokenManagerDAOImpl() { - - hashingPersistenceProcessor = new HashingPersistenceProcessor(); - } - - @Override - public TokenBinding getTokenBinding(String refreshToken, boolean isTokenHashingEnabled) throws IdentityOAuth2Exception { - - if (isTokenHashingEnabled) { - return getBindingFromRefreshToken(refreshToken, true); - } - return getBindingFromRefreshToken(refreshToken, false); - } - - private TokenBinding getBindingFromRefreshToken(String refreshToken,boolean isTokenHashingEnabled) throws IdentityOAuth2Exception { - - JdbcTemplate jdbcTemplate = Utils.getNewTemplate(); - if (isTokenHashingEnabled) { - refreshToken = hashingPersistenceProcessor.getProcessedRefreshToken(refreshToken); - } - try { - String finalRefreshToken = refreshToken; - List tokenBindingList = jdbcTemplate.executeQuery( - DPoPConstants.SQLQueries.RETRIEVE_TOKEN_BINDING_BY_REFRESH_TOKEN, - (resultSet, rowNumber) -> { - TokenBinding tokenBinding = new TokenBinding(); - tokenBinding.setBindingType(resultSet.getString(1)); - tokenBinding.setBindingValue(resultSet.getString(2)); - tokenBinding.setBindingReference(resultSet.getString(3)); - - return tokenBinding; - }, - preparedStatement -> { - int parameterIndex = 0; - preparedStatement.setString(++parameterIndex, finalRefreshToken); - preparedStatement.setString(++parameterIndex, DPoPConstants.DPOP_TOKEN_TYPE); - }); - - return tokenBindingList.isEmpty() ? null : tokenBindingList.get(0); - } catch (DataAccessException e) { - String error = String.format("Error obtaining token binding type using refresh token: %s.", - refreshToken); - throw new IdentityOAuth2Exception(error, e); - } - } -} diff --git a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/handler/DPoPAuthenticationHandler.java b/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/handler/DPoPAuthenticationHandler.java deleted file mode 100644 index 47cff4ba..00000000 --- a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/handler/DPoPAuthenticationHandler.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com). - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.dpop.handler; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.http.HttpHeaders; -import org.wso2.carbon.identity.auth.service.AuthenticationContext; -import org.wso2.carbon.identity.auth.service.AuthenticationRequest; -import org.wso2.carbon.identity.auth.service.AuthenticationResult; -import org.wso2.carbon.identity.auth.service.AuthenticationStatus; -import org.wso2.carbon.identity.auth.service.exception.AuthenticationFailException; -import org.wso2.carbon.identity.auth.service.handler.AuthenticationHandler; -import org.wso2.carbon.identity.auth.service.util.AuthConfigurationUtil; -import org.wso2.carbon.identity.core.bean.context.MessageContext; -import org.wso2.carbon.identity.dpop.constant.DPoPConstants; -import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService; -import org.wso2.carbon.identity.oauth2.dto.OAuth2ClientApplicationDTO; -import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationRequestDTO; -import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationResponseDTO; - -import javax.servlet.http.HttpServletRequest; - -/** - * DPoPAuthenticationHandler will validate the requests authorized with DPoP access tokens. - */ -public class DPoPAuthenticationHandler extends AuthenticationHandler { - - private static final Log log = LogFactory.getLog(DPoPAuthenticationHandler.class); - - @Override - protected AuthenticationResult doAuthenticate(MessageContext messageContext) throws - AuthenticationFailException { - - AuthenticationResult authenticationResult = new AuthenticationResult(AuthenticationStatus.FAILED); - AuthenticationContext authenticationContext = (AuthenticationContext) messageContext; - AuthenticationRequest authenticationRequest = authenticationContext.getAuthenticationRequest(); - if (authenticationRequest != null) { - - String authorizationHeader = authenticationRequest.getHeader(HttpHeaders.AUTHORIZATION); - if (StringUtils.isNotBlank(authorizationHeader) && - authorizationHeader.startsWith(DPoPConstants.OAUTH_DPOP_HEADER)) { - String accessToken; - String[] dpopToken = authorizationHeader.split(" "); - if (dpopToken.length != 2) { - String errorMessage = String.format("Error occurred while trying to authenticate." + - "The %s header value is not defined correctly.", DPoPConstants.OAUTH_DPOP_HEADER); - throw new AuthenticationFailException(errorMessage); - } - accessToken = dpopToken[1]; - OAuth2TokenValidationService oAuth2TokenValidationService = new OAuth2TokenValidationService(); - OAuth2TokenValidationRequestDTO requestDTO = new OAuth2TokenValidationRequestDTO(); - OAuth2TokenValidationRequestDTO.OAuth2AccessToken token = requestDTO.new OAuth2AccessToken(); - token.setIdentifier(accessToken); - token.setTokenType(DPoPConstants.OAUTH_DPOP_HEADER); - requestDTO.setAccessToken(token); - setContextParam(authenticationRequest, requestDTO); - OAuth2ClientApplicationDTO clientApplicationDTO = - oAuth2TokenValidationService.findOAuthConsumerIfTokenIsValid(requestDTO); - OAuth2TokenValidationResponseDTO responseDTO = clientApplicationDTO.getAccessTokenValidationResponse(); - if (!responseDTO.isValid()) { - if (log.isDebugEnabled()) { - log.debug(responseDTO.getErrorMsg()); - } - return authenticationResult; - } - authenticationResult.setAuthenticationStatus(AuthenticationStatus.SUCCESS); - return authenticationResult; - } - } - return authenticationResult; - } - - @Override - public int getPriority(MessageContext messageContext) { - - return getPriority(messageContext, 24); - } - - @Override - public boolean canHandle(MessageContext messageContext) { - - return AuthConfigurationUtil.isAuthHeaderMatch(messageContext, DPoPConstants.OAUTH_DPOP_HEADER); - } - - private void setContextParam(AuthenticationRequest authenticationRequest, - OAuth2TokenValidationRequestDTO requestDTO) { - - HttpServletRequest request = authenticationRequest.getRequest(); - String dpopHeader = request.getHeader(DPoPConstants.OAUTH_DPOP_HEADER); - - OAuth2TokenValidationRequestDTO.TokenValidationContextParam httpMethod = requestDTO.new - TokenValidationContextParam(); - httpMethod.setKey(DPoPConstants.HTTP_METHOD); - httpMethod.setValue(request.getMethod()); - - OAuth2TokenValidationRequestDTO.TokenValidationContextParam httpURL = requestDTO.new - TokenValidationContextParam(); - httpURL.setKey(DPoPConstants.HTTP_URL); - httpURL.setValue(String.valueOf(request.getRequestURL())); - - OAuth2TokenValidationRequestDTO.TokenValidationContextParam dpopProof = requestDTO.new - TokenValidationContextParam(); - dpopProof.setKey(DPoPConstants.OAUTH_DPOP_HEADER); - dpopProof.setValue(dpopHeader); - - OAuth2TokenValidationRequestDTO.TokenValidationContextParam[] contextParams = - new OAuth2TokenValidationRequestDTO.TokenValidationContextParam[3]; - contextParams[0] = httpMethod; - contextParams[1] = httpURL; - contextParams[2] = dpopProof; - requestDTO.setContext(contextParams); - } -} diff --git a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/internal/DPoPDataHolder.java b/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/internal/DPoPDataHolder.java deleted file mode 100644 index 9d9b7e1b..00000000 --- a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/internal/DPoPDataHolder.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com). - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.dpop.internal; - -import org.wso2.carbon.identity.dpop.dao.DPoPTokenManagerDAO; - -/** - * DPoP data holder. - */ -public class DPoPDataHolder { - - private static final DPoPDataHolder dPoPDataHolder = new DPoPDataHolder(); - private DPoPTokenManagerDAO tokenBindingTypeManagerDao; - - public static DPoPDataHolder getInstance() { - - return dPoPDataHolder; - } - - public static DPoPDataHolder getDPoPDataHolder() { - - return dPoPDataHolder; - } - - /** - * Get Token binding type manager dao. - * - * @return TokenBindingTypeManagerDao - */ - public DPoPTokenManagerDAO getTokenBindingTypeManagerDao() { - - return tokenBindingTypeManagerDao; - } - - /** - * Set Token binding type manager dao. - * - * @param tokenBindingTypeManagerDao TokenBindingTypeManagerDao - */ - public void setTokenBindingTypeManagerDao( - DPoPTokenManagerDAO tokenBindingTypeManagerDao) { - - this.tokenBindingTypeManagerDao = tokenBindingTypeManagerDao; - } -} diff --git a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/internal/DPoPServiceComponent.java b/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/internal/DPoPServiceComponent.java deleted file mode 100644 index f6d73693..00000000 --- a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/internal/DPoPServiceComponent.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License - */ - -package org.wso2.carbon.identity.dpop.internal; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.osgi.service.component.ComponentContext; -import org.osgi.service.component.annotations.Activate; -import org.osgi.service.component.annotations.Component; -import org.wso2.carbon.identity.auth.service.handler.AuthenticationHandler; -import org.wso2.carbon.identity.dpop.dao.DPoPTokenManagerDAOImpl; -import org.wso2.carbon.identity.dpop.handler.DPoPAuthenticationHandler; -import org.wso2.carbon.identity.dpop.introspection.dataprovider.DPoPIntrospectionDataProvider; -import org.wso2.carbon.identity.dpop.listener.OauthDPoPInterceptorHandlerProxy; -import org.wso2.carbon.identity.dpop.token.binder.DPoPBasedTokenBinder; -import org.wso2.carbon.identity.dpop.validators.DPoPTokenValidator; -import org.wso2.carbon.identity.oauth.common.token.bindings.TokenBinderInfo; -import org.wso2.carbon.identity.oauth.event.OAuthEventInterceptor; -import org.wso2.carbon.identity.oauth2.IntrospectionDataProvider; -import org.wso2.carbon.identity.oauth2.validators.OAuth2TokenValidator; - -@Component( - name = "org.wso2.carbon.identity.oauth.dpop", - immediate = true) -public class DPoPServiceComponent { - - private static final Log log = LogFactory.getLog(DPoPServiceComponent.class); - - @Activate - protected void activate(ComponentContext context) { - - try { - DPoPDataHolder.getInstance().setTokenBindingTypeManagerDao(new DPoPTokenManagerDAOImpl()); - context.getBundleContext().registerService(TokenBinderInfo.class.getName(), - new DPoPBasedTokenBinder(), null); - context.getBundleContext().registerService(OAuthEventInterceptor.class, - new OauthDPoPInterceptorHandlerProxy(), null); - context.getBundleContext().registerService(AuthenticationHandler.class.getName(), - new DPoPAuthenticationHandler(), null); - context.getBundleContext().registerService(IntrospectionDataProvider.class.getName(), - new DPoPIntrospectionDataProvider(), null); - context.getBundleContext().registerService(OAuth2TokenValidator.class.getName(), - new DPoPTokenValidator(), null); - if (log.isDebugEnabled()) { - log.debug("DPoPService is activated."); - } - } catch (Throwable e) { - log.error("Error while activating DPoPServiceComponent.", e); - } - } -} diff --git a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/introspection/dataprovider/DPoPIntrospectionDataProvider.java b/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/introspection/dataprovider/DPoPIntrospectionDataProvider.java deleted file mode 100644 index ac480c61..00000000 --- a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/introspection/dataprovider/DPoPIntrospectionDataProvider.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com). - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.dpop.introspection.dataprovider; - -import org.json.simple.JSONObject; -import org.wso2.carbon.identity.core.handler.AbstractIdentityHandler; -import org.wso2.carbon.identity.dpop.constant.DPoPConstants; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; -import org.wso2.carbon.identity.oauth2.IntrospectionDataProvider; -import org.wso2.carbon.identity.oauth2.dto.OAuth2IntrospectionResponseDTO; -import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationRequestDTO; -import org.wso2.carbon.identity.oauth2.model.AccessTokenDO; -import org.wso2.carbon.identity.oauth2.util.OAuth2Util; - -import java.util.HashMap; -import java.util.Map; - -/** - * Introspection Data provider to include cnf to introspection response. - */ -public class DPoPIntrospectionDataProvider extends AbstractIdentityHandler implements IntrospectionDataProvider { - - @Override - public Map getIntrospectionData(OAuth2TokenValidationRequestDTO oAuth2TokenValidationRequestDTO, - OAuth2IntrospectionResponseDTO oAuth2IntrospectionResponseDTO) - throws IdentityOAuth2Exception { - - Map introspectionData = new HashMap<>(); - AccessTokenDO accessTokenDO; - - if (isEnabled()) { - - accessTokenDO = OAuth2Util.findAccessToken(oAuth2TokenValidationRequestDTO. - getAccessToken().getIdentifier(), false); - - if (accessTokenDO.getTokenBinding() != null && - DPoPConstants.DPOP_TOKEN_TYPE.equals(accessTokenDO.getTokenBinding().getBindingType())) { - introspectionData.put(DPoPConstants.TOKEN_TYPE, (DPoPConstants.DPOP_TOKEN_TYPE)); - JSONObject cnf = new JSONObject(); - cnf.put(DPoPConstants.JWK_THUMBPRINT, accessTokenDO.getTokenBinding().getBindingValue()); - introspectionData.put(DPoPConstants.CNF, cnf); - } - } - return introspectionData; - } -} diff --git a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/listener/OauthDPoPInterceptorHandlerProxy.java b/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/listener/OauthDPoPInterceptorHandlerProxy.java deleted file mode 100644 index 8fddda54..00000000 --- a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/listener/OauthDPoPInterceptorHandlerProxy.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License - */ - -package org.wso2.carbon.identity.dpop.listener; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.identity.core.handler.AbstractIdentityHandler; -import org.wso2.carbon.identity.core.model.IdentityEventListenerConfig; -import org.wso2.carbon.identity.core.util.IdentityUtil; -import org.wso2.carbon.identity.dpop.constant.DPoPConstants; -import org.wso2.carbon.identity.dpop.dao.DPoPTokenManagerDAO; -import org.wso2.carbon.identity.dpop.internal.DPoPDataHolder; -import org.wso2.carbon.identity.dpop.validators.DPoPHeaderValidator; -import org.wso2.carbon.identity.oauth.common.exception.InvalidOAuthClientException; -import org.wso2.carbon.identity.oauth.event.AbstractOAuthEventInterceptor; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2ClientException; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; -import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO; -import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenRespDTO; -import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext; -import org.wso2.carbon.identity.oauth2.token.bindings.TokenBinding; -import org.wso2.carbon.identity.oauth2.util.OAuth2Util; - -import java.util.Map; - -/** - * This class extends {@link AbstractOAuthEventInterceptor} and listen to oauth token related events. - * In this class, DPoP proof validation will be handled for DPoP token requests. - */ -public class OauthDPoPInterceptorHandlerProxy extends AbstractOAuthEventInterceptor { - - private static final Log log = LogFactory.getLog(OauthDPoPInterceptorHandlerProxy.class); - private DPoPTokenManagerDAO - tokenBindingTypeManagerDao = DPoPDataHolder.getInstance().getTokenBindingTypeManagerDao(); - - /** - * {@inheritdoc} - */ - @Override - public void onPreTokenIssue(OAuth2AccessTokenReqDTO tokenReqDTO, OAuthTokenReqMessageContext tokReqMsgCtx, - Map params) throws IdentityOAuth2Exception { - - String consumerKey = tokenReqDTO.getClientId(); - if (log.isDebugEnabled()) { - log.debug(String.format("DPoP proxy intercepted the token request from the client : %s.", consumerKey)); - } - try { - String tokenBindingType = DPoPHeaderValidator.getApplicationBindingType(tokenReqDTO.getClientId()); - if (DPoPConstants.DPOP_TOKEN_TYPE.equals(tokenBindingType)) { - - String dPoPProof = DPoPHeaderValidator.getDPoPHeader(tokReqMsgCtx); - if (StringUtils.isBlank(dPoPProof)) { - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, - "DPoP header is required."); - } - boolean isValidDPoP = DPoPHeaderValidator.isValidDPoP(dPoPProof, tokenReqDTO, tokReqMsgCtx); - if (!isValidDPoP) { - if (log.isDebugEnabled()) { - log.debug(String.format("DPoP proof validation failed, Application ID: %s.", consumerKey)); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, - DPoPConstants.INVALID_DPOP_ERROR); - } - } else { - if (log.isDebugEnabled()) { - log.debug(String.format("Bearer access token request received from client: %s.", consumerKey)); - } - } - } catch (InvalidOAuthClientException e) { - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_CLIENT, DPoPConstants.INVALID_CLIENT_ERROR); - } - } - - /** - * {@inheritdoc} - */ - @Override - public void onPreTokenRenewal(OAuth2AccessTokenReqDTO tokenReqDTO, OAuthTokenReqMessageContext tokReqMsgCtx, - Map params) throws IdentityOAuth2Exception { - - String consumerKey = tokenReqDTO.getClientId(); - if (log.isDebugEnabled()) { - log.debug(String.format("DPoP proxy intercepted the token renewal request from the client : %s.", - consumerKey)); - } - try { - String tokenBindingType = DPoPHeaderValidator.getApplicationBindingType(tokenReqDTO.getClientId()); - TokenBinding tokenBinding = - tokenBindingTypeManagerDao.getTokenBinding(tokenReqDTO.getRefreshToken(), OAuth2Util.isHashEnabled()); - if (tokenBinding != null) { - if (!DPoPConstants.DPOP_TOKEN_TYPE.equals(tokenBindingType)) { - if (log.isDebugEnabled()) { - log.debug(String.format("DPoP based token binding is not enabled for the " + - "application Id : %s.", consumerKey)); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_CLIENT, - DPoPConstants.INVALID_CLIENT_ERROR); - } - - String dPoPProof = DPoPHeaderValidator.getDPoPHeader(tokReqMsgCtx); - if (StringUtils.isBlank(dPoPProof)) { - if (log.isDebugEnabled()) { - log.debug(String.format("Renewal request received without the DPoP proof from the " + - "application Id: %s.", consumerKey)); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, - "DPoP proof is required."); - } - - if (!DPoPHeaderValidator.isValidDPoP(dPoPProof, tokenReqDTO, tokReqMsgCtx)) { - if (log.isDebugEnabled()) { - log.debug(String.format("DPoP proof validation failed for the application Id : %s.", - consumerKey)); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, - DPoPConstants.INVALID_DPOP_ERROR); - } - if (!tokReqMsgCtx.getTokenBinding().getBindingValue().equalsIgnoreCase(tokenBinding.getBindingValue())) { - if (log.isDebugEnabled()) { - log.debug("DPoP proof thumbprint value of the public key is not equal to binding value from" + - " the refresh token."); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, - DPoPConstants.INVALID_DPOP_ERROR); - } - } - } catch (InvalidOAuthClientException e) { - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_CLIENT, DPoPConstants.INVALID_CLIENT_ERROR); - } - } - - @Override - public boolean isEnabled() { - - IdentityEventListenerConfig identityEventListenerConfig = IdentityUtil.readEventListenerProperty - (AbstractIdentityHandler.class.getName(), this.getClass().getName()); - return identityEventListenerConfig != null && Boolean.parseBoolean(identityEventListenerConfig.getEnable()); - } - - /** - * {@inheritdoc} - */ - @Override - public void onPostTokenIssue(OAuth2AccessTokenReqDTO tokenReqDTO, OAuth2AccessTokenRespDTO tokenRespDTO, - OAuthTokenReqMessageContext tokReqMsgCtx, Map params) { - - setDPoPTokenType(tokReqMsgCtx,tokenRespDTO); - } - - /** - * {@inheritdoc} - */ - @Override - public void onPostTokenRenewal(OAuth2AccessTokenReqDTO tokenReqDTO, OAuth2AccessTokenRespDTO tokenRespDTO, - OAuthTokenReqMessageContext tokReqMsgCtx, Map params) { - setDPoPTokenType(tokReqMsgCtx,tokenRespDTO); - - } - - private void setDPoPTokenType(OAuthTokenReqMessageContext tokReqMsgCtx, OAuth2AccessTokenRespDTO tokenRespDTO) { - - if (tokReqMsgCtx.getTokenBinding() != null && - DPoPConstants.DPOP_TOKEN_TYPE.equals(tokReqMsgCtx.getTokenBinding().getBindingType())) { - if (tokenRespDTO != null) { - tokenRespDTO.setTokenType(DPoPConstants.DPOP_TOKEN_TYPE); - } - } - } -} diff --git a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/token/binder/DPoPBasedTokenBinder.java b/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/token/binder/DPoPBasedTokenBinder.java deleted file mode 100644 index 30187cee..00000000 --- a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/token/binder/DPoPBasedTokenBinder.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com). - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.dpop.token.binder; - -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.identity.core.handler.AbstractIdentityHandler; -import org.wso2.carbon.identity.core.util.IdentityUtil; -import org.wso2.carbon.identity.dpop.constant.DPoPConstants; -import org.wso2.carbon.identity.dpop.dao.DPoPTokenManagerDAO; -import org.wso2.carbon.identity.dpop.internal.DPoPDataHolder; -import org.wso2.carbon.identity.dpop.listener.OauthDPoPInterceptorHandlerProxy; -import org.wso2.carbon.identity.dpop.util.Utils; -import org.wso2.carbon.identity.dpop.validators.DPoPHeaderValidator; -import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; -import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO; -import org.wso2.carbon.identity.oauth2.model.HttpRequestHeader; -import org.wso2.carbon.identity.oauth2.token.bindings.TokenBinding; -import org.wso2.carbon.identity.oauth2.token.bindings.impl.AbstractTokenBinder; -import org.wso2.carbon.identity.oauth2.util.OAuth2Util; - -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.Set; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * This class provides the DPoP based token binder implementation. - */ -public class DPoPBasedTokenBinder extends AbstractTokenBinder { - - private static final String BINDING_TYPE = "DPoP"; - private static final Log log = LogFactory.getLog(DPoPBasedTokenBinder.class); - static Set supportedGrantTypesSet = Collections.emptySet(); - private DPoPTokenManagerDAO - tokenBindingTypeManagerDao = DPoPDataHolder.getInstance().getTokenBindingTypeManagerDao(); - - - @Override - public String getDisplayName() { - - return "DPoP Based"; - } - - @Override - public String getDescription() { - - return "Bind tokens as DPoP tokens."; - } - - @Override - public String getBindingType() { - - return BINDING_TYPE; - } - - @Override - public List getSupportedGrantTypes() { - - return new ArrayList<>(Arrays.asList(getAllGrantTypes())); - } - - @Override - public String getOrGenerateTokenBindingValue(HttpServletRequest request) { - - return null; - } - - @Override - public void setTokenBindingValueForResponse(HttpServletResponse response, String bindingValue) { - - // Not required. - } - - @Override - public void clearTokenBindingElements(HttpServletRequest request, HttpServletResponse response) { - - // Not required. - } - - @Override - public boolean isValidTokenBinding(Object request, String bindingReference) { - - return true; - } - - @Override - public boolean isValidTokenBinding(Object request, TokenBinding tokenBinding) { - - try { - if (tokenBinding != null && DPoPConstants.OAUTH_DPOP_HEADER.equals(tokenBinding.getBindingType())) { - return validateDPoPHeader(request, tokenBinding); - } - } catch (IdentityOAuth2Exception | ParseException e) { - log.error("Error while getting the token binding value", e); - return false; - } - return false; - } - - @Override - public boolean isValidTokenBinding(OAuth2AccessTokenReqDTO oAuth2AccessTokenReqDTO, String bindingReference) { - - if (StringUtils.isBlank(bindingReference)) { - return false; - } - - String refreshToken = oAuth2AccessTokenReqDTO.getRefreshToken(); - try { - TokenBinding tokenBinding = - tokenBindingTypeManagerDao.getTokenBinding(refreshToken, OAuth2Util.isHashEnabled()); - - if (tokenBinding != null && DPoPConstants.OAUTH_DPOP_HEADER.equals(tokenBinding.getBindingType())) { - return bindingReference.equalsIgnoreCase(tokenBinding.getBindingReference()); - } - return false; - } catch (IdentityOAuth2Exception e) { - return false; - } - } - - @Override - public String getTokenBindingValue(HttpServletRequest request) { - - try { - String tokenBindingValue = retrieveTokenBindingValueFromDPoPHeader(request); - - if (StringUtils.isNotBlank(tokenBindingValue)) { - return tokenBindingValue; - } - return null; - } catch (IdentityOAuth2Exception e) { - return null; - } - } - - @Override - public Optional getTokenBindingValue(OAuth2AccessTokenReqDTO oAuth2AccessTokenReqDTO) { - - HttpRequestHeader[] httpRequestHeaders = oAuth2AccessTokenReqDTO.getHttpRequestHeaders(); - if (ArrayUtils.isEmpty(httpRequestHeaders)) { - return Optional.empty(); - } - for (HttpRequestHeader httpRequestHeader : httpRequestHeaders) { - if (DPoPConstants.OAUTH_DPOP_HEADER.equalsIgnoreCase(httpRequestHeader.getName())) { - if (ArrayUtils.isEmpty(httpRequestHeader.getValue())) { - return Optional.empty(); - } - - String dpopProof = httpRequestHeader.getValue()[0]; - if (StringUtils.isEmpty(dpopProof)) { - return Optional.empty(); - } - - try { - String thumbprintOfPublicKey = Utils.getThumbprintOfKeyFromDpopProof(dpopProof); - return Optional.of(thumbprintOfPublicKey); - } catch (IdentityOAuth2Exception e) { - return Optional.empty(); - } - } - } - return Optional.empty(); - } - - private String retrieveTokenBindingValueFromDPoPHeader(HttpServletRequest request) throws IdentityOAuth2Exception { - - String dpopProof = request.getHeader(DPoPConstants.OAUTH_DPOP_HEADER); - if (StringUtils.isBlank(dpopProof)) { - return null; - } - - String thumbprintOfPublicKey = Utils.getThumbprintOfKeyFromDpopProof(dpopProof); - if (StringUtils.isBlank(thumbprintOfPublicKey)) { - return null; - } - return thumbprintOfPublicKey; - } - - private boolean validateDPoPHeader(Object request, TokenBinding tokenBinding) throws IdentityOAuth2Exception, - ParseException { - - if (((HttpServletRequest) request).getRequestURI().equals(DPoPConstants.OAUTH_REVOKE_ENDPOINT) && - skipDPoPValidationInRevoke()){ - return true; - } - - if (!((HttpServletRequest) request).getRequestURI().equals(DPoPConstants.OAUTH_REVOKE_ENDPOINT) && - !((HttpServletRequest) request).getHeader(DPoPConstants.AUTHORIZATION_HEADER) - .startsWith(DPoPConstants.OAUTH_DPOP_HEADER)) { - if (log.isDebugEnabled()) { - log.debug("DPoP prefix is not defined correctly in the Authorization header."); - } - return false; - } - String dpopHeader = ((HttpServletRequest) request).getHeader(DPoPConstants.OAUTH_DPOP_HEADER); - - if (StringUtils.isBlank(dpopHeader)) { - if (log.isDebugEnabled()) { - log.debug("DPoP header is empty."); - } - return false; - - } - - String httpMethod = (((HttpServletRequest) request).getMethod()); - String httpUrl = (((HttpServletRequest) request).getRequestURL().toString()); - if (!DPoPHeaderValidator.isValidDPoPProof(httpMethod, httpUrl, dpopHeader)) { - return false; - } - - String thumbprintOfPublicKey = Utils.getThumbprintOfKeyFromDpopProof(dpopHeader); - - if (StringUtils.isBlank(thumbprintOfPublicKey)) { - if (log.isDebugEnabled()) { - log.debug("Thumbprint value of the public key is empty in the DPoP Proof."); - } - return false; - } - - if (!thumbprintOfPublicKey.equalsIgnoreCase(tokenBinding.getBindingValue())) { - if (log.isDebugEnabled()) { - log.debug("Thumbprint value of the public key in the DPoP proof is not equal to binding value" + - " of the responseDTO."); - } - return false; - } - return true; - } - - public String[] getAllGrantTypes() { - - if (supportedGrantTypesSet.isEmpty()) { - synchronized (DPoPBasedTokenBinder.class) { - if (supportedGrantTypesSet.isEmpty()) { - supportedGrantTypesSet = OAuthServerConfiguration.getInstance().getSupportedGrantTypes().keySet(); - } - } - } - return supportedGrantTypesSet.toArray(new String[supportedGrantTypesSet.size()]); - } - - private static boolean skipDPoPValidationInRevoke() { - - Object skipDPoPValidationInRevokeObject = IdentityUtil.readEventListenerProperty - (AbstractIdentityHandler.class.getName(), OauthDPoPInterceptorHandlerProxy.class.getName()) - .getProperties().get(DPoPConstants.SKIP_DPOP_VALIDATION_IN_REVOKE); - - if (skipDPoPValidationInRevokeObject == null){ - return DPoPConstants.DEFAULT_SKIP_DPOP_VALIDATION_IN_REVOKE_VALUE; - } - - String skipDPoPValidationInRevokeValue = skipDPoPValidationInRevokeObject.toString().trim(); - - if (!("true".equals(skipDPoPValidationInRevokeValue) || "false".equals(skipDPoPValidationInRevokeValue))) { - log.info("Configured, skip dpop validation in revoke value is set to an invalid value. Hence the " + - "default value will be used."); - return DPoPConstants.DEFAULT_SKIP_DPOP_VALIDATION_IN_REVOKE_VALUE; - - } - - return Boolean.parseBoolean(skipDPoPValidationInRevokeValue); - } -} diff --git a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/util/Utils.java b/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/util/Utils.java deleted file mode 100644 index 6a879cca..00000000 --- a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/util/Utils.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com). - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.dpop.util; - -import com.nimbusds.jose.JOSEException; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jose.JWSVerifier; -import com.nimbusds.jose.crypto.ECDSAVerifier; -import com.nimbusds.jose.crypto.RSASSAVerifier; -import com.nimbusds.jose.jwk.ECKey; -import com.nimbusds.jose.jwk.JWK; -import com.nimbusds.jose.jwk.RSAKey; -import com.nimbusds.jwt.SignedJWT; -import org.apache.axiom.om.OMElement; -import org.apache.commons.lang.StringUtils; -import org.wso2.carbon.database.utils.jdbc.JdbcTemplate; -import org.wso2.carbon.identity.core.persistence.UmPersistenceManager; -import org.wso2.carbon.identity.core.util.IdentityConfigParser; -import org.wso2.carbon.identity.core.util.IdentityCoreConstants; -import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil; -import org.wso2.carbon.identity.dpop.constant.DPoPConstants; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2ClientException; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; - -import java.security.interfaces.ECPublicKey; -import java.security.interfaces.RSAPublicKey; -import java.text.ParseException; -import javax.xml.namespace.QName; - -/** - * This class provides utility functions for dpop implementation. - */ -public class Utils { - - public static JdbcTemplate getNewTemplate() { - - return new JdbcTemplate(IdentityDatabaseUtil.getDataSource()); - } - - /** - * Get thumbprint value from the jwk header parameter in the dpop proof. - * - * @param dPopProof DPoP proof header. - * @return Thumbprint value. - * @throws IdentityOAuth2ClientException Error while getting the thumbprint value. - */ - public static String getThumbprintOfKeyFromDpopProof(String dPopProof) throws IdentityOAuth2Exception { - - try { - SignedJWT signedJwt = SignedJWT.parse(dPopProof); - JWSHeader header = signedJwt.getHeader(); - return getKeyThumbprintOfKey(header.getJWK().toString(), signedJwt); - } catch (ParseException | JOSEException e) { - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_ERROR); - } - } - - private static String getKeyThumbprintOfKey(String jwk, SignedJWT signedJwt) - throws ParseException, JOSEException { - - JWK parseJwk = JWK.parse(jwk); - boolean validSignature; - if (DPoPConstants.ECDSA_ENCRYPTION.equalsIgnoreCase(String.valueOf(parseJwk.getKeyType()))) { - ECKey ecKey = (ECKey) parseJwk; - ECPublicKey ecPublicKey = ecKey.toECPublicKey(); - validSignature = verifySignatureWithPublicKey(new ECDSAVerifier(ecPublicKey), signedJwt); - if (validSignature) { - return computeThumbprintOfECKey(ecKey); - } - } else if (DPoPConstants.RSA_ENCRYPTION.equalsIgnoreCase(String.valueOf(parseJwk.getKeyType()))) { - RSAKey rsaKey = (RSAKey) parseJwk; - RSAPublicKey rsaPublicKey = rsaKey.toRSAPublicKey(); - validSignature = verifySignatureWithPublicKey(new RSASSAVerifier(rsaPublicKey), signedJwt); - if (validSignature) { - return computeThumbprintOfRSAKey(rsaKey); - } - } - return StringUtils.EMPTY; - } - - private static String computeThumbprintOfRSAKey(RSAKey rsaKey) throws JOSEException { - - return rsaKey.computeThumbprint().toString(); - } - - private static String computeThumbprintOfECKey(ECKey ecKey) throws JOSEException { - - return ecKey.computeThumbprint().toString(); - } - - private static boolean verifySignatureWithPublicKey(JWSVerifier jwsVerifier, SignedJWT signedJwt) - throws JOSEException { - - return signedJwt.verify(jwsVerifier); - } -} diff --git a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/validators/DPoPHeaderValidator.java b/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/validators/DPoPHeaderValidator.java deleted file mode 100644 index 91c4bbbf..00000000 --- a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/validators/DPoPHeaderValidator.java +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com). - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.dpop.validators; - -import com.nimbusds.jose.JWSAlgorithm; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jose.jwk.JWK; -import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.SignedJWT; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.simple.JSONObject; -import org.wso2.carbon.identity.core.handler.AbstractIdentityHandler; -import org.wso2.carbon.identity.core.util.IdentityUtil; -import org.wso2.carbon.identity.dpop.constant.DPoPConstants; -import org.wso2.carbon.identity.dpop.listener.OauthDPoPInterceptorHandlerProxy; -import org.wso2.carbon.identity.dpop.util.Utils; -import org.wso2.carbon.identity.oauth.common.exception.InvalidOAuthClientException; -import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2ClientException; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; -import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO; -import org.wso2.carbon.identity.oauth2.model.HttpRequestHeader; -import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext; -import org.wso2.carbon.identity.oauth2.token.bindings.TokenBinding; -import org.wso2.carbon.identity.oauth2.util.OAuth2Util; - -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.sql.Timestamp; -import java.text.ParseException; -import java.util.Base64; -import java.util.Date; - -import javax.servlet.http.HttpServletRequest; - -/** - * DPoP Header validator. - */ -public class DPoPHeaderValidator { - - static final Log log = LogFactory.getLog(DPoPHeaderValidator.class); - - /** - * Extract DPoP header from the headers. - * - * @param tokReqMsgCtx Message context of token request. - * @return DPoP header. - */ - public static String getDPoPHeader(OAuthTokenReqMessageContext tokReqMsgCtx) throws IdentityOAuth2ClientException { - - HttpRequestHeader[] httpRequestHeaders = tokReqMsgCtx.getOauth2AccessTokenReqDTO().getHttpRequestHeaders(); - if (httpRequestHeaders != null) { - for (HttpRequestHeader header : httpRequestHeaders) { - if (header != null && DPoPConstants.OAUTH_DPOP_HEADER.equalsIgnoreCase(header.getName())) { - if (ArrayUtils.isNotEmpty(header.getValue())){ - if (header.getValue().length > 1) { - String error = "Exception occurred while extracting the DPoP proof header: Request contains multiple DPoP headers."; - log.error(error); - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, error); - } - return header.getValue()[0]; - } - return null; - } - } - } - return StringUtils.EMPTY; - } - - /** - * Get Oauth application Access token binding type. - * - * @param consumerKey Consumer Key. - * @return Access token binding type of the oauth application. - * @throws InvalidOAuthClientException Error while getting the Oauth application information. - * @throws IdentityOAuth2Exception Error while getting the Oauth application information. - */ - public static String getApplicationBindingType(String consumerKey) throws - IdentityOAuth2Exception, InvalidOAuthClientException { - - OAuthAppDO oauthAppDO = OAuth2Util.getAppInformationByClientId(consumerKey); - return oauthAppDO.getTokenBindingType(); - } - - /** - * Validate dpop proof header. - * - * @param httpMethod HTTP method of the request. - * @param httpURL HTTP URL of the request, - * @param dPoPProof DPoP header of the request. - * @return - * @throws ParseException Error while retrieving the signedJwt. - * @throws IdentityOAuth2Exception Error while validating the dpop proof. - */ - public static boolean isValidDPoPProof(String httpMethod, String httpURL, String dPoPProof) - throws ParseException, IdentityOAuth2Exception { - - SignedJWT signedJwt = SignedJWT.parse(dPoPProof); - JWSHeader header = signedJwt.getHeader(); - - return validateDPoPPayload(httpMethod, httpURL, signedJwt.getJWTClaimsSet()) && validateDPoPHeader(header); - } - - /** - * Validate dpop proof header. - * - * @param httpMethod HTTP method of the request. - * @param httpURL HTTP URL of the request, - * @param dPoPProof DPoP header of the request. - * @param token Access token / Refresh token. - * @return - * @throws ParseException Error while retrieving the signedJwt. - * @throws IdentityOAuth2Exception Error while validating the dpop proof. - */ - public static boolean isValidDPoPProof(String httpMethod, String httpURL, String dPoPProof, String token) - throws ParseException, IdentityOAuth2Exception { - - SignedJWT signedJwt = SignedJWT.parse(dPoPProof); - JWSHeader header = signedJwt.getHeader(); - - return validateDPoPPayload(httpMethod, httpURL, signedJwt.getJWTClaimsSet(), token) && validateDPoPHeader(header) ; - } - - /** - * Set token binder information if dpop proof is valid. - * - * @param dPoPProof DPoP proof header. - * @param tokenReqDTO Token request dto. - * @param tokReqMsgCtx Message context of token request. - * @return - * @throws IdentityOAuth2Exception Error while validating the dpop proof. - */ - public static boolean isValidDPoP(String dPoPProof, OAuth2AccessTokenReqDTO tokenReqDTO, - OAuthTokenReqMessageContext tokReqMsgCtx) throws IdentityOAuth2Exception { - - try { - HttpServletRequest request = tokenReqDTO.getHttpServletRequestWrapper(); - String httpMethod = request.getMethod(); - String httpURL = request.getRequestURL().toString(); - if (isValidDPoPProof(httpMethod, httpURL, dPoPProof)) { - String thumbprint = Utils.getThumbprintOfKeyFromDpopProof(dPoPProof); - if (StringUtils.isNotBlank(thumbprint)) { - TokenBinding tokenBinding = new TokenBinding(); - tokenBinding.setBindingType(DPoPConstants.DPOP_TOKEN_TYPE); - tokenBinding.setBindingValue(thumbprint); - tokenBinding.setBindingReference(DigestUtils.md5Hex(thumbprint)); - tokReqMsgCtx.setTokenBinding(tokenBinding); - setCnFValue(tokReqMsgCtx, tokenBinding.getBindingValue()); - return true; - } - } - } catch (ParseException e) { - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_ERROR); - } - return false; - } - - private static boolean validateDPoPHeader(JWSHeader header) throws IdentityOAuth2Exception { - - return checkJwk(header) && checkAlg(header) && checkHeaderType(header); - } - - //Authorization server side validator without "ath" claim validation - private static boolean validateDPoPPayload(String httpMethod, String httpURL, JWTClaimsSet jwtClaimsSet) - throws IdentityOAuth2Exception { - - return checkJwtClaimSet(jwtClaimsSet) && checkDPoPHeaderValidity(jwtClaimsSet) && checkJti(jwtClaimsSet) && - checkHTTPMethod(httpMethod, jwtClaimsSet) && checkHTTPURI(httpURL, jwtClaimsSet); - } - - //Resource server side validator with "ath" claim validation - private static boolean validateDPoPPayload(String httpMethod, String httpURL, JWTClaimsSet jwtClaimsSet, String token) - throws IdentityOAuth2Exception { - - return checkJwtClaimSet(jwtClaimsSet) && checkDPoPHeaderValidity(jwtClaimsSet) && checkJti(jwtClaimsSet) && - checkHTTPMethod(httpMethod, jwtClaimsSet) && checkHTTPURI(httpURL, jwtClaimsSet) && checkAth(token, jwtClaimsSet); - } - - private static boolean checkJwk(JWSHeader header) throws IdentityOAuth2ClientException { - - JWK jwk = header.getJWK(); - if (jwk != null) { - if (!header.getJWK().isPrivate()) { - return true; - } - if (log.isDebugEnabled()) { - log.debug("Private key is used in the DPoP Proof header."); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_ERROR); - } - if (log.isDebugEnabled()) { - log.debug("'jwk' is not presented in the DPoP Proof header"); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_ERROR); - } - - private static boolean checkAlg(JWSHeader header) throws IdentityOAuth2ClientException { - - JWSAlgorithm algorithm = header.getAlgorithm(); - if (algorithm == null) { - if (log.isDebugEnabled()) { - log.debug("'algorithm' is not presented in the DPoP Proof header"); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_ERROR); - } - return true; - } - - private static boolean checkHeaderType(JWSHeader header) throws IdentityOAuth2ClientException { - - if (!DPoPConstants.DPOP_JWT_TYPE.equalsIgnoreCase(header.getType().toString())) { - if (log.isDebugEnabled()) { - log.debug(" typ field value in the DPoP Proof header is not equal to 'dpop+jwt'"); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_ERROR); - } - - return true; - } - - private static boolean checkJwtClaimSet(JWTClaimsSet jwtClaimsSet) throws IdentityOAuth2ClientException { - - if (jwtClaimsSet == null) { - if (log.isDebugEnabled()) { - log.debug("'jwtClaimsSet' is missing in the body of a DPoP proof."); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_ERROR); - } - return true; - } - - private static boolean checkDPoPHeaderValidity(JWTClaimsSet jwtClaimsSet) throws IdentityOAuth2ClientException { - - Timestamp currentTimestamp = new Timestamp(new Date().getTime()); - Date issuedAt = (Date) jwtClaimsSet.getClaim(DPoPConstants.DPOP_ISSUED_AT); - if (issuedAt == null) { - if (log.isDebugEnabled()) { - log.debug("DPoP Proof missing the 'iat' field."); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_ERROR); - } - boolean isExpired = (currentTimestamp.getTime() - issuedAt.getTime()) > getDPoPValidityPeriod(); - if (isExpired) { - String error = "Expired DPoP Proof"; - if (log.isDebugEnabled()) { - log.debug(error); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, error); - } - return true; - } - - private static boolean checkJti(JWTClaimsSet jwtClaimsSet) throws IdentityOAuth2ClientException { - - if (!jwtClaimsSet.getClaims().containsKey(DPoPConstants.JTI)) { - if (log.isDebugEnabled()) { - log.debug("'jti' is missing in the 'jwtClaimsSet' of the DPoP proof body."); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_ERROR); - } - return true; - } - - private static boolean checkHTTPMethod(String httpMethod, JWTClaimsSet jwtClaimsSet) throws IdentityOAuth2ClientException { - - Object dPoPHttpMethod = jwtClaimsSet.getClaim(DPoPConstants.DPOP_HTTP_METHOD); - - // Check if the DPoP proof HTTP method is empty. - if (dPoPHttpMethod == null) { - if (log.isDebugEnabled()) { - log.debug("DPoP Proof HTTP method empty."); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_ERROR); - } - - // Validate if the DPoP proof HTTP method matches that of the request. - if (!httpMethod.equalsIgnoreCase(dPoPHttpMethod.toString())) { - if (log.isDebugEnabled()) { - log.debug("DPoP Proof HTTP method mismatch."); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_ERROR); - } - - return true; - } - - private static boolean checkHTTPURI(String httpUrl, JWTClaimsSet jwtClaimsSet) throws IdentityOAuth2ClientException { - - Object dPoPContextPath = jwtClaimsSet.getClaim(DPoPConstants.DPOP_HTTP_URI); - - if (dPoPContextPath == null) { - if (log.isDebugEnabled()) { - log.debug("DPoP Proof context path empty."); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_ERROR); - } - - // Validate if the DPoP proof HTTP URI matches that of the request. - if (!httpUrl.equalsIgnoreCase(dPoPContextPath.toString())) { - if (log.isDebugEnabled()) { - log.debug("DPoP Proof context path mismatch."); - } - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_ERROR); - } - return true; - } - - private static int getDPoPValidityPeriod() { - Object validityPeriodObject = IdentityUtil.readEventListenerProperty - (AbstractIdentityHandler.class.getName(), OauthDPoPInterceptorHandlerProxy.class.getName()) - .getProperties().get(DPoPConstants.VALIDITY_PERIOD); - - if (validityPeriodObject == null){ - return DPoPConstants.DEFAULT_HEADER_VALIDITY; - } - - String validityPeriodValue = validityPeriodObject.toString(); - - if (StringUtils.isNotBlank(validityPeriodValue)) { - if (StringUtils.isNumeric(validityPeriodValue)) { - return Integer.parseInt(validityPeriodValue.trim()) * 1000; - } - log.info("Configured dpop validity period is set to an invalid value. Hence the default validity " + - "period will be used."); - return DPoPConstants.DEFAULT_HEADER_VALIDITY; - } - return DPoPConstants.DEFAULT_HEADER_VALIDITY; - } - - private static void setCnFValue(OAuthTokenReqMessageContext tokReqMsgCtx, String tokenBindingValue) { - - JSONObject obj = new JSONObject(); - obj.put(DPoPConstants.JWK_THUMBPRINT, tokenBindingValue); - tokReqMsgCtx.addProperty(DPoPConstants.CNF, obj); - } - - private static boolean checkAth(String token, JWTClaimsSet jwtClaimsSet) throws IdentityOAuth2ClientException { - - Object ath = jwtClaimsSet.getClaim(DPoPConstants.DPOP_ACCESS_TOKEN_HASH); - if (ath == null) { - log.error("DPoP Proof access token hash is empty."); - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_ERROR); - } - MessageDigest digest = null; - try { - digest = MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - log.error("Error while getting the SHA-256 algorithm.", e); - } - byte[] hashBytes = digest.digest(token.getBytes(StandardCharsets.US_ASCII)); - // Encode the hash using base64url encoding - String hashFromToken = Base64.getUrlEncoder().withoutPadding().encodeToString(hashBytes); - if (!StringUtils.equals(ath.toString(), hashFromToken)) { - log.error("DPoP Proof access token hash mismatch."); - throw new IdentityOAuth2ClientException(DPoPConstants.INVALID_DPOP_PROOF, DPoPConstants.INVALID_DPOP_PROOF); - } - return true; - } -} diff --git a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/validators/DPoPTokenValidator.java b/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/validators/DPoPTokenValidator.java deleted file mode 100644 index f6d3c9c5..00000000 --- a/component/org.wso2.carbon.identity.dpop/src/main/java/org/wso2/carbon/identity/dpop/validators/DPoPTokenValidator.java +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com). - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.dpop.validators; - -import com.nimbusds.jose.JOSEException; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jose.JWSVerifier; -import com.nimbusds.jose.crypto.RSASSAVerifier; -import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.SignedJWT; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.context.PrivilegedCarbonContext; -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.util.IdentityApplicationConstants; -import org.wso2.carbon.identity.application.common.util.IdentityApplicationManagementUtil; -import org.wso2.carbon.identity.dpop.constant.DPoPConstants; -import org.wso2.carbon.identity.dpop.util.Utils; -import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; -import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationRequestDTO; -import org.wso2.carbon.identity.oauth2.model.AccessTokenDO; -import org.wso2.carbon.identity.oauth2.validators.OAuth2TokenValidationMessageContext; -import org.wso2.carbon.identity.oauth2.validators.OAuth2TokenValidator; -import org.wso2.carbon.idp.mgt.IdentityProviderManagementException; -import org.wso2.carbon.idp.mgt.IdentityProviderManager; -import org.wso2.carbon.utils.multitenancy.MultitenantConstants; - -import java.security.PublicKey; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.security.interfaces.RSAPublicKey; -import java.text.ParseException; -import java.util.Date; -import java.util.List; - -/** - * DPoP token validator. - */ -public class DPoPTokenValidator implements OAuth2TokenValidator { - - private static final String ALGO_PREFIX = "RS"; - private static final String DOT_SEPARATOR = "."; - private static final Log log = LogFactory.getLog(DPoPTokenValidator.class); - private static final String OIDC_IDP_ENTITY_ID = "IdPEntityId"; - private static final String ACCESS_TOKEN_DO = "AccessTokenDO"; - - @Override - public boolean validateAccessDelegation(OAuth2TokenValidationMessageContext messageContext) { - - return true; - } - - @Override - public boolean validateScope(OAuth2TokenValidationMessageContext messageContext) { - - return true; - } - - @Override - public boolean validateAccessToken(OAuth2TokenValidationMessageContext validationReqDTO) - throws IdentityOAuth2Exception { - - try { - if (!validateDPoP(validationReqDTO)) { - return false; - } - if (!isJWT(validationReqDTO.getRequestDTO().getAccessToken().getIdentifier())) { - return true; - } - SignedJWT signedJWT = getSignedJWT(validationReqDTO); - JWTClaimsSet claimsSet = signedJWT.getJWTClaimsSet(); - - if (claimsSet == null) { - throw new IdentityOAuth2Exception("Claim values are empty in the given Token."); - } - - validateRequiredFields(validationReqDTO, claimsSet); - - IdentityProvider identityProvider = getResidentIDPForIssuer(claimsSet.getIssuer()); - - if (!validateSignature(signedJWT, identityProvider)) { - return false; - } - if (!checkExpirationTime(claimsSet.getExpirationTime())) { - return false; - } - - checkNotBeforeTime(claimsSet.getNotBeforeTime()); - } catch (JOSEException | ParseException e) { - throw new IdentityOAuth2Exception("Error while validating Token.", e); - } - return true; - } - - @Override - public String getTokenType() { - - return DPoPConstants.DPOP_TOKEN_TYPE; - } - - private SignedJWT getSignedJWT(OAuth2TokenValidationMessageContext validationReqDTO) throws ParseException { - - return SignedJWT.parse(validationReqDTO.getRequestDTO().getAccessToken().getIdentifier()); - } - - private boolean validateRequiredFields(OAuth2TokenValidationMessageContext validationReqDTO, JWTClaimsSet claimsSet) - throws IdentityOAuth2Exception, ParseException { - - AccessTokenDO accessTokenDO = (AccessTokenDO) validationReqDTO.getProperty(ACCESS_TOKEN_DO); - String bindingValue = accessTokenDO.getTokenBinding().getBindingValue(); - String subject = resolveSubject(claimsSet); - - if (StringUtils.isBlank(String.valueOf(claimsSet.getClaims().containsKey(DPoPConstants.CNF))) - && StringUtils.isBlank(claimsSet.getClaim(DPoPConstants.CNF).toString())) { - throw new IdentityOAuth2Exception("Mandatory field cnf is empty in the given Token."); - } - - String jkt = claimsSet.getJSONObjectClaim(DPoPConstants.CNF).getAsString(DPoPConstants.JWK_THUMBPRINT); - if (StringUtils.isBlank(jkt) || !bindingValue.equalsIgnoreCase(jkt)) { - throw new IdentityOAuth2Exception("Mandatory field jkt is empty or invalid in the cnf."); - } - - String jti = claimsSet.getJWTID(); - List audience = claimsSet.getAudience(); - if (StringUtils.isEmpty(claimsSet.getIssuer()) || StringUtils.isEmpty(subject) || - claimsSet.getExpirationTime() == null || audience == null || jti == null) { - throw new IdentityOAuth2Exception("Mandatory fields(Issuer, Subject, Expiration time," + - " jtl or Audience) are empty in the given Token."); - } - return true; - } - - private String resolveSubject(JWTClaimsSet claimsSet) { - - return claimsSet.getSubject(); - } - - /** - * The default implementation resolves one certificate to Identity Provider and ignores the JWT header. - * Override this method, to resolve and enforce the certificate in any other way - * such as x5t attribute of the header. - * - * @param header The JWT header. Some of the x attributes may provide certificate information. - * @param idp The identity provider, if you need it. - * @return the resolved X509 Certificate, to be used to validate the JWT signature. - * @throws IdentityOAuth2Exception something goes wrong. - */ - protected X509Certificate resolveSignerCertificate(JWSHeader header, - IdentityProvider idp) throws IdentityOAuth2Exception { - - X509Certificate x509Certificate; - String tenantDomain = getTenantDomain(); - try { - x509Certificate = (X509Certificate) IdentityApplicationManagementUtil - .decodeCertificate(idp.getCertificate()); - } catch (CertificateException e) { - throw new IdentityOAuth2Exception("Error occurred while decoding public certificate of Identity Provider " - + idp.getIdentityProviderName() + " for tenant domain " + tenantDomain, e); - } - return x509Certificate; - } - - private IdentityProvider getResidentIDPForIssuer(String jwtIssuer) throws IdentityOAuth2Exception { - - String tenantDomain = getTenantDomain(); - String issuer = StringUtils.EMPTY; - IdentityProvider residentIdentityProvider; - try { - residentIdentityProvider = IdentityProviderManager.getInstance().getResidentIdP(tenantDomain); - } catch (IdentityProviderManagementException e) { - String errorMsg = - String.format("Error while getting Resident Identity Provider of '%s' tenant.", tenantDomain); - throw new IdentityOAuth2Exception(errorMsg, e); - } - FederatedAuthenticatorConfig[] fedAuthnConfigs = residentIdentityProvider.getFederatedAuthenticatorConfigs(); - FederatedAuthenticatorConfig oauthAuthenticatorConfig = - IdentityApplicationManagementUtil.getFederatedAuthenticator(fedAuthnConfigs, - IdentityApplicationConstants.Authenticator.OIDC.NAME); - if (oauthAuthenticatorConfig != null) { - issuer = IdentityApplicationManagementUtil.getProperty(oauthAuthenticatorConfig.getProperties(), - OIDC_IDP_ENTITY_ID).getValue(); - } - - if (!jwtIssuer.equals(issuer)) { - throw new IdentityOAuth2Exception("No Registered IDP found for the token with issuer name : " + jwtIssuer); - } - return residentIdentityProvider; - } - - private boolean validateSignature(SignedJWT signedJWT, IdentityProvider idp) - throws JOSEException, IdentityOAuth2Exception { - - JWSVerifier verifier = null; - JWSHeader header = signedJWT.getHeader(); - X509Certificate x509Certificate = resolveSignerCertificate(header, idp); - if (x509Certificate == null) { - throw new IdentityOAuth2Exception("Unable to locate certificate for Identity Provider: " + idp - .getDisplayName()); - } - - String alg = signedJWT.getHeader().getAlgorithm().getName(); - if (StringUtils.isEmpty(alg)) { - throw new IdentityOAuth2Exception("Algorithm must not be null."); - - } else { - if (log.isDebugEnabled()) { - log.debug("Signature Algorithm found in the Token Header: " + alg); - } - if (alg.indexOf(ALGO_PREFIX) == 0) { - // At this point 'x509Certificate' will never be null. - PublicKey publicKey = x509Certificate.getPublicKey(); - if (publicKey instanceof RSAPublicKey) { - verifier = new RSASSAVerifier((RSAPublicKey) publicKey); - } else { - throw new IdentityOAuth2Exception("Public key is not an RSA public key."); - } - } else { - if (log.isDebugEnabled()) { - log.debug("Signature Algorithm not supported yet: " + alg); - } - } - if (verifier == null) { - throw new IdentityOAuth2Exception("Could not create a signature verifier for algorithm type: " + alg); - } - } - - boolean isValid = signedJWT.verify(verifier); - if (log.isDebugEnabled()) { - log.debug("Signature verified: " + isValid); - } - return isValid; - } - - private boolean checkExpirationTime(Date expirationTime) { - - long timeStampSkewMillis = OAuthServerConfiguration.getInstance().getTimeStampSkewInSeconds() * 1000; - long expirationTimeInMillis = expirationTime.getTime(); - long currentTimeInMillis = System.currentTimeMillis(); - if ((currentTimeInMillis + timeStampSkewMillis) > expirationTimeInMillis) { - if (log.isDebugEnabled()) { - log.debug("Token is expired." + - ", Expiration Time(ms) : " + expirationTimeInMillis + - ", TimeStamp Skew : " + timeStampSkewMillis + - ", Current Time : " + currentTimeInMillis + ". Token Rejected and validation terminated."); - } - return false; - } - - if (log.isDebugEnabled()) { - log.debug("Expiration Time(exp) of Token was validated successfully."); - } - return true; - } - - private boolean checkNotBeforeTime(Date notBeforeTime) throws IdentityOAuth2Exception { - - if (notBeforeTime != null) { - long timeStampSkewMillis = OAuthServerConfiguration.getInstance().getTimeStampSkewInSeconds() * 1000; - long notBeforeTimeMillis = notBeforeTime.getTime(); - long currentTimeInMillis = System.currentTimeMillis(); - if (currentTimeInMillis + timeStampSkewMillis < notBeforeTimeMillis) { - if (log.isDebugEnabled()) { - log.debug("Token is used before Not_Before_Time." + - ", Not Before Time(ms) : " + notBeforeTimeMillis + - ", TimeStamp Skew : " + timeStampSkewMillis + - ", Current Time : " + currentTimeInMillis + ". Token Rejected and validation terminated."); - } - throw new IdentityOAuth2Exception("Token is used before Not_Before_Time."); - } - if (log.isDebugEnabled()) { - log.debug("Not Before Time(nbf) of Token was validated successfully."); - } - } - return true; - } - - private String getTenantDomain() { - - String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); - if (StringUtils.isEmpty(tenantDomain)) { - tenantDomain = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME; - } - return tenantDomain; - } - - /** - * Return true if the token identifier is JWT. - * - * @param tokenIdentifier String JWT token identifier. - * @return true for a JWT token. - */ - private boolean isJWT(String tokenIdentifier) { - // JWT token contains 3 base64 encoded components separated by periods. - return StringUtils.countMatches(tokenIdentifier, DOT_SEPARATOR) == 2; - } - - private boolean validateDPoP(OAuth2TokenValidationMessageContext validationReqDTO) throws IdentityOAuth2Exception, - ParseException { - - AccessTokenDO accessTokenDO = (AccessTokenDO) validationReqDTO.getProperty(ACCESS_TOKEN_DO); - if (accessTokenDO != null && accessTokenDO.getTokenBinding() != null && - DPoPConstants.OAUTH_DPOP_HEADER.equalsIgnoreCase(accessTokenDO.getTokenBinding().getBindingType())) { - String dpopProof = getResourceFromMessageContext(validationReqDTO, DPoPConstants.OAUTH_DPOP_HEADER); - String httpMethod = getResourceFromMessageContext(validationReqDTO, DPoPConstants.HTTP_METHOD); - String httpUrl = getResourceFromMessageContext(validationReqDTO, DPoPConstants.HTTP_URL); - - if (StringUtils.isBlank(dpopProof)) { - if (log.isDebugEnabled()) { - log.debug("DPoP header is empty."); - } - return false; - } - - if (!DPoPHeaderValidator.isValidDPoPProof(httpMethod, httpUrl, dpopProof, validationReqDTO.getRequestDTO().getAccessToken().getIdentifier())) { - return false; - } - - String thumbprintOfPublicKey = Utils.getThumbprintOfKeyFromDpopProof(dpopProof); - - if (StringUtils.isBlank(thumbprintOfPublicKey)) { - if (log.isDebugEnabled()) { - log.debug("Thumbprint value of the public key is empty in the DPoP Proof."); - } - return false; - } - - if (!thumbprintOfPublicKey.equalsIgnoreCase(accessTokenDO.getTokenBinding().getBindingValue())) { - if (log.isDebugEnabled()) { - log.debug("Thumbprint value of the public key in the DPoP proof is not equal to binding value" + - " of the responseDTO."); - } - return false; - } - return true; - } - return false; - } - - /** - * Extract the passed parameter value from the access token validation request message - * - * @param messageContext Message context of the token validation request - * @return resource - */ - private String getResourceFromMessageContext(OAuth2TokenValidationMessageContext messageContext, String param) { - - String resource = null; - if (messageContext.getRequestDTO().getContext() != null) { - // Iterate the array of context params to find the 'resource' context param. - for (OAuth2TokenValidationRequestDTO.TokenValidationContextParam resourceParam : - messageContext.getRequestDTO().getContext()) { - // If the context param is the resource that is being accessed - if (resourceParam != null && param.equals(resourceParam.getKey())) { - resource = resourceParam.getValue(); - break; - } - } - } - return resource; - } -} diff --git a/pom.xml b/pom.xml index 9b6252c9..d307025d 100644 --- a/pom.xml +++ b/pom.xml @@ -31,15 +31,12 @@ http://wso2.org - component/client-handler - component/org.wso2.carbon.identity.oauth2.token.handler.clientauth.mutualtls component/org.wso2.carbon.identity.oauth2.token.handler.clientauth.tlswithidsecret component/org.wso2.carbon.identity.oauth2.validators.xacml features/org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.feature features/org.wso2.carbon.identity.oauth2.validators.xacml.server.feature component/org.wso2.carbon.identity.oauth2.clientauth.privilegeduser - component/org.wso2.carbon.identity.dpop