Skip to content

Commit 0703924

Browse files
committed
Change default token type of portal apps to JWT.
1 parent 84315d1 commit 0703924

File tree

3 files changed

+119
-22
lines changed

3 files changed

+119
-22
lines changed

components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java

+20
Original file line numberDiff line numberDiff line change
@@ -8944,6 +8944,26 @@ private static String[] claimMappingtoClaimURIString(ClaimMapping[] claims) {
89448944
return temp;
89458945
}
89468946

8947+
/**
8948+
* Helper method to retrieve default key manager configuration for the given organization.
8949+
*
8950+
* @param organization Organization
8951+
* @return KeyManagerConfigurationDTO
8952+
* @throws APIManagementException if an error occurs while retrieving latest default key manager configs
8953+
*/
8954+
public static KeyManagerConfigurationDTO getDefaultKeyManagerConfiguration(String organization) throws
8955+
APIManagementException {
8956+
8957+
KeyManagerConfigurationDTO keyManagerConfiguration =
8958+
ApiMgtDAO.getInstance().getKeyManagerConfigurationByName(organization,
8959+
APIConstants.KeyManager.DEFAULT_KEY_MANAGER);
8960+
if (keyManagerConfiguration != null) {
8961+
APIUtil.getAndSetDefaultKeyManagerConfiguration(keyManagerConfiguration);
8962+
return keyManagerConfiguration;
8963+
}
8964+
return null;
8965+
}
8966+
89478967
public static KeyManagerConfigurationDTO getAndSetDefaultKeyManagerConfiguration(
89488968
KeyManagerConfigurationDTO keyManagerConfigurationDTO) throws APIManagementException {
89498969

components/apimgt/org.wso2.carbon.apimgt.rest.api.dcr/src/main/java/org/wso2/carbon/apimgt/rest/api/dcr/web/impl/RegistrationServiceImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ public Response register(RegistrationProfile profile) {
144144
}
145145
}
146146

