|
49 | 49 | import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCache;
|
50 | 50 | import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCacheEntry;
|
51 | 51 | import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCacheKey;
|
| 52 | +import org.wso2.carbon.identity.oauth.cache.OAuthCache; |
| 53 | +import org.wso2.carbon.identity.oauth.cache.OAuthCacheKey; |
52 | 54 | import org.wso2.carbon.identity.oauth.common.OAuth2ErrorCodes;
|
53 | 55 | import org.wso2.carbon.identity.oauth.common.OAuthConstants;
|
54 | 56 | import org.wso2.carbon.identity.oauth.common.exception.InvalidOAuthClientException;
|
|
62 | 64 | import org.wso2.carbon.identity.oauth2.IDTokenValidationFailureException;
|
63 | 65 | import org.wso2.carbon.identity.oauth2.IdentityOAuth2ClientException;
|
64 | 66 | import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
|
| 67 | +import org.wso2.carbon.identity.oauth2.IdentityOAuth2ServerException; |
65 | 68 | import org.wso2.carbon.identity.oauth2.OAuth2Constants;
|
66 | 69 | import org.wso2.carbon.identity.oauth2.ResponseHeader;
|
67 | 70 | import org.wso2.carbon.identity.oauth2.bean.OAuthClientAuthnContext;
|
|
75 | 78 | import org.wso2.carbon.identity.oauth2.impersonation.services.ImpersonationNotificationMgtService;
|
76 | 79 | import org.wso2.carbon.identity.oauth2.impersonation.services.ImpersonationNotificationMgtServiceImpl;
|
77 | 80 | import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
|
| 81 | +import org.wso2.carbon.identity.oauth2.model.AccessTokenDO; |
78 | 82 | import org.wso2.carbon.identity.oauth2.model.RequestParameter;
|
| 83 | +import org.wso2.carbon.identity.oauth2.model.TokenIssuanceDO; |
79 | 84 | import org.wso2.carbon.identity.oauth2.rar.util.AuthorizationDetailsUtils;
|
80 | 85 | import org.wso2.carbon.identity.oauth2.rar.validator.AuthorizationDetailsValidator;
|
81 | 86 | import org.wso2.carbon.identity.oauth2.rar.validator.DefaultAuthorizationDetailsValidator;
|
|
84 | 89 | import org.wso2.carbon.identity.oauth2.token.handlers.grant.AuthorizationGrantHandler;
|
85 | 90 | import org.wso2.carbon.identity.oauth2.token.handlers.response.AccessTokenResponseHandler;
|
86 | 91 | import org.wso2.carbon.identity.oauth2.util.AuthzUtil;
|
| 92 | +import org.wso2.carbon.identity.oauth2.util.JWTUtils; |
87 | 93 | import org.wso2.carbon.identity.oauth2.util.OAuth2TokenUtil;
|
88 | 94 | import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
|
89 | 95 | import org.wso2.carbon.identity.oauth2.validators.DefaultOAuth2ScopeValidator;
|
90 | 96 | import org.wso2.carbon.identity.oauth2.validators.JDBCPermissionBasedInternalScopeValidator;
|
91 | 97 | import org.wso2.carbon.identity.oauth2.validators.RoleBasedInternalScopeValidator;
|
92 | 98 | import org.wso2.carbon.identity.openidconnect.IDTokenBuilder;
|
| 99 | +import org.wso2.carbon.identity.openidconnect.OIDCConstants; |
93 | 100 | import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;
|
94 | 101 | import org.wso2.carbon.user.api.UserStoreException;
|
95 | 102 | import org.wso2.carbon.user.core.common.AbstractUserStoreManager;
|
|
98 | 105 | import org.wso2.carbon.utils.CarbonUtils;
|
99 | 106 | import org.wso2.carbon.utils.DiagnosticLog;
|
100 | 107 |
|
| 108 | +import java.text.ParseException; |
101 | 109 | import java.util.ArrayList;
|
102 | 110 | import java.util.Arrays;
|
103 | 111 | import java.util.Collections;
|
|
127 | 135 | import static org.wso2.carbon.identity.oauth2.device.constants.Constants.DEVICE_FLOW_GRANT_TYPE;
|
128 | 136 | import static org.wso2.carbon.identity.oauth2.util.OAuth2Util.EXTENDED_REFRESH_TOKEN_DEFAULT_TIME;
|
129 | 137 | import static org.wso2.carbon.identity.oauth2.util.OAuth2Util.INTERNAL_LOGIN_SCOPE;
|
130 |
| -import static org.wso2.carbon.identity.oauth2.util.OAuth2Util.validateRequestTenantDomain; |
| 138 | +import static org.wso2.carbon.identity.openidconnect.OIDCConstants.EXISTING_TOKEN_USED; |
131 | 139 | import static org.wso2.carbon.identity.openidconnect.OIDCConstants.ID_TOKEN_USER_CLAIMS_PROP_KEY;
|
132 | 140 |
|
133 | 141 | /**
|
@@ -328,7 +336,7 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO)
|
328 | 336 | // Indirectly we can say that the tenantDomain of the SP is the tenantDomain of the user who created SP.
|
329 | 337 | // This is done to avoid having to send the tenantDomain as a query param to the token endpoint
|
330 | 338 | String tenantDomainOfApp = OAuth2Util.getTenantDomainOfOauthApp(oAuthAppDO);
|
331 |
| - validateRequestTenantDomain(tenantDomainOfApp, tokenReqDTO); |
| 339 | + OAuth2Util.validateRequestTenantDomain(tenantDomainOfApp, tokenReqDTO); |
332 | 340 |
|
333 | 341 | tokenReqDTO.setTenantDomain(tenantDomainOfApp);
|
334 | 342 |
|
@@ -1364,6 +1372,11 @@ private void triggerPostListeners(OAuth2AccessTokenReqDTO tokenReqDTO,
|
1364 | 1372 |
|
1365 | 1373 | OAuthEventInterceptor oAuthEventInterceptorProxy = OAuthComponentServiceHolder.getInstance()
|
1366 | 1374 | .getOAuthEventInterceptorProxy();
|
| 1375 | + try { |
| 1376 | + triggerPostIssueTokenEvent(tokenReqDTO, tokenRespDTO, tokReqMsgCtx); |
| 1377 | + } catch (IdentityOAuth2Exception e) { |
| 1378 | + log.error("Error while triggering post issue token event.", e); |
| 1379 | + } |
1367 | 1380 |
|
1368 | 1381 | if (isRefresh) {
|
1369 | 1382 | if (oAuthEventInterceptorProxy != null && oAuthEventInterceptorProxy.isEnabled()) {
|
@@ -1394,6 +1407,64 @@ private void triggerPostListeners(OAuth2AccessTokenReqDTO tokenReqDTO,
|
1394 | 1407 | }
|
1395 | 1408 | }
|
1396 | 1409 |
|
| 1410 | + private static void triggerPostIssueTokenEvent(OAuth2AccessTokenReqDTO tokenReqDTO, |
| 1411 | + OAuth2AccessTokenRespDTO tokenRespDTO, |
| 1412 | + OAuthTokenReqMessageContext tokReqMsgCtx) |
| 1413 | + throws IdentityOAuth2Exception { |
| 1414 | + |
| 1415 | + String cacheKey; |
| 1416 | + if (JWTUtils.isJWT(tokenRespDTO.getAccessToken())) { |
| 1417 | + Optional<JWTClaimsSet> jwtClaimSet; |
| 1418 | + try { |
| 1419 | + jwtClaimSet = JWTUtils.getJWTClaimSet( |
| 1420 | + JWTUtils.parseJWT(tokenRespDTO.getAccessToken())); |
| 1421 | + } catch (ParseException e) { |
| 1422 | + throw new IdentityOAuth2ServerException("Error while parsing the JWT access token.", e); |
| 1423 | + } |
| 1424 | + jwtClaimSet.orElseThrow(() -> new IdentityOAuth2ServerException("Empty JWT claims set found.")); |
| 1425 | + cacheKey = jwtClaimSet.get().getJWTID(); |
| 1426 | + } else { |
| 1427 | + cacheKey = tokenRespDTO.getAccessToken(); |
| 1428 | + } |
| 1429 | + if (StringUtils.isBlank(cacheKey)) { |
| 1430 | + throw new IdentityOAuth2ServerException("Token cache key not found."); |
| 1431 | + } |
| 1432 | + AccessTokenDO accessTokenDO = (AccessTokenDO) OAuthCache.getInstance().getValueFromCache( |
| 1433 | + new OAuthCacheKey(cacheKey)); |
| 1434 | + if (accessTokenDO == null) { |
| 1435 | + throw new IdentityOAuth2ServerException("Access token not found in the cache"); |
| 1436 | + } |
| 1437 | + String tokenType = accessTokenDO.getTokenType(); |
| 1438 | + int appResidentTenantId = accessTokenDO.getAppResidentTenantId(); |
| 1439 | + String issuedTime = accessTokenDO.getIssuedTime() != null ? |
| 1440 | + accessTokenDO.getIssuedTime().toString() : StringUtils.EMPTY; |
| 1441 | + String authorizedOrganizationId = accessTokenDO.getAuthorizedOrganizationId(); |
| 1442 | + if (!existingTokenUsed(tokReqMsgCtx)) { |
| 1443 | + OAuth2TokenUtil.postIssueToken(new TokenIssuanceDO.Builder(). |
| 1444 | + tokenId(tokenRespDTO.getTokenId()). |
| 1445 | + tokenType(tokenType). |
| 1446 | + tenantDomain(tokReqMsgCtx.getOauth2AccessTokenReqDTO().getTenantDomain()). |
| 1447 | + tokenType(accessTokenDO.getTokenType()). |
| 1448 | + clientId(tokReqMsgCtx.getOauth2AccessTokenReqDTO().getClientId()). |
| 1449 | + grantType(tokenReqDTO.getGrantType()). |
| 1450 | + tokenBillingCategory(OIDCConstants.TokenBillingCategory.M2M_ACCESS_TOKEN). |
| 1451 | + appResidentTenantId(appResidentTenantId). |
| 1452 | + issuedTime(issuedTime). |
| 1453 | + authorizedOrganizationId(authorizedOrganizationId). |
| 1454 | + build() |
| 1455 | + ); |
| 1456 | + } |
| 1457 | + } |
| 1458 | + |
| 1459 | + private static Boolean existingTokenUsed(OAuthTokenReqMessageContext tokReqMsgCtx) { |
| 1460 | + |
| 1461 | + Boolean existingTokenUsed = (Boolean) tokReqMsgCtx.getProperty(EXISTING_TOKEN_USED); |
| 1462 | + if (existingTokenUsed == null) { |
| 1463 | + existingTokenUsed = false; |
| 1464 | + } |
| 1465 | + return existingTokenUsed; |
| 1466 | + } |
| 1467 | + |
1397 | 1468 | /**
|
1398 | 1469 | * Copies the cache entry against the authorization code/device code and adds an entry against the access token.
|
1399 | 1470 | * This is done to reuse the calculated user claims for subsequent usages such as user info calls.
|
|
0 commit comments