147-
String tokenType = APIConstants.DEFAULT_TOKEN_TYPE;
147+
String tokenType = APIConstants.JWT;
148148
String profileTokenType = profile.getTokenType();
149149
if (StringUtils.isNotEmpty(profileTokenType)) {
150150
tokenType = profileTokenType;

components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthJwtAuthenticatorImpl.java

+98-21
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,15 @@
2626
import org.apache.cxf.message.Message;
2727
import org.wso2.carbon.apimgt.api.APIManagementException;
2828
import org.wso2.carbon.apimgt.api.OAuthTokenInfo;
29+
import org.wso2.carbon.apimgt.api.dto.KeyManagerConfigurationDTO;
2930
import org.wso2.carbon.apimgt.common.gateway.constants.JWTConstants;
3031
import org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo;
3132
import org.wso2.carbon.apimgt.common.gateway.dto.TokenIssuerDto;
3233
import org.wso2.carbon.apimgt.impl.APIConstants;
3334
import org.wso2.carbon.apimgt.impl.APIConstants.JwtTokenConstants;
3435
import org.wso2.carbon.apimgt.impl.RESTAPICacheConfiguration;
36+
import org.wso2.carbon.apimgt.impl.dto.KeyManagerDto;
37+
import org.wso2.carbon.apimgt.impl.factory.KeyManagerHolder;
3538
import org.wso2.carbon.apimgt.impl.jwt.JWTValidator;
3639
import org.wso2.carbon.apimgt.impl.jwt.SignedJWTInfo;
3740
import org.wso2.carbon.apimgt.impl.utils.APIUtil;
@@ -52,12 +55,8 @@
5255
import java.net.URL;
5356
import java.text.ParseException;
5457
import java.util.Date;
55-
import java.util.HashMap;
56-
import java.util.List;
5758
import java.util.Map;
5859

59-
import static org.wso2.carbon.apimgt.rest.api.common.APIMConfigUtil.getRestApiJWTAuthAudiences;
60-
6160
/**
6261
* This OAuthJwtAuthenticatorImpl class specifically implemented for API Manager store and publisher rest APIs'
6362
* JWT based authentication.
@@ -223,10 +222,11 @@ private JWTValidationInfo validateJWTToken(SignedJWTInfo signedJWTInfo, String j
223222

224223
JWTValidationInfo jwtValidationInfo;
225224
String issuer = signedJWTInfo.getJwtClaimsSet().getIssuer();
225+
String subject = signedJWTInfo.getJwtClaimsSet().getSubject();
226226

227227
if (StringUtils.isNotEmpty(issuer)) {
228228
//validate Issuer
229-
if (tokenIssuers != null && tokenIssuers.containsKey(issuer)) {
229+
if (tokenIssuers != null && validateIssuer(subject, issuer, maskedToken)) {
230230
if (isRESTApiTokenCacheEnabled) {
231231
JWTValidationInfo tempJWTValidationInfo = (JWTValidationInfo) getRESTAPITokenCache().get(jti);
232232
if (tempJWTValidationInfo != null) {
@@ -256,27 +256,38 @@ private JWTValidationInfo validateJWTToken(SignedJWTInfo signedJWTInfo, String j
256256
}
257257
}
258258
//info not in cache. validate signature and exp
259-
JWTValidator jwtValidator = APIMConfigUtil.getJWTValidatorMap().get(issuer);
260-
jwtValidationInfo = jwtValidator.validateToken(signedJWTInfo);
261-
if (jwtValidationInfo.isValid()) {
262-
//valid token
263-
if (isRESTApiTokenCacheEnabled) {
264-
getRESTAPITokenCache().put(jti, jwtValidationInfo);
259+
JWTValidator jwtValidator = getJWTValidator(issuer, subject, maskedToken);
260+
if (jwtValidator != null) {
261+
jwtValidationInfo = jwtValidator.validateToken(signedJWTInfo);
262+
if (jwtValidationInfo.isValid()) {
263+
//valid token
264+
if (isRESTApiTokenCacheEnabled) {
265+
getRESTAPITokenCache().put(jti, jwtValidationInfo);
266+
}
267+
} else {
268+
//put in invalid cache
269+
if (isRESTApiTokenCacheEnabled) {
270+
getRESTAPIInvalidTokenCache().put(jti, jwtValidationInfo);
271+
}
272+
//invalid credentials : 900901 error code
273+
log.error("JWT token validation failed. Reason: Invalid Credentials. " +
274+
"Make sure you have provided the correct security credentials in the token :"
275+
+ maskedToken);
265276
}
266277
} else {
267-
//put in invalid cache
268-
if (isRESTApiTokenCacheEnabled) {
269-
getRESTAPIInvalidTokenCache().put(jti, jwtValidationInfo);
270-
}
271-
//invalid credentials : 900901 error code
272-
log.error("JWT token validation failed. Reason: Invalid Credentials. " +
273-
"Make sure you have provided the correct security credentials in the token :"
274-
+ maskedToken);
278+
log.error("JWT token issuer validation failed. Reason: Cannot find a JWTValidator for the " +
279+
"issuer present in the JWT: " + issuer);
280+
return null;
275281
}
276282
} else {
277283
//invalid issuer. invalid token
278-
log.error("JWT token issuer validation failed. Reason: Issuer present in the JWT (" + issuer
279-
+ ") does not match with the token issuer (" + tokenIssuers.keySet().toString() + ")");
284+
if (tokenIssuers != null) {
285+
log.error("JWT token issuer validation failed. Reason: Issuer present in the JWT (" + issuer
286+
+ ") does not match with the token issuer (" + tokenIssuers.keySet() + ")");
287+
} else {
288+
log.error("JWT token issuer validation failed. Reason: Issuer present in the JWT (" + issuer
289+
+ ") does not match with the token issuer.");
290+
}
280291
return null;
281292
}
282293
} else {
@@ -286,6 +297,72 @@ private JWTValidationInfo validateJWTToken(SignedJWTInfo signedJWTInfo, String j
286297
return jwtValidationInfo;
287298
}
288299

300+
/**
301+
* Get logged-in organization from the sub claim of the token.
302+
*
303+
* @param subject Sub claim value
304+
* @param maskedToken Masked token for logging
305+
* @return Organization
306+
*/
307+
private String getOrganizationFromSubject(String subject, String maskedToken) {
308+
if (subject == null) {
309+
log.error("Subject is not found in the token " + maskedToken);
310+
return null;
311+
}
312+
return MultitenantUtils.getTenantDomain(subject);
313+
}
314+
315+
/**
316+
* Retrieve JWT Validator for the given issuer.
317+
*
318+
* @param issuer Issuer from the token
319+
* @param subject Subject from the token
320+
* @param maskedToken Masked token string for logging
321+
* @return JWTValidator implementation for the given issuer.
322+
*/
323+
private JWTValidator getJWTValidator(String issuer, String subject, String maskedToken) {
324+
325+
JWTValidator jwtValidator = APIMConfigUtil.getJWTValidatorMap().get(issuer);
326+
if (jwtValidator == null) {
327+
String organization = getOrganizationFromSubject(subject, maskedToken);
328+
if (StringUtils.isNotEmpty(issuer) && StringUtils.isNotEmpty(organization)) {
329+
KeyManagerDto keyManagerDto = KeyManagerHolder.getKeyManagerByIssuer(organization, issuer);
330+
if (keyManagerDto != null && keyManagerDto.getJwtValidator() != null) {
331+
jwtValidator = keyManagerDto.getJwtValidator();
332+
}
333+
}
334+
}
335+
return jwtValidator;
336+
}
337+
338+
/**
339+
* Validate issuer in the token against the registered token issuers/default key manager issuer.
340+
*
341+
* @param subject Subject to derive the logged-in organization
342+
* @param tokenIssuer Token issuer from the token
343+
* @param maskedToken Masked token for logging purposes
344+
* @return if issuer validation fails or sucess
345+
* @throws APIManagementException if an error occurs during validation
346+
*/
347+
private boolean validateIssuer(String subject, String tokenIssuer, String maskedToken)
348+
throws APIManagementException {
349+
350+
String organization = getOrganizationFromSubject(subject, maskedToken);
351+
if (tokenIssuers != null && !tokenIssuers.isEmpty()) {
352+
return tokenIssuers.containsKey(tokenIssuer);
353+
}
354+
KeyManagerConfigurationDTO keyManagerConfigurationDTO =
355+
APIUtil.getDefaultKeyManagerConfiguration(organization);
356+
if (keyManagerConfigurationDTO == null) {
357+
//invalid issuer. invalid token
358+
log.error("JWT token issuer validation failed. Reason: Default Key Manager configuration cannot be"
359+
+ " found for the organization: " + organization);
360+
return false;
361+
}
362+
return StringUtils.equals(tokenIssuer, (String) keyManagerConfigurationDTO.getAdditionalProperties()
363+
.get(APIConstants.KeyManager.ISSUER));
364+
}
365+
289366
/**
290367
* Retrieve token issuer details from deployment.toml file.
291368
*

0 commit comments

Comments
 (0)