From 579425387e13eefa70455d9a0403ac8a08414b9f Mon Sep 17 00:00:00 2001 From: Pulasthi Mahawithana Date: Mon, 7 Mar 2016 18:09:42 +0530 Subject: [PATCH 1/2] Improving token revocation event publishing --- .../identity/oauth/OAuthAdminService.java | 54 +++++- .../identity/oauth/dao/OAuthAppDAO.java | 4 +- .../oauth/event/OauthEventListener.java | 161 ++++++++++++++++++ .../internal/OAuthComponentServiceHolder.java | 61 ++++++- .../oauth/internal/OAuthServiceComponent.java | 52 ++++-- .../carbon/identity/oauth2/OAuth2Service.java | 93 +++++++--- .../oauth2/OAuth2TokenValidationService.java | 93 ++++++---- .../authcontext/DefaultClaimsRetriever.java | 12 +- .../oauth2/authcontext/JWTTokenGenerator.java | 4 +- .../handlers/TokenResponseTypeHandler.java | 111 +++++++----- .../oauth2/token/AccessTokenIssuer.java | 106 +++++++++--- .../handlers/grant/PasswordGrantHandler.java | 2 +- .../identity/oauth2/util/OAuth2Util.java | 4 +- .../oauth2/validators/JDBCScopeValidator.java | 2 +- 14 files changed, 604 insertions(+), 155 deletions(-) create mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/event/OauthEventListener.java diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthAdminService.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthAdminService.java index bf9be06ab62..a680f46c33e 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthAdminService.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthAdminService.java @@ -27,7 +27,6 @@ import org.wso2.carbon.core.AbstractAdmin; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; import org.wso2.carbon.identity.application.common.model.User; -import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.oauth.cache.AppInfoCache; import org.wso2.carbon.identity.oauth.cache.OAuthCache; @@ -37,9 +36,12 @@ import org.wso2.carbon.identity.oauth.common.exception.InvalidOAuthClientException; import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; import org.wso2.carbon.identity.oauth.dao.OAuthAppDAO; +import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; import org.wso2.carbon.identity.oauth.dto.OAuthConsumerAppDTO; import org.wso2.carbon.identity.oauth.dto.OAuthRevocationRequestDTO; import org.wso2.carbon.identity.oauth.dto.OAuthRevocationResponseDTO; +import org.wso2.carbon.identity.oauth.event.OauthEventListener; +import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; import org.wso2.carbon.identity.oauth2.dao.TokenMgtDAO; import org.wso2.carbon.identity.oauth2.model.AccessTokenDO; @@ -136,6 +138,7 @@ public OAuthConsumerAppDTO[] getAllOAuthApplicationData() throws IdentityOAuthAd * @throws Exception Error when reading application information from persistence store. */ public OAuthConsumerAppDTO getOAuthApplicationData(String consumerKey) throws IdentityOAuthAdminException { + OAuthConsumerAppDTO dto = new OAuthConsumerAppDTO(); OAuthAppDAO dao = new OAuthAppDAO(); try { @@ -163,6 +166,7 @@ public OAuthConsumerAppDTO getOAuthApplicationData(String consumerKey) throws Id * @throws Exception Error when reading application information from persistence store. */ public OAuthConsumerAppDTO getOAuthApplicationDataByAppName(String appName) throws IdentityOAuthAdminException { + OAuthConsumerAppDTO dto = new OAuthConsumerAppDTO(); OAuthAppDAO dao = new OAuthAppDAO(); try { @@ -176,7 +180,7 @@ public OAuthConsumerAppDTO getOAuthApplicationDataByAppName(String appName) thro dto.setGrantTypes(app.getGrantTypes()); } return dto; - }catch (InvalidOAuthClientException | IdentityOAuth2Exception e){ + } catch (InvalidOAuthClientException | IdentityOAuth2Exception e) { throw new IdentityOAuthAdminException("Error while retrieving the app information by app name", e); } } @@ -187,7 +191,8 @@ public OAuthConsumerAppDTO getOAuthApplicationDataByAppName(String appName) thro * @param application OAuthConsumerAppDTO with application information * @throws Exception Error when persisting the application information to the persistence store */ - public void registerOAuthApplicationData(OAuthConsumerAppDTO application) throws IdentityOAuthAdminException{ + public void registerOAuthApplicationData(OAuthConsumerAppDTO application) throws IdentityOAuthAdminException { + String userName = CarbonContext.getThreadLocalCarbonContext().getUsername(); if (userName != null) { String tenantUser = MultitenantUtils.getTenantAwareUsername(userName); @@ -240,7 +245,7 @@ public void registerOAuthApplicationData(OAuthConsumerAppDTO application) throws List allowedGrants = new ArrayList<>(Arrays.asList(getAllowedGrantTypes())); String[] requestGrants = application.getGrantTypes().split("\\s"); for (String requestedGrant : requestGrants) { - if (StringUtils.isBlank(requestedGrant)){ + if (StringUtils.isBlank(requestedGrant)) { continue; } if (!allowedGrants.contains(requestedGrant)) { @@ -264,6 +269,7 @@ public void registerOAuthApplicationData(OAuthConsumerAppDTO application) throws * @throws IdentityOAuthAdminException Error when updating the underlying identity persistence store. */ public void updateConsumerApplication(OAuthConsumerAppDTO consumerAppDTO) throws IdentityOAuthAdminException { + String userName = CarbonContext.getThreadLocalCarbonContext().getUsername(); String tenantAwareUsername = MultitenantUtils.getTenantAwareUsername(userName); int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); @@ -305,6 +311,7 @@ public void updateConsumerApplication(OAuthConsumerAppDTO consumerAppDTO) throws * @throws Exception Error when removing the consumer information from the database. */ public void removeOAuthApplicationData(String consumerKey) throws IdentityOAuthAdminException { + OAuthAppDAO dao = new OAuthAppDAO(); dao.removeConsumerApplication(consumerKey); // remove client credentials from cache @@ -373,7 +380,7 @@ public OAuthConsumerAppDTO[] getAppsAuthorizedByUser() throws IdentityOAuthAdmin try { scopedToken = tokenMgtDAO.retrieveLatestAccessToken( clientId, authenticatedUser, userStoreDomain, scopeString, true); - if(scopedToken != null && !distinctClientUserScopeCombo.contains(clientId+":"+username)){ + if (scopedToken != null && !distinctClientUserScopeCombo.contains(clientId + ":" + username)) { OAuthConsumerAppDTO appDTO = new OAuthConsumerAppDTO(); OAuthAppDO appDO; try { @@ -393,7 +400,7 @@ public OAuthConsumerAppDTO[] getAppsAuthorizedByUser() throws IdentityOAuthAdmin log.error(errorMsg, e); throw new IdentityOAuthAdminException(errorMsg); } - distinctClientUserScopeCombo.add(clientId+":"+username); + distinctClientUserScopeCombo.add(clientId + ":" + username); } } catch (IdentityOAuth2Exception e) { @@ -417,6 +424,18 @@ public OAuthConsumerAppDTO[] getAppsAuthorizedByUser() throws IdentityOAuthAdmin public OAuthRevocationResponseDTO revokeAuthzForAppsByResoureOwner( OAuthRevocationRequestDTO revokeRequestDTO) throws IdentityOAuthAdminException { + List oauthListeners = OAuthComponentServiceHolder.getInstance().getOauthEventListeners(); + + for (OauthEventListener listener : oauthListeners) { + try { + listener.onPreTokenRevocationByResourceOwner(revokeRequestDTO); + } catch (IdentityOAuth2Exception e) { + throw new IdentityOAuthAdminException("Error occured with Oauth pre-revoke listner " + listener + .getClass().getName(), e); + } + } + + TokenMgtDAO tokenMgtDAO = new TokenMgtDAO(); if (revokeRequestDTO.getApps() != null && revokeRequestDTO.getApps().length > 0) { String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); @@ -486,13 +505,15 @@ public OAuthRevocationResponseDTO revokeAuthzForAppsByResoureOwner( throw new IdentityOAuthAdminException(errorMsg, e); } } + triggerPostRevokeListeners(oauthListeners, revokeRequestDTO, new OAuthRevocationResponseDTO + (), accessTokenDOs.toArray(new AccessTokenDO[accessTokenDOs.size()])); } try { tokenMgtDAO.revokeOAuthConsentByApplicationAndUser(userName, appName); } catch (IdentityOAuth2Exception e) { String errorMsg = "Error occurred while removing OAuth Consent of Application " + appName + - " of user " + userName; + " of user " + userName; log.error(errorMsg, e); throw new IdentityOAuthAdminException(errorMsg, e); } @@ -504,12 +525,31 @@ public OAuthRevocationResponseDTO revokeAuthzForAppsByResoureOwner( revokeRespDTO.setError(true); revokeRespDTO.setErrorCode(OAuth2ErrorCodes.INVALID_REQUEST); revokeRespDTO.setErrorMsg("Invalid revocation request"); + + //passing a single element array with null element to make sure listeners are triggered at least once + triggerPostRevokeListeners(oauthListeners, revokeRequestDTO, revokeRespDTO, new AccessTokenDO[]{null}); return revokeRespDTO; } return new OAuthRevocationResponseDTO(); } + private void triggerPostRevokeListeners(List oauthListeners, + OAuthRevocationRequestDTO revokeRequestDTO, + OAuthRevocationResponseDTO revokeRespDTO, AccessTokenDO[] accessTokenDOs) { + + for (AccessTokenDO accessTokenDO : accessTokenDOs) { + for (OauthEventListener listener : oauthListeners) { + try { + listener.onPostTokenRevocationByResourceOwner(revokeRequestDTO, revokeRespDTO, accessTokenDO); + } catch (IdentityOAuth2Exception e) { + log.error("Error occurred with post revocation listener " + listener.getClass().getName(), e); + } + } + } + } + public String[] getAllowedGrantTypes() { + if (allowedGrants == null) { synchronized (OAuthAdminService.class) { if (allowedGrants == null) { diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dao/OAuthAppDAO.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dao/OAuthAppDAO.java index 14595ccdb69..42e63174e8a 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dao/OAuthAppDAO.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/dao/OAuthAppDAO.java @@ -141,7 +141,7 @@ public OAuthAppDO[] getOAuthConsumerAppsOfUser(String username, int tenantId) th OAuthAppDO[] oauthAppsOfUser; try { - RealmService realmService = OAuthComponentServiceHolder.getRealmService(); + RealmService realmService = OAuthComponentServiceHolder.getInstance().getRealmService(); String tenantDomain = realmService.getTenantManager().getDomain(tenantId); String tenantAwareUserName = MultitenantUtils.getTenantAwareUsername(username); String tenantUnawareUserName = tenantAwareUserName + "@" + tenantDomain; @@ -451,4 +451,4 @@ private boolean isDuplicateConsumer(String consumerKey) throws IdentityOAuthAdmi return isDuplicateConsumer; } -} \ No newline at end of file +} diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/event/OauthEventListener.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/event/OauthEventListener.java new file mode 100644 index 00000000000..3417555c0f6 --- /dev/null +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/event/OauthEventListener.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2016, 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.oauth.event; + +import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; +import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext; +import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO; +import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenRespDTO; +import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeRespDTO; +import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationRequestDTO; +import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationResponseDTO; +import org.wso2.carbon.identity.oauth2.dto.OAuthRevocationRequestDTO; +import org.wso2.carbon.identity.oauth2.dto.OAuthRevocationResponseDTO; +import org.wso2.carbon.identity.oauth2.model.AccessTokenDO; +import org.wso2.carbon.identity.oauth2.model.RefreshTokenValidationDataDO; +import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext; + +public interface OauthEventListener { + + /** + * Called prior to issuing tokens. + * Note : This won't be called for implicit grant. Use the overloaded method for implicit grant + * + * @param tokenReqDTO + * @param tokReqMsgCtx + * @throws IdentityOAuth2Exception + */ + void onPreTokenIssue(OAuth2AccessTokenReqDTO tokenReqDTO, OAuthTokenReqMessageContext tokReqMsgCtx) + throws IdentityOAuth2Exception; + + /** + * Called after issuing tokens + * Note : This won't be called for implicit grant. Use the overloaded method for implicit grant + * + * @param tokenReqDTO + * @param tokenRespDTO + * @param tokReqMsgCtx + * @throws IdentityOAuth2Exception + */ + void onPostTokenIssue(OAuth2AccessTokenReqDTO tokenReqDTO, OAuth2AccessTokenRespDTO tokenRespDTO, + OAuthTokenReqMessageContext tokReqMsgCtx) throws IdentityOAuth2Exception; + + /** + * Called prior to issuing tokens in implicit grant + * + * @param oauthAuthzMsgCtx + * @throws IdentityOAuth2Exception + */ + void onPreTokenIssue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx) + throws IdentityOAuth2Exception; + + /** + * Called after generating tokens in implicit grant + * + * @param oauthAuthzMsgCtx + * @param respDTO + * @throws IdentityOAuth2Exception + */ + void onPostTokenIssue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx, AccessTokenDO tokenDO, OAuth2AuthorizeRespDTO + respDTO) throws IdentityOAuth2Exception; + + + /** + * Called prior to renewing tokens (Refresh grant) + * + * @param tokenReqDTO + * @param tokReqMsgCtx + * @throws IdentityOAuth2Exception + */ + void onPreTokenRenewal(OAuth2AccessTokenReqDTO tokenReqDTO, OAuthTokenReqMessageContext tokReqMsgCtx) + throws IdentityOAuth2Exception; + + /** + * Called after renewing a token + * + * @param tokenReqDTO + * @param tokenRespDTO + * @param tokReqMsgCtx + * @throws IdentityOAuth2Exception + */ + void onPostTokenRenewal(OAuth2AccessTokenReqDTO tokenReqDTO, OAuth2AccessTokenRespDTO tokenRespDTO, + OAuthTokenReqMessageContext tokReqMsgCtx) throws IdentityOAuth2Exception; + + /** + * Called prior to revoking a token by oauth client + * + * @param revokeRequestDTO + * @throws IdentityOAuth2Exception + */ + void onPreTokenRevocationByClient(OAuthRevocationRequestDTO revokeRequestDTO) throws IdentityOAuth2Exception; + + /** + * Called after revoking a token by oauth client + * + * @param revokeRequestDTO + * @param revokeResponseDTO + * @param accessTokenDO + * @param refreshTokenDO + * @throws IdentityOAuth2Exception + */ + void onPostTokenRevocationByClient(OAuthRevocationRequestDTO revokeRequestDTO, + OAuthRevocationResponseDTO revokeResponseDTO, AccessTokenDO accessTokenDO, + RefreshTokenValidationDataDO refreshTokenDO) throws IdentityOAuth2Exception; + + + /** + * Called prior to revoking a token by oauth client + * + * @param revokeRequestDTO + * @throws IdentityOAuth2Exception + */ + void onPreTokenRevocationByResourceOwner( + org.wso2.carbon.identity.oauth.dto.OAuthRevocationRequestDTO revokeRequestDTO) throws + IdentityOAuth2Exception; + + /** + * Called after to revoking a token by oauth client + * + * @param revokeRequestDTO + * @throws IdentityOAuth2Exception + */ + void onPostTokenRevocationByResourceOwner( + org.wso2.carbon.identity.oauth.dto.OAuthRevocationRequestDTO revokeRequestDTO, + org.wso2.carbon.identity.oauth.dto.OAuthRevocationResponseDTO revokeRespDTO, AccessTokenDO accessTokenDO) + throws IdentityOAuth2Exception; + + /** + * Called prior to validate an issued token + * + * @param validationReqDTO + * @throws IdentityOAuth2Exception + */ + void onPreTokenValidation(OAuth2TokenValidationRequestDTO validationReqDTO) throws IdentityOAuth2Exception; + + /** + * Called after validating an issued token + * + * @param validationReqDTO + * @param validationResponseDTO + * @throws IdentityOAuth2Exception + */ + void onPostTokenValidation(OAuth2TokenValidationRequestDTO validationReqDTO, + OAuth2TokenValidationResponseDTO validationResponseDTO) throws IdentityOAuth2Exception; + +} diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthComponentServiceHolder.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthComponentServiceHolder.java index d671cc0b116..692264347af 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthComponentServiceHolder.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthComponentServiceHolder.java @@ -18,30 +18,75 @@ package org.wso2.carbon.identity.oauth.internal; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.oauth.event.OauthEventListener; import org.wso2.carbon.registry.api.RegistryService; import org.wso2.carbon.user.core.service.RealmService; +import java.util.ArrayList; +import java.util.List; + public class OAuthComponentServiceHolder { - private static RegistryService registryService; - private static RealmService realmService; + + private static OAuthComponentServiceHolder instance = new OAuthComponentServiceHolder(); + private RegistryService registryService; + private RealmService realmService; + private List oauthEventListeners; + private static Log log = LogFactory.getLog(OAuthComponentServiceHolder.class); private OAuthComponentServiceHolder(){ } - public static RegistryService getRegistryService() { + public static OAuthComponentServiceHolder getInstance() { + + return instance; + } + + public RegistryService getRegistryService() { + return registryService; } - public static void setRegistryService(RegistryService registryService) { - OAuthComponentServiceHolder.registryService = registryService; + public void setRegistryService(RegistryService registryService) { + + this.registryService = registryService; } - public static RealmService getRealmService() { + public RealmService getRealmService() { + return realmService; } - public static void setRealmService(RealmService realmService) { - OAuthComponentServiceHolder.realmService = realmService; + public void setRealmService(RealmService realmService) { + + this.realmService = realmService; + } + + public void addOauthEventListener(OauthEventListener oauthEventListener) { + + if (oauthEventListeners == null) { + oauthEventListeners = new ArrayList<>(); + } + oauthEventListeners.add(oauthEventListener); + } + + public void removeOauthEventListener(OauthEventListener oauthEventListener) { + + if (oauthEventListeners != null && oauthEventListener != null) { + boolean isRemoved = oauthEventListeners.remove(oauthEventListener); + if (!isRemoved) { + log.warn(oauthEventListener.getClass().getName() + " had not been registered as a listener"); + } + } + } + + public List getOauthEventListeners() { + + if (oauthEventListeners == null) { + oauthEventListeners = new ArrayList<>(); + } + return oauthEventListeners; } } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthServiceComponent.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthServiceComponent.java index 0d4caf5daf5..22f45acb31c 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthServiceComponent.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthServiceComponent.java @@ -24,6 +24,7 @@ import org.osgi.service.component.ComponentContext; import org.wso2.carbon.identity.oauth.cache.OAuthCache; import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; +import org.wso2.carbon.identity.oauth.event.OauthEventListener; import org.wso2.carbon.identity.oauth.listener.IdentityOathEventListener; import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.user.core.listener.UserOperationEventListener; @@ -35,6 +36,11 @@ * interface="org.wso2.carbon.registry.core.service.RegistryService" * cardinality="1..1" policy="dynamic" bind="setRegistryService" * unbind="unsetRegistryService" + * @scr.reference name="org.wso2.carbon.identity.oauth.event.OauthEventListener" + * interface="org.wso2.carbon.identity.oauth.event.OauthEventListener" + * cardinality="0..n" policy="dynamic" + * bind="setOauthEventListener" + * unbind="unsetOauthEventListener" * @scr.reference name="user.realmservice.default" * interface="org.wso2.carbon.user.core.service.RealmService" cardinality="1..1" * policy="dynamic" bind="setRealmService" unbind="unsetRealmService" @@ -65,7 +71,7 @@ protected void activate(ComponentContext context) { log.debug("Identity Oath Event Listener is enabled"); if (log.isDebugEnabled()) { - log.info("Identity OAuth bundle is activated"); + log.debug("Identity OAuth bundle is activated"); } } @@ -74,35 +80,61 @@ protected void deactivate(ComponentContext context) { serviceRegistration.unregister(); } if (log.isDebugEnabled()) { - log.info("Identity OAuth bundle is deactivated"); + log.debug("Identity OAuth bundle is deactivated"); } } protected void setRegistryService(RegistryService registryService) { if (log.isDebugEnabled()) { - log.info("RegistryService set in Identity OAuth bundle"); + log.debug("RegistryService set in Identity OAuth bundle"); } - OAuthComponentServiceHolder.setRegistryService(registryService); + OAuthComponentServiceHolder.getInstance().setRegistryService(registryService); } protected void unsetRegistryService(RegistryService registryService) { if (log.isDebugEnabled()) { - log.info("RegistryService unset in Identity OAuth bundle"); + log.debug("RegistryService unset in Identity OAuth bundle"); } - OAuthComponentServiceHolder.setRegistryService(null); + OAuthComponentServiceHolder.getInstance().setRegistryService(null); } protected void setRealmService(RealmService realmService) { if (log.isDebugEnabled()) { - log.info("Setting the Realm Service"); + log.debug("Setting the Realm Service"); } - OAuthComponentServiceHolder.setRealmService(realmService); + OAuthComponentServiceHolder.getInstance().setRealmService(realmService); } protected void unsetRealmService(RealmService realmService) { if (log.isDebugEnabled()) { - log.info("Unsetting the Realm Service"); + log.debug("Unsetting the Realm Service"); } - OAuthComponentServiceHolder.setRealmService(null); + OAuthComponentServiceHolder.getInstance().setRealmService(null); + } + + protected void setOauthEventListener(OauthEventListener oauthEventListener) { + + if (oauthEventListener == null) { + log.warn("Null OauthEventListener received, hence not registering"); + return; + } + + if (log.isDebugEnabled()) { + log.debug("Setting OauthEventListener :" + oauthEventListener.getClass().getName()); + } + OAuthComponentServiceHolder.getInstance().addOauthEventListener(oauthEventListener); + } + + protected void unsetOauthEventListener(OauthEventListener oauthEventListener) { + + if (oauthEventListener == null) { + log.warn("Null OauthEventListener received, hence not unregistering"); + return; + } + + if (log.isDebugEnabled()) { + log.debug("Unsetting OauthEventListener :" + oauthEventListener.getClass().getName()); + } + OAuthComponentServiceHolder.getInstance().removeOauthEventListener(oauthEventListener); } } \ No newline at end of file diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2Service.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2Service.java index 9dadc5abbc8..2d75cc04030 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2Service.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2Service.java @@ -24,14 +24,16 @@ import org.apache.oltu.oauth2.common.message.types.GrantType; import org.wso2.carbon.core.AbstractAdmin; import org.wso2.carbon.identity.base.IdentityException; -import org.wso2.carbon.identity.oauth.OAuthUtil; -import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.identity.oauth.OAuthUtil; import org.wso2.carbon.identity.oauth.common.OAuth2ErrorCodes; import org.wso2.carbon.identity.oauth.common.OAuthConstants; import org.wso2.carbon.identity.oauth.common.exception.InvalidOAuthClientException; import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; import org.wso2.carbon.identity.oauth.dao.OAuthAppDAO; +import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; +import org.wso2.carbon.identity.oauth.event.OauthEventListener; +import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; import org.wso2.carbon.identity.oauth2.authz.AuthorizationHandlerManager; import org.wso2.carbon.identity.oauth2.dao.TokenMgtDAO; import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO; @@ -111,6 +113,7 @@ public OAuth2AuthorizeRespDTO authorize(OAuth2AuthorizeReqDTO oAuth2AuthorizeReq * callback, App Name, Error Code and Error Message when appropriate. */ public OAuth2ClientValidationResponseDTO validateClientInfo(String clientId, String callbackURI) { + OAuth2ClientValidationResponseDTO validationResponseDTO = new OAuth2ClientValidationResponseDTO(); @@ -123,8 +126,8 @@ public OAuth2ClientValidationResponseDTO validateClientInfo(String clientId, Str OAuthAppDAO oAuthAppDAO = new OAuthAppDAO(); OAuthAppDO appDO = oAuthAppDAO.getAppInformation(clientId); - if(StringUtils.isEmpty(appDO.getGrantTypes()) || StringUtils.isEmpty(appDO.getCallbackUrl())){ - if(log.isDebugEnabled()) { + if (StringUtils.isEmpty(appDO.getGrantTypes()) || StringUtils.isEmpty(appDO.getCallbackUrl())) { + if (log.isDebugEnabled()) { log.debug("Registered App found for the given Client Id : " + clientId + " ,App Name : " + appDO .getApplicationName() + ", does not support the requested grant type."); } @@ -189,7 +192,8 @@ public OAuth2AccessTokenRespDTO issueAccessToken(OAuth2AccessTokenReqDTO tokenRe if (log.isDebugEnabled()) { log.debug("Access Token request received for Client ID " + tokenReqDTO.getClientId() + ", User ID " + tokenReqDTO.getResourceOwnerUsername() + - ", Scope : " + Arrays.toString(tokenReqDTO.getScope()) + " and Grant Type : " + tokenReqDTO.getGrantType()); + ", Scope : " + Arrays.toString(tokenReqDTO.getScope()) + " and Grant Type : " + + tokenReqDTO.getGrantType()); } try { @@ -199,7 +203,8 @@ public OAuth2AccessTokenRespDTO issueAccessToken(OAuth2AccessTokenReqDTO tokenRe if (log.isDebugEnabled()) { log.debug("Error occurred while issuing access token for Client ID : " + tokenReqDTO.getClientId() + ", User ID: " + tokenReqDTO.getResourceOwnerUsername() + - ", Scope : " + Arrays.toString(tokenReqDTO.getScope()) + " and Grant Type : " + tokenReqDTO.getGrantType(), e); + ", Scope : " + Arrays.toString(tokenReqDTO.getScope()) + " and Grant Type : " + + tokenReqDTO.getGrantType(), e); } OAuth2AccessTokenRespDTO tokenRespDTO = new OAuth2AccessTokenRespDTO(); tokenRespDTO.setError(true); @@ -209,10 +214,11 @@ public OAuth2AccessTokenRespDTO issueAccessToken(OAuth2AccessTokenReqDTO tokenRe } catch (Exception e) { // in case of an error, consider it as a system error log.error("Error occurred while issuing the access token for Client ID : " + tokenReqDTO.getClientId() + ", User ID " + tokenReqDTO.getResourceOwnerUsername() + - ", Scope : " + Arrays.toString(tokenReqDTO.getScope()) + " and Grant Type : " + tokenReqDTO.getGrantType(), e); + ", Scope : " + Arrays.toString(tokenReqDTO.getScope()) + " and Grant Type : " + + tokenReqDTO.getGrantType(), e); OAuth2AccessTokenRespDTO tokenRespDTO = new OAuth2AccessTokenRespDTO(); tokenRespDTO.setError(true); - if (e.getCause().getCause() instanceof SQLIntegrityConstraintViolationException){ + if (e.getCause().getCause() instanceof SQLIntegrityConstraintViolationException) { tokenRespDTO.setErrorCode("sql_error"); } else { tokenRespDTO.setErrorCode(OAuth2ErrorCodes.SERVER_ERROR); @@ -233,6 +239,23 @@ public OAuthRevocationResponseDTO revokeTokenByOAuthClient(OAuthRevocationReques //fix here remove associated cache entry TokenMgtDAO tokenMgtDAO = new TokenMgtDAO(); OAuthRevocationResponseDTO revokeResponseDTO = new OAuthRevocationResponseDTO(); + List oauthListeners = OAuthComponentServiceHolder.getInstance().getOauthEventListeners(); + + //Invoke pre listeners + for (OauthEventListener listener : oauthListeners) { + try { + listener.onPreTokenRevocationByClient(revokeRequestDTO); + } catch (IdentityOAuth2Exception e) { + log.error("Error occurred while invoking pre-revoke listener: " + listener.getClass().getName(), e); + revokeResponseDTO.setError(true); + revokeResponseDTO.setErrorCode(OAuth2ErrorCodes.SERVER_ERROR); + revokeResponseDTO.setErrorMsg("Error occurred while revoking authorization grant for applications"); + return revokeResponseDTO; + } + } + + RefreshTokenValidationDataDO refreshTokenDO = null; + AccessTokenDO accessTokenDO = null; try { if (StringUtils.isNotEmpty(revokeRequestDTO.getConsumerKey()) && @@ -243,19 +266,16 @@ public OAuthRevocationResponseDTO revokeTokenByOAuthClient(OAuthRevocationReques refreshTokenFirst = true; } - RefreshTokenValidationDataDO refreshTokenDO = null; - AccessTokenDO accessTokenDO = null; - if (refreshTokenFirst) { refreshTokenDO = tokenMgtDAO .validateRefreshToken(revokeRequestDTO.getConsumerKey(), revokeRequestDTO.getToken()); if (refreshTokenDO == null || StringUtils.isEmpty(refreshTokenDO.getRefreshTokenState()) || - !(OAuthConstants.TokenStates.TOKEN_STATE_ACTIVE - .equals(refreshTokenDO.getRefreshTokenState()) || - OAuthConstants.TokenStates.TOKEN_STATE_EXPIRED - .equals(refreshTokenDO.getRefreshTokenState()))) { + !(OAuthConstants.TokenStates.TOKEN_STATE_ACTIVE + .equals(refreshTokenDO.getRefreshTokenState()) || + OAuthConstants.TokenStates.TOKEN_STATE_EXPIRED + .equals(refreshTokenDO.getRefreshTokenState()))) { accessTokenDO = tokenMgtDAO.retrieveAccessToken(revokeRequestDTO.getToken(), true); refreshTokenDO = null; @@ -274,6 +294,8 @@ public OAuthRevocationResponseDTO revokeTokenByOAuthClient(OAuthRevocationReques .equals(refreshTokenDO.getRefreshTokenState()) || OAuthConstants.TokenStates.TOKEN_STATE_EXPIRED .equals(refreshTokenDO.getRefreshTokenState()))) { + invokePostRevocationListeners(oauthListeners, revokeRequestDTO, revokeResponseDTO, + accessTokenDO, refreshTokenDO); return revokeResponseDTO; } } @@ -296,43 +318,48 @@ public OAuthRevocationResponseDTO revokeTokenByOAuthClient(OAuthRevocationReques revokeRespDTO.setErrorCode(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT); revokeRespDTO.setErrorMsg("Unauthorized Client"); + invokePostRevocationListeners(oauthListeners, revokeRequestDTO, revokeResponseDTO, accessTokenDO, + refreshTokenDO); return revokeRespDTO; } if (refreshTokenDO != null) { OAuthUtil.clearOAuthCache(revokeRequestDTO.getConsumerKey(), refreshTokenDO.getAuthorizedUser(), - OAuth2Util.buildScopeString(refreshTokenDO.getScope())); + OAuth2Util.buildScopeString(refreshTokenDO.getScope())); OAuthUtil.clearOAuthCache(revokeRequestDTO.getConsumerKey(), refreshTokenDO.getAuthorizedUser()); OAuthUtil.clearOAuthCache(refreshTokenDO.getAccessToken()); - tokenMgtDAO.revokeTokens(new String[] { refreshTokenDO.getAccessToken() }); + tokenMgtDAO.revokeTokens(new String[]{refreshTokenDO.getAccessToken()}); addRevokeResponseHeaders(revokeResponseDTO, refreshTokenDO.getAccessToken(), revokeRequestDTO.getToken(), refreshTokenDO.getAuthorizedUser().toString()); } else if (accessTokenDO != null) { - if(revokeRequestDTO.getConsumerKey().equals(accessTokenDO.getConsumerKey())){ + if (revokeRequestDTO.getConsumerKey().equals(accessTokenDO.getConsumerKey())) { OAuthUtil.clearOAuthCache(revokeRequestDTO.getConsumerKey(), accessTokenDO.getAuthzUser(), OAuth2Util.buildScopeString(accessTokenDO.getScope())); OAuthUtil.clearOAuthCache(revokeRequestDTO.getConsumerKey(), accessTokenDO.getAuthzUser()); OAuthUtil.clearOAuthCache(revokeRequestDTO.getToken()); - tokenMgtDAO.revokeTokens(new String[] { revokeRequestDTO.getToken() }); + tokenMgtDAO.revokeTokens(new String[]{revokeRequestDTO.getToken()}); addRevokeResponseHeaders(revokeResponseDTO, revokeRequestDTO.getToken(), accessTokenDO.getRefreshToken(), accessTokenDO.getAuthzUser().toString()); - }else { + } else { throw new InvalidOAuthClientException("Unauthorized Client"); } } - + invokePostRevocationListeners(oauthListeners, revokeRequestDTO, revokeResponseDTO, accessTokenDO, + refreshTokenDO); return revokeResponseDTO; } else { revokeResponseDTO.setError(true); revokeResponseDTO.setErrorCode(OAuth2ErrorCodes.INVALID_REQUEST); revokeResponseDTO.setErrorMsg("Invalid revocation request"); + invokePostRevocationListeners(oauthListeners, revokeRequestDTO, revokeResponseDTO, accessTokenDO, + refreshTokenDO); return revokeResponseDTO; } @@ -342,6 +369,8 @@ public OAuthRevocationResponseDTO revokeTokenByOAuthClient(OAuthRevocationReques revokeRespDTO.setError(true); revokeRespDTO.setErrorCode(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT); revokeRespDTO.setErrorMsg("Unauthorized Client"); + invokePostRevocationListeners(oauthListeners, revokeRequestDTO, revokeResponseDTO, accessTokenDO, + refreshTokenDO); return revokeRespDTO; } catch (IdentityException e) { log.error("Error occurred while revoking authorization grant for applications", e); @@ -349,10 +378,27 @@ public OAuthRevocationResponseDTO revokeTokenByOAuthClient(OAuthRevocationReques revokeRespDTO.setError(true); revokeRespDTO.setErrorCode(OAuth2ErrorCodes.SERVER_ERROR); revokeRespDTO.setErrorMsg("Error occurred while revoking authorization grant for applications"); + invokePostRevocationListeners(oauthListeners, revokeRequestDTO, revokeResponseDTO, accessTokenDO, + refreshTokenDO); return revokeRespDTO; } } + private void invokePostRevocationListeners(List listeners, OAuthRevocationRequestDTO + revokeRequestDTO, OAuthRevocationResponseDTO revokeResponseDTO, AccessTokenDO accessTokenDO, + RefreshTokenValidationDataDO refreshTokenDO) { + + for (OauthEventListener listener : listeners) { + try { + listener.onPostTokenRevocationByClient(revokeRequestDTO, revokeResponseDTO, accessTokenDO, + refreshTokenDO); + } catch (IdentityOAuth2Exception e) { + log.error("Error occured when invoking post token revoke listner " + listener.getClass().getName(), e); + } + } + + } + /** * Returns an array of claims of the authorized user. This is for the * OpenIDConnect user-end-point implementation. @@ -415,7 +461,7 @@ public Claim[] getUserClaims(String accessTokenIdentifier) { Map extClaimsMap = userStore.getUserClaimValues(username, claims, profileName); - for (Map.Entry entry : extClaimsMap.entrySet()){ + for (Map.Entry entry : extClaimsMap.entrySet()) { Claim curClaim = new Claim(); curClaim.setClaimUri(entry.getKey()); curClaim.setValue(entry.getValue()); @@ -477,7 +523,8 @@ public Claim[] getUserClaims(String accessTokenIdentifier) { return allClaims; } - private void addRevokeResponseHeaders(OAuthRevocationResponseDTO revokeResponseDTP, String accessToken, String refreshToken, String authorizedUser) { + private void addRevokeResponseHeaders(OAuthRevocationResponseDTO revokeResponseDTP, String accessToken, + String refreshToken, String authorizedUser) { List respHeaders = new ArrayList<>(); ResponseHeader header = new ResponseHeader(); diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2TokenValidationService.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2TokenValidationService.java index fb889a7f253..500e2138733 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2TokenValidationService.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2TokenValidationService.java @@ -21,12 +21,16 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.core.AbstractAdmin; +import org.wso2.carbon.identity.oauth.event.OauthEventListener; +import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; import org.wso2.carbon.identity.oauth2.dto.OAuth2ClientApplicationDTO; import org.wso2.carbon.identity.oauth2.dto.OAuth2IntrospectionResponseDTO; import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationRequestDTO; import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationResponseDTO; import org.wso2.carbon.identity.oauth2.validators.TokenValidationHandler; +import java.util.List; + /** * This is the SOAP version of the OAuth validation service which will be used by the resource server. */ @@ -40,57 +44,80 @@ public class OAuth2TokenValidationService extends AbstractAdmin { */ public OAuth2TokenValidationResponseDTO validate(OAuth2TokenValidationRequestDTO validationReqDTO) { - TokenValidationHandler validationHandler = TokenValidationHandler.getInstance(); + TokenValidationHandler validationHandler = TokenValidationHandler.getInstance(); + List oauthEventListeners = + OAuthComponentServiceHolder.getInstance().getOauthEventListeners(); + for (OauthEventListener oauthEventListener : oauthEventListeners) { + try { + oauthEventListener.onPreTokenValidation(validationReqDTO); + } catch (IdentityOAuth2Exception e) { + OAuth2TokenValidationResponseDTO errRespDTO = new OAuth2TokenValidationResponseDTO(); + errRespDTO.setValid(false); + errRespDTO.setErrorMsg(e.getMessage()); + return errRespDTO; + } + } + OAuth2TokenValidationResponseDTO responseDTO = null; + try { + responseDTO = validationHandler.validate(validationReqDTO); + } catch (IdentityOAuth2Exception e) { + log.error("Error occurred while validating the OAuth2 access token", e); + OAuth2TokenValidationResponseDTO errRespDTO = new OAuth2TokenValidationResponseDTO(); + errRespDTO.setValid(false); + errRespDTO.setErrorMsg("Server error occurred while validating the OAuth2 access token"); + return errRespDTO; + } - try { - return validationHandler.validate(validationReqDTO); - } catch (IdentityOAuth2Exception e) { - log.error("Error occurred while validating the OAuth2 access token", e); - OAuth2TokenValidationResponseDTO errRespDTO = new OAuth2TokenValidationResponseDTO(); - errRespDTO.setValid(false); - errRespDTO.setErrorMsg("Server error occurred while validating the OAuth2 access token"); - return errRespDTO; - } + for (OauthEventListener oauthEventListener : oauthEventListeners) { + try { + oauthEventListener.onPostTokenValidation(validationReqDTO, responseDTO); + } catch (IdentityOAuth2Exception e) { + log.error("Oauth post listener " + oauthEventListener.getClass().getName() + " failed.", e); + } + } + return responseDTO; } /** * @param validationReqDTO * @return */ - public OAuth2ClientApplicationDTO findOAuthConsumerIfTokenIsValid(OAuth2TokenValidationRequestDTO validationReqDTO) { + public OAuth2ClientApplicationDTO findOAuthConsumerIfTokenIsValid( + OAuth2TokenValidationRequestDTO validationReqDTO) { - TokenValidationHandler validationHandler = TokenValidationHandler.getInstance(); + TokenValidationHandler validationHandler = TokenValidationHandler.getInstance(); - try { - return validationHandler.findOAuthConsumerIfTokenIsValid(validationReqDTO); - } catch (IdentityOAuth2Exception e) { - log.error("Error occurred while validating the OAuth2 access token", e); - OAuth2ClientApplicationDTO appDTO = new OAuth2ClientApplicationDTO(); - OAuth2TokenValidationResponseDTO errRespDTO = new OAuth2TokenValidationResponseDTO(); - errRespDTO.setValid(false); - errRespDTO.setErrorMsg(e.getMessage()); - appDTO.setAccessTokenValidationResponse(errRespDTO); - return appDTO; - } + try { + return validationHandler.findOAuthConsumerIfTokenIsValid(validationReqDTO); + } catch (IdentityOAuth2Exception e) { + log.error("Error occurred while validating the OAuth2 access token", e); + OAuth2ClientApplicationDTO appDTO = new OAuth2ClientApplicationDTO(); + OAuth2TokenValidationResponseDTO errRespDTO = new OAuth2TokenValidationResponseDTO(); + errRespDTO.setValid(false); + errRespDTO.setErrorMsg(e.getMessage()); + appDTO.setAccessTokenValidationResponse(errRespDTO); + return appDTO; + } } /** * returns back the introspection response, which is compatible with RFC 7662. + * * @param validationReq * @return */ public OAuth2IntrospectionResponseDTO buildIntrospectionResponse(OAuth2TokenValidationRequestDTO validationReq) { - TokenValidationHandler validationHandler = TokenValidationHandler.getInstance(); + TokenValidationHandler validationHandler = TokenValidationHandler.getInstance(); - try { - return validationHandler.buildIntrospectionResponse(validationReq); - } catch (IdentityOAuth2Exception e) { - log.error("Error occurred while building the introspection response", e); - OAuth2IntrospectionResponseDTO response = new OAuth2IntrospectionResponseDTO(); - response.setActive(false); - response.setError(e.getMessage()); - return response; - } + try { + return validationHandler.buildIntrospectionResponse(validationReq); + } catch (IdentityOAuth2Exception e) { + log.error("Error occurred while building the introspection response", e); + OAuth2IntrospectionResponseDTO response = new OAuth2IntrospectionResponseDTO(); + response.setActive(false); + response.setError(e.getMessage()); + return response; + } } } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authcontext/DefaultClaimsRetriever.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authcontext/DefaultClaimsRetriever.java index fc2c518e084..2dc00f0fa8c 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authcontext/DefaultClaimsRetriever.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authcontext/DefaultClaimsRetriever.java @@ -56,6 +56,7 @@ public class DefaultClaimsRetriever implements ClaimsRetriever { */ @Override public void init() { + dialectURI = OAuthServerConfiguration.getInstance().getConsumerDialectURI(); if (dialectURI == null) { dialectURI = DEFAULT_DIALECT_URI; @@ -63,14 +64,15 @@ public void init() { } @Override - public SortedMap getClaims(String endUserName, String[] requestedClaims) throws IdentityOAuth2Exception { + public SortedMap getClaims(String endUserName, String[] requestedClaims) + throws IdentityOAuth2Exception { SortedMap claimValues; int tenantId = MultitenantConstants.SUPER_TENANT_ID; try { tenantId = OAuth2Util.getTenantIdFromUserName(endUserName); String tenantAwareUsername = MultitenantUtils.getTenantAwareUsername(endUserName); - UserStoreManager userStoreManager = OAuthComponentServiceHolder.getRealmService(). + UserStoreManager userStoreManager = OAuthComponentServiceHolder.getInstance().getRealmService(). getTenantUserRealm(tenantId).getUserStoreManager(); claimValues = new TreeMap(userStoreManager.getUserClaimValues(tenantAwareUsername, requestedClaims, null)); } catch (UserStoreException e) { @@ -86,11 +88,12 @@ public String[] getDefaultClaims(String endUserName) throws IdentityOAuth2Except try { tenantId = OAuth2Util.getTenantIdFromUserName(endUserName); // if no claims were requested, return all - if(log.isDebugEnabled()){ + if (log.isDebugEnabled()) { log.debug("No claims set requested. Returning all claims in the dialect"); } ClaimManager claimManager = - OAuthComponentServiceHolder.getRealmService().getTenantUserRealm(tenantId).getClaimManager(); + OAuthComponentServiceHolder.getInstance().getRealmService().getTenantUserRealm(tenantId) + .getClaimManager(); ClaimMapping[] claims = claimManager.getAllClaimMappings(dialectURI); return claimToString(claims); } catch (UserStoreException e) { @@ -103,6 +106,7 @@ public String[] getDefaultClaims(String endUserName) throws IdentityOAuth2Except * array of String objects corresponding to the ClaimURI values. */ private String[] claimToString(ClaimMapping[] claims) { + String[] temp = new String[claims.length]; for (int i = 0; i < claims.length; i++) { temp[i] = claims[i].getClaim().getClaimUri(); diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authcontext/JWTTokenGenerator.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authcontext/JWTTokenGenerator.java index 309db5fc62a..54a17c68287 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authcontext/JWTTokenGenerator.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authcontext/JWTTokenGenerator.java @@ -164,7 +164,7 @@ public void generateToken(OAuth2TokenValidationMessageContext messageContext) th String tenantDomain = OAuth2Util.getTenantDomain(tenantID); boolean isExistingUser = false; - RealmService realmService = OAuthComponentServiceHolder.getRealmService(); + RealmService realmService = OAuthComponentServiceHolder.getInstance().getRealmService(); // TODO : Need to handle situation where federated user name is similar to a one we have in our user store if (realmService != null && tenantID != MultitenantConstants.INVALID_TENANT_ID ) { try { @@ -530,7 +530,7 @@ private String getMultiAttributeSeparator(String authenticatedUser, int tenantId try { RealmConfiguration realmConfiguration = null; - RealmService realmService = OAuthComponentServiceHolder.getRealmService(); + RealmService realmService = OAuthComponentServiceHolder.getInstance().getRealmService(); if (realmService != null && tenantId != MultitenantConstants.INVALID_TENANT_ID) { UserStoreManager userStoreManager = (UserStoreManager) realmService.getTenantUserRealm(tenantId) diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/TokenResponseTypeHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/TokenResponseTypeHandler.java index 08335e1183e..51007d5a7d7 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/TokenResponseTypeHandler.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/TokenResponseTypeHandler.java @@ -30,6 +30,8 @@ import org.wso2.carbon.identity.oauth.cache.OAuthCacheKey; import org.wso2.carbon.identity.oauth.common.OAuthConstants; import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; +import org.wso2.carbon.identity.oauth.event.OauthEventListener; +import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext; import org.wso2.carbon.identity.oauth2.dto.OAuth2AuthorizeReqDTO; @@ -40,6 +42,7 @@ import java.sql.Timestamp; import java.util.Date; +import java.util.List; import java.util.UUID; public class TokenResponseTypeHandler extends AbstractResponseTypeHandler { @@ -50,6 +53,13 @@ public class TokenResponseTypeHandler extends AbstractResponseTypeHandler { public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx) throws IdentityOAuth2Exception { + List oauthListeners = OAuthComponentServiceHolder.getInstance().getOauthEventListeners(); + + for (OauthEventListener oauthListener : oauthListeners) { + oauthListener.onPreTokenIssue(oauthAuthzMsgCtx); + } + + OAuth2AuthorizeRespDTO respDTO = new OAuth2AuthorizeRespDTO(); OAuth2AuthorizeReqDTO authorizationReqDTO = oauthAuthzMsgCtx.getAuthorizationReqDTO(); @@ -91,6 +101,8 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx Timestamp refreshTokenIssuedTime = null; long refreshTokenValidityPeriodInMillis = 0; + AccessTokenDO tokenDO = null; + synchronized ((consumerKey + ":" + authorizedUser + ":" + scope).intern()) { // check if valid access token exists in cache @@ -107,9 +119,9 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx if (expireTime > 0 || expireTime < 0) { if (log.isDebugEnabled()) { - if(expireTime > 0) { - log.debug("Access Token"+ - " is valid for another " + expireTime + "ms"); + if (expireTime > 0) { + log.debug("Access Token" + + " is valid for another " + expireTime + "ms"); } else { log.debug("Infinite lifetime Access Token found in cache"); } @@ -117,13 +129,14 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx respDTO.setAccessToken(accessTokenDO.getAccessToken()); if (expireTime > 0) { - respDTO.setValidityPeriod(expireTime/1000); + respDTO.setValidityPeriod(expireTime / 1000); } else { - respDTO.setValidityPeriod(Long.MAX_VALUE/1000); + respDTO.setValidityPeriod(Long.MAX_VALUE / 1000); } respDTO.setScope(oauthAuthzMsgCtx.getApprovedScope()); respDTO.setTokenType(accessTokenDO.getTokenType()); buildIdToken(oauthAuthzMsgCtx, respDTO); + triggerPostListeners(oauthListeners,oauthAuthzMsgCtx,accessTokenDO,respDTO); return respDTO; } else { @@ -177,7 +190,7 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx // token is active and valid if (log.isDebugEnabled()) { - if(expiryTime > 0) { + if (expiryTime > 0) { log.debug("Access token is valid for another " + expiryTime + "ms"); } else { log.debug("Infinite lifetime Access Token found in cache"); @@ -194,7 +207,7 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx respDTO.setAccessToken(existingAccessTokenDO.getAccessToken()); - if(expiryTime > 0) { + if (expiryTime > 0) { respDTO.setValidityPeriod(expiryTime / 1000); } else { respDTO.setValidityPeriod(Long.MAX_VALUE / 1000); @@ -204,7 +217,7 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx respDTO.setTokenType(existingAccessTokenDO.getTokenType()); buildIdToken(oauthAuthzMsgCtx, respDTO); - + triggerPostListeners(oauthListeners, oauthAuthzMsgCtx, existingAccessTokenDO, respDTO); return respDTO; } else { @@ -224,7 +237,8 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx } refreshToken = existingAccessTokenDO.getRefreshToken(); refreshTokenIssuedTime = existingAccessTokenDO.getRefreshTokenIssuedTime(); - refreshTokenValidityPeriodInMillis = existingAccessTokenDO.getRefreshTokenValidityPeriodInMillis(); + refreshTokenValidityPeriodInMillis = + existingAccessTokenDO.getRefreshTokenValidityPeriodInMillis(); } if (log.isDebugEnabled()) { @@ -249,7 +263,7 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx Timestamp timestamp = new Timestamp(new Date().getTime()); // if reusing existing refresh token, use its original issued time - if(refreshTokenIssuedTime == null) { + if (refreshTokenIssuedTime == null) { refreshTokenIssuedTime = timestamp; } // Default token validity Period @@ -265,39 +279,39 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx // If issuing new refresh token, use default refresh token validity Period // otherwise use existing refresh token's validity period - if(refreshTokenValidityPeriodInMillis == 0) { + if (refreshTokenValidityPeriodInMillis == 0) { refreshTokenValidityPeriodInMillis = OAuthServerConfiguration.getInstance() .getRefreshTokenValidityPeriodInSeconds() * 1000; } - + // issue a new access token String accessToken; - + // set the validity period. this is needed by downstream handlers. // if this is set before - then this will override it by the calculated new value. oauthAuthzMsgCtx.setValidityPeriod(validityPeriodInMillis); - + // set the refresh token validity period. this is needed by downstream handlers. // if this is set before - then this will override it by the calculated new value. oauthAuthzMsgCtx.setRefreshTokenvalidityPeriod(refreshTokenValidityPeriodInMillis); - + // set access token issued time.this is needed by downstream handlers. oauthAuthzMsgCtx.setAccessTokenIssuedTime(timestamp.getTime()); - + // set refresh token issued time.this is needed by downstream handlers. oauthAuthzMsgCtx.setRefreshTokenIssuedTime(refreshTokenIssuedTime.getTime()); - try { - accessToken = oauthIssuerImpl.accessToken(); + try { + accessToken = oauthIssuerImpl.accessToken(); - // regenerate only if refresh token is null - if (refreshToken == null) { - refreshToken = oauthIssuerImpl.refreshToken(); - } + // regenerate only if refresh token is null + if (refreshToken == null) { + refreshToken = oauthIssuerImpl.refreshToken(); + } - } catch (OAuthSystemException e) { - throw new IdentityOAuth2Exception("Error occurred while generating access token and refresh token", e); - } + } catch (OAuthSystemException e) { + throw new IdentityOAuth2Exception("Error occurred while generating access token and refresh token", e); + } if (OAuth2Util.checkUserNameAssertionEnabled()) { String userName = oauthAuthzMsgCtx.getAuthorizationReqDTO().getUser().toString(); @@ -309,9 +323,11 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx refreshToken = Base64Utils.encode(refreshTokenStrToEncode.getBytes(Charsets.UTF_8)); } - AccessTokenDO newAccessTokenDO = new AccessTokenDO(consumerKey, authorizationReqDTO.getUser(), oauthAuthzMsgCtx.getApprovedScope(), timestamp, - refreshTokenIssuedTime, validityPeriodInMillis, refreshTokenValidityPeriodInMillis, - OAuthConstants.UserType.APPLICATION_USER); + AccessTokenDO newAccessTokenDO = + new AccessTokenDO(consumerKey, authorizationReqDTO.getUser(), oauthAuthzMsgCtx.getApprovedScope(), + timestamp, + refreshTokenIssuedTime, validityPeriodInMillis, refreshTokenValidityPeriodInMillis, + OAuthConstants.UserType.APPLICATION_USER); newAccessTokenDO.setAccessToken(accessToken); newAccessTokenDO.setRefreshToken(refreshToken); @@ -322,22 +338,22 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx // Persist the access token in database try { tokenMgtDAO.storeAccessToken(accessToken, authorizationReqDTO.getConsumerKey(), - newAccessTokenDO, existingAccessTokenDO, userStoreDomain); + newAccessTokenDO, existingAccessTokenDO, userStoreDomain); } catch (IdentityException e) { throw new IdentityOAuth2Exception( - "Error occurred while storing new access token : " + accessToken, e); + "Error occurred while storing new access token : " + accessToken, e); } - + tokenDO = newAccessTokenDO; if (log.isDebugEnabled()) { log.debug("Persisted Access Token for " + - "Client ID : " + authorizationReqDTO.getConsumerKey() + - ", Authorized User : " + authorizationReqDTO.getUser() + - ", Timestamp : " + timestamp + - ", Validity period (s) : " + newAccessTokenDO.getValidityPeriod() + - ", Scope : " + OAuth2Util.buildScopeString(oauthAuthzMsgCtx.getApprovedScope()) + - ", Callback URL : " + authorizationReqDTO.getCallbackUrl() + - ", Token State : " + OAuthConstants.TokenStates.TOKEN_STATE_ACTIVE + - " and User Type : " + OAuthConstants.UserType.APPLICATION_USER); + "Client ID : " + authorizationReqDTO.getConsumerKey() + + ", Authorized User : " + authorizationReqDTO.getUser() + + ", Timestamp : " + timestamp + + ", Validity period (s) : " + newAccessTokenDO.getValidityPeriod() + + ", Scope : " + OAuth2Util.buildScopeString(oauthAuthzMsgCtx.getApprovedScope()) + + ", Callback URL : " + authorizationReqDTO.getCallbackUrl() + + ", Token State : " + OAuthConstants.TokenStates.TOKEN_STATE_ACTIVE + + " and User Type : " + OAuthConstants.UserType.APPLICATION_USER); } // Add the access token to the cache. @@ -349,7 +365,7 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx } } - if(StringUtils.contains(responseType, ResponseType.TOKEN.toString())) { + if (StringUtils.contains(responseType, ResponseType.TOKEN.toString())) { respDTO.setAccessToken(accessToken); if (validityPeriodInMillis > 0) { @@ -364,11 +380,24 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx } buildIdToken(oauthAuthzMsgCtx, respDTO); + triggerPostListeners(oauthListeners, oauthAuthzMsgCtx, tokenDO, respDTO); return respDTO; } + private void triggerPostListeners(List oauthListeners, OAuthAuthzReqMessageContext + oauthAuthzMsgCtx, AccessTokenDO tokenDO, OAuth2AuthorizeRespDTO respDTO) { + + for (OauthEventListener oauthListener : oauthListeners) { + try { + oauthListener.onPostTokenIssue(oauthAuthzMsgCtx, tokenDO, respDTO); + } catch (IdentityOAuth2Exception e) { + log.error("Oauth post token issue listener " + oauthListener.getClass().getName() + " failed.", e); + } + } + } + private void buildIdToken(OAuthAuthzReqMessageContext msgCtx, OAuth2AuthorizeRespDTO authzRespDTO) - throws IdentityOAuth2Exception{ + throws IdentityOAuth2Exception { if (StringUtils.contains(msgCtx.getAuthorizationReqDTO().getResponseType(), "id_token") && msgCtx.getApprovedScope() != null && OAuth2Util.isOIDCAuthzRequest(msgCtx.getApprovedScope())) { diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java index 53b77f32acb..8d1c11345ae 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java @@ -23,7 +23,6 @@ import org.apache.oltu.oauth2.common.error.OAuthError; import org.apache.oltu.oauth2.common.message.types.GrantType; import org.wso2.carbon.identity.base.IdentityException; -import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; import org.wso2.carbon.identity.oauth.cache.AppInfoCache; import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCache; import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCacheEntry; @@ -32,6 +31,9 @@ import org.wso2.carbon.identity.oauth.common.exception.InvalidOAuthClientException; import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; import org.wso2.carbon.identity.oauth.dao.OAuthAppDAO; +import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; +import org.wso2.carbon.identity.oauth.event.OauthEventListener; +import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; import org.wso2.carbon.identity.oauth2.ResponseHeader; import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO; @@ -77,6 +79,7 @@ private AccessTokenIssuer() throws IdentityOAuth2Exception { } } + /** * Singleton method * @@ -109,10 +112,26 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) String grantType = tokenReqDTO.getGrantType(); OAuth2AccessTokenRespDTO tokenRespDTO; + List oauthEventListeners = + OAuthComponentServiceHolder.getInstance().getOauthEventListeners(); AuthorizationGrantHandler authzGrantHandler = authzGrantHandlers.get(grantType); OAuthTokenReqMessageContext tokReqMsgCtx = new OAuthTokenReqMessageContext(tokenReqDTO); + boolean isRefreshRequest = GrantType.REFRESH_TOKEN.toString().equals(grantType); + + if (isRefreshRequest) { + for (OauthEventListener eventListener : oauthEventListeners) { + //If listener fail, it will throw an exception and stop the token issue process + eventListener.onPreTokenRenewal(tokenReqDTO, tokReqMsgCtx); + } + } else { + for (OauthEventListener eventListener : oauthEventListeners) { + //If listener fail, it will throw an exception and stop the token issue process + eventListener.onPreTokenIssue(tokenReqDTO, tokReqMsgCtx); + } + } + // If multiple client authentication methods have been used the authorization server must reject the request int authenticatorHandlerIndex = -1; @@ -125,6 +144,8 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) OAuthConstants.OAuthError.TokenResponse.UNSUPPORTED_CLIENT_AUTHENTICATION_METHOD, "Unsupported Client Authentication Method!", tokenReqDTO); setResponseHeaders(tokReqMsgCtx, tokenRespDTO); + triggerPostListeners(oauthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, + isRefreshRequest); return tokenRespDTO; } authenticatorHandlerIndex = i; @@ -137,6 +158,8 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) OAuthConstants.OAuthError.TokenResponse.UNSUPPORTED_CLIENT_AUTHENTICATION_METHOD, "Unsupported Client Authentication Method!", tokenReqDTO); setResponseHeaders(tokReqMsgCtx, tokenRespDTO); + triggerPostListeners(oauthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, + isRefreshRequest); return tokenRespDTO; } @@ -151,12 +174,14 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) isAuthenticated = true; } if (!isAuthenticated) { - if(log.isDebugEnabled()) { + if (log.isDebugEnabled()) { log.debug("Client Authentication failed for client Id: " + tokenReqDTO.getClientId()); } tokenRespDTO = handleError(OAuthError.TokenResponse.INVALID_CLIENT, "Client credentials are invalid.", tokenReqDTO); setResponseHeaders(tokReqMsgCtx, tokenRespDTO); + triggerPostListeners(oauthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, + isRefreshRequest); return tokenRespDTO; } @@ -171,7 +196,7 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) try { isValidGrant = authzGrantHandler.validateGrant(tokReqMsgCtx); } catch (IdentityOAuth2Exception e) { - if(log.isDebugEnabled()){ + if (log.isDebugEnabled()) { log.debug("Error occurred while validating grant", e); } error = e.getMessage(); @@ -183,40 +208,48 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) } tokenRespDTO = handleError(OAuthError.TokenResponse.INVALID_GRANT, error, tokenReqDTO); setResponseHeaders(tokReqMsgCtx, tokenRespDTO); + triggerPostListeners(oauthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, + isRefreshRequest); return tokenRespDTO; } boolean isAuthorized = authzGrantHandler.authorizeAccessDelegation(tokReqMsgCtx); if (!isAuthorized) { - if(log.isDebugEnabled()) { + if (log.isDebugEnabled()) { log.debug("Invalid authorization for client Id = " + tokenReqDTO.getClientId()); } tokenRespDTO = handleError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT, "Unauthorized Client!", tokenReqDTO); setResponseHeaders(tokReqMsgCtx, tokenRespDTO); + triggerPostListeners(oauthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, + isRefreshRequest); return tokenRespDTO; } boolean isValidScope = authzGrantHandler.validateScope(tokReqMsgCtx); if (!isValidScope) { - if(log.isDebugEnabled()) { + if (log.isDebugEnabled()) { log.debug("Invalid scope provided by client Id: " + tokenReqDTO.getClientId()); } tokenRespDTO = handleError(OAuthError.TokenResponse.INVALID_SCOPE, "Invalid Scope!", tokenReqDTO); setResponseHeaders(tokReqMsgCtx, tokenRespDTO); + triggerPostListeners(oauthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, + isRefreshRequest); return tokenRespDTO; } - try { - // set the token request context to be used by downstream handlers. This is introduced as a fix for - // IDENTITY-4111. - OAuth2Util.setTokenRequestContext(tokReqMsgCtx); - tokenRespDTO = authzGrantHandler.issue(tokReqMsgCtx); - } finally { - // clears the token request context. - OAuth2Util.clearTokenRequestContext(); - } - + try { + // set the token request context to be used by downstream handlers. This is introduced as a fix for + // IDENTITY-4111. + OAuth2Util.setTokenRequestContext(tokReqMsgCtx); + tokenRespDTO = authzGrantHandler.issue(tokReqMsgCtx); + triggerPostListeners(oauthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, + isRefreshRequest); + } finally { + // clears the token request context. + OAuth2Util.clearTokenRequestContext(); + } + tokenRespDTO.setCallbackURI(oAuthAppDO.getCallbackUrl()); String[] scopes = tokReqMsgCtx.getScope(); @@ -249,6 +282,29 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) return tokenRespDTO; } + private void triggerPostListeners(List listeners, OAuth2AccessTokenReqDTO tokenReqDTO, + OAuth2AccessTokenRespDTO tokenRespDTO, OAuthTokenReqMessageContext tokReqMsgCtx, + boolean isRefresh) { + + if (isRefresh) { + for (OauthEventListener listener : listeners) { + try { + listener.onPostTokenRenewal(tokenReqDTO, tokenRespDTO, tokReqMsgCtx); + } catch (IdentityOAuth2Exception e) { + log.error("Oauth post renewal listener " + listener.getClass().getName() + " failed.", e); + } + } + } else { + for (OauthEventListener listener : listeners) { + try { + listener.onPostTokenIssue(tokenReqDTO, tokenRespDTO, tokReqMsgCtx); + } catch (IdentityOAuth2Exception e) { + log.error("Oauth post issuer listener " + listener.getClass().getName() + " failed.", e); + } + } + } + } + /** * Add user attributes to cache. * @@ -256,20 +312,23 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) * @param tokenRespDTO */ private void addUserAttributesToCache(OAuth2AccessTokenReqDTO tokenReqDTO, OAuth2AccessTokenRespDTO tokenRespDTO) { + AuthorizationGrantCacheKey oldCacheKey = new AuthorizationGrantCacheKey(tokenReqDTO.getAuthorizationCode()); //checking getUserAttributesId value of cacheKey before retrieve entry from cache as it causes to NPE if (oldCacheKey.getUserAttributesId() != null) { - AuthorizationGrantCacheEntry authorizationGrantCacheEntry = AuthorizationGrantCache.getInstance().getValueFromCacheByCode(oldCacheKey); + AuthorizationGrantCacheEntry authorizationGrantCacheEntry = + AuthorizationGrantCache.getInstance().getValueFromCacheByCode(oldCacheKey); AuthorizationGrantCacheKey newCacheKey = new AuthorizationGrantCacheKey(tokenRespDTO.getAccessToken()); authorizationGrantCacheEntry.setTokenId(tokenRespDTO.getTokenId()); if (AuthorizationGrantCache.getInstance().getValueFromCacheByToken(newCacheKey) == null) { - if(log.isDebugEnabled()){ - log.debug("No AuthorizationGrantCache entry found for the access token:"+ newCacheKey.getUserAttributesId()+ - ", hence adding to cache"); + if (log.isDebugEnabled()) { + log.debug("No AuthorizationGrantCache entry found for the access token:" + + newCacheKey.getUserAttributesId() + + ", hence adding to cache"); } AuthorizationGrantCache.getInstance().addToCacheByToken(newCacheKey, authorizationGrantCacheEntry); AuthorizationGrantCache.getInstance().clearCacheEntryByCode(oldCacheKey); - } else{ + } else { //if the user attributes are already saved for access token, no need to add again. } } @@ -283,7 +342,9 @@ private void addUserAttributesToCache(OAuth2AccessTokenReqDTO tokenReqDTO, OAuth * @throws IdentityOAuth2Exception * @throws InvalidOAuthClientException */ - private OAuthAppDO getAppInformation(OAuth2AccessTokenReqDTO tokenReqDTO) throws IdentityOAuth2Exception, InvalidOAuthClientException { + private OAuthAppDO getAppInformation(OAuth2AccessTokenReqDTO tokenReqDTO) + throws IdentityOAuth2Exception, InvalidOAuthClientException { + OAuthAppDO oAuthAppDO = appInfoCache.getValueFromCache(tokenReqDTO.getClientId()); if (oAuthAppDO != null) { return oAuthAppDO; @@ -305,6 +366,7 @@ private OAuthAppDO getAppInformation(OAuth2AccessTokenReqDTO tokenReqDTO) throws private OAuth2AccessTokenRespDTO handleError(String errorCode, String errorMsg, OAuth2AccessTokenReqDTO tokenReqDTO) { + if (log.isDebugEnabled()) { log.debug("OAuth-Error-Code=" + errorCode + " client-id=" + tokenReqDTO.getClientId() + " grant-type=" + tokenReqDTO.getGrantType() @@ -320,11 +382,13 @@ private OAuth2AccessTokenRespDTO handleError(String errorCode, /** * Set headers in OAuth2AccessTokenRespDTO + * * @param tokReqMsgCtx * @param tokenRespDTO */ private void setResponseHeaders(OAuthTokenReqMessageContext tokReqMsgCtx, OAuth2AccessTokenRespDTO tokenRespDTO) { + if (tokReqMsgCtx.getProperty("RESPONSE_HEADERS") != null) { tokenRespDTO.setResponseHeaders((ResponseHeader[]) tokReqMsgCtx.getProperty("RESPONSE_HEADERS")); } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/PasswordGrantHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/PasswordGrantHandler.java index 6798e28f317..27060e802eb 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/PasswordGrantHandler.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/grant/PasswordGrantHandler.java @@ -88,7 +88,7 @@ public boolean validateGrant(OAuthTokenReqMessageContext tokReqMsgCtx) return false; } - RealmService realmService = OAuthComponentServiceHolder.getRealmService(); + RealmService realmService = OAuthComponentServiceHolder.getInstance().getRealmService(); UserStoreManager userStoreManager = null; boolean authStatus; try { diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/OAuth2Util.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/OAuth2Util.java index b894becb54d..31f84179e58 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/OAuth2Util.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/OAuth2Util.java @@ -596,7 +596,7 @@ public static long getAccessTokenExpireMillis(AccessTokenDO accessTokenDO) { } public static int getTenantId(String tenantDomain) throws IdentityOAuth2Exception { - RealmService realmService = OAuthComponentServiceHolder.getRealmService(); + RealmService realmService = OAuthComponentServiceHolder.getInstance().getRealmService(); try { return realmService.getTenantManager().getTenantId(tenantDomain); } catch (UserStoreException e) { @@ -606,7 +606,7 @@ public static int getTenantId(String tenantDomain) throws IdentityOAuth2Exceptio } public static String getTenantDomain(int tenantId) throws IdentityOAuth2Exception { - RealmService realmService = OAuthComponentServiceHolder.getRealmService(); + RealmService realmService = OAuthComponentServiceHolder.getInstance().getRealmService(); try { return realmService.getTenantManager().getDomain(tenantId); } catch (UserStoreException e) { diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/JDBCScopeValidator.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/JDBCScopeValidator.java index 17d1a5ae6af..e81046571a5 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/JDBCScopeValidator.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/validators/JDBCScopeValidator.java @@ -134,7 +134,7 @@ public boolean validateScope(AccessTokenDO accessTokenDO, String resource) throw } User authzUser = accessTokenDO.getAuthzUser(); - RealmService realmService = OAuthComponentServiceHolder.getRealmService(); + RealmService realmService = OAuthComponentServiceHolder.getInstance().getRealmService(); int tenantId = realmService.getTenantManager(). getTenantId(authzUser.getTenantDomain()); From 34261782c88b94a53cdd45ad7e51568d00046c27 Mon Sep 17 00:00:00 2001 From: Pulasthi Mahawithana Date: Wed, 16 Mar 2016 17:35:56 +0530 Subject: [PATCH 2/2] Fixing the suggestions at PR --- .../identity/oauth/OAuthAdminService.java | 31 ++++++----- ...tListener.java => OAuthEventListener.java} | 2 +- .../internal/OAuthComponentServiceHolder.java | 30 +++++----- .../oauth/internal/OAuthServiceComponent.java | 32 ++++++----- .../carbon/identity/oauth2/OAuth2Service.java | 41 +++++++++----- .../oauth2/OAuth2TokenValidationService.java | 47 ++++++++++------ .../handlers/TokenResponseTypeHandler.java | 36 +++++++----- .../oauth2/token/AccessTokenIssuer.java | 55 +++++++++++-------- 8 files changed, 162 insertions(+), 112 deletions(-) rename components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/event/{OauthEventListener.java => OAuthEventListener.java} (99%) diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthAdminService.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthAdminService.java index 62fde6fa3e3..7a458591fa2 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthAdminService.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/OAuthAdminService.java @@ -40,7 +40,7 @@ import org.wso2.carbon.identity.oauth.dto.OAuthConsumerAppDTO; import org.wso2.carbon.identity.oauth.dto.OAuthRevocationRequestDTO; import org.wso2.carbon.identity.oauth.dto.OAuthRevocationResponseDTO; -import org.wso2.carbon.identity.oauth.event.OauthEventListener; +import org.wso2.carbon.identity.oauth.event.OAuthEventListener; import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; import org.wso2.carbon.identity.oauth2.dao.TokenMgtDAO; @@ -436,17 +436,9 @@ public OAuthConsumerAppDTO[] getAppsAuthorizedByUser() throws IdentityOAuthAdmin public OAuthRevocationResponseDTO revokeAuthzForAppsByResoureOwner( OAuthRevocationRequestDTO revokeRequestDTO) throws IdentityOAuthAdminException { - List oauthListeners = OAuthComponentServiceHolder.getInstance().getOauthEventListeners(); - - for (OauthEventListener listener : oauthListeners) { - try { - listener.onPreTokenRevocationByResourceOwner(revokeRequestDTO); - } catch (IdentityOAuth2Exception e) { - throw new IdentityOAuthAdminException("Error occured with Oauth pre-revoke listner " + listener - .getClass().getName(), e); - } - } + List oauthListeners = OAuthComponentServiceHolder.getInstance().getoAuthEventListeners(); + triggerPreRevokeListeners(oauthListeners, revokeRequestDTO); TokenMgtDAO tokenMgtDAO = new TokenMgtDAO(); if (revokeRequestDTO.getApps() != null && revokeRequestDTO.getApps().length > 0) { @@ -545,12 +537,25 @@ public OAuthRevocationResponseDTO revokeAuthzForAppsByResoureOwner( return new OAuthRevocationResponseDTO(); } - private void triggerPostRevokeListeners(List oauthListeners, + private void triggerPreRevokeListeners(List oauthListeners, OAuthRevocationRequestDTO + revokeRequestDTO) throws IdentityOAuthAdminException { + + for (OAuthEventListener listener : oauthListeners) { + try { + listener.onPreTokenRevocationByResourceOwner(revokeRequestDTO); + } catch (IdentityOAuth2Exception e) { + throw new IdentityOAuthAdminException("Error occurred with Oauth pre-revoke listener " + listener + .getClass().getName(), e); + } + } + } + + private void triggerPostRevokeListeners(List oauthListeners, OAuthRevocationRequestDTO revokeRequestDTO, OAuthRevocationResponseDTO revokeRespDTO, AccessTokenDO[] accessTokenDOs) { for (AccessTokenDO accessTokenDO : accessTokenDOs) { - for (OauthEventListener listener : oauthListeners) { + for (OAuthEventListener listener : oauthListeners) { try { listener.onPostTokenRevocationByResourceOwner(revokeRequestDTO, revokeRespDTO, accessTokenDO); } catch (IdentityOAuth2Exception e) { diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/event/OauthEventListener.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/event/OAuthEventListener.java similarity index 99% rename from components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/event/OauthEventListener.java rename to components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/event/OAuthEventListener.java index 3417555c0f6..9e4d1bb04b1 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/event/OauthEventListener.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/event/OAuthEventListener.java @@ -31,7 +31,7 @@ import org.wso2.carbon.identity.oauth2.model.RefreshTokenValidationDataDO; import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext; -public interface OauthEventListener { +public interface OAuthEventListener { /** * Called prior to issuing tokens. diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthComponentServiceHolder.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthComponentServiceHolder.java index 692264347af..c4875a131ad 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthComponentServiceHolder.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthComponentServiceHolder.java @@ -20,7 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.identity.oauth.event.OauthEventListener; +import org.wso2.carbon.identity.oauth.event.OAuthEventListener; import org.wso2.carbon.registry.api.RegistryService; import org.wso2.carbon.user.core.service.RealmService; @@ -32,10 +32,10 @@ public class OAuthComponentServiceHolder { private static OAuthComponentServiceHolder instance = new OAuthComponentServiceHolder(); private RegistryService registryService; private RealmService realmService; - private List oauthEventListeners; + private List oAuthEventListeners; private static Log log = LogFactory.getLog(OAuthComponentServiceHolder.class); - private OAuthComponentServiceHolder(){ + private OAuthComponentServiceHolder() { } @@ -64,29 +64,29 @@ public void setRealmService(RealmService realmService) { this.realmService = realmService; } - public void addOauthEventListener(OauthEventListener oauthEventListener) { + public void addOauthEventListener(OAuthEventListener oAuthEventListener) { - if (oauthEventListeners == null) { - oauthEventListeners = new ArrayList<>(); + if (oAuthEventListeners == null) { + oAuthEventListeners = new ArrayList<>(); } - oauthEventListeners.add(oauthEventListener); + oAuthEventListeners.add(oAuthEventListener); } - public void removeOauthEventListener(OauthEventListener oauthEventListener) { + public void removeOauthEventListener(OAuthEventListener OAuthEventListener) { - if (oauthEventListeners != null && oauthEventListener != null) { - boolean isRemoved = oauthEventListeners.remove(oauthEventListener); + if (oAuthEventListeners != null && OAuthEventListener != null) { + boolean isRemoved = oAuthEventListeners.remove(OAuthEventListener); if (!isRemoved) { - log.warn(oauthEventListener.getClass().getName() + " had not been registered as a listener"); + log.warn(OAuthEventListener.getClass().getName() + " had not been registered as a listener"); } } } - public List getOauthEventListeners() { + public List getoAuthEventListeners() { - if (oauthEventListeners == null) { - oauthEventListeners = new ArrayList<>(); + if (oAuthEventListeners == null) { + oAuthEventListeners = new ArrayList<>(); } - return oauthEventListeners; + return oAuthEventListeners; } } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthServiceComponent.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthServiceComponent.java index 22f45acb31c..271bbeb8dbd 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthServiceComponent.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/internal/OAuthServiceComponent.java @@ -24,7 +24,7 @@ import org.osgi.service.component.ComponentContext; import org.wso2.carbon.identity.oauth.cache.OAuthCache; import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; -import org.wso2.carbon.identity.oauth.event.OauthEventListener; +import org.wso2.carbon.identity.oauth.event.OAuthEventListener; import org.wso2.carbon.identity.oauth.listener.IdentityOathEventListener; import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.user.core.listener.UserOperationEventListener; @@ -36,8 +36,8 @@ * interface="org.wso2.carbon.registry.core.service.RegistryService" * cardinality="1..1" policy="dynamic" bind="setRegistryService" * unbind="unsetRegistryService" - * @scr.reference name="org.wso2.carbon.identity.oauth.event.OauthEventListener" - * interface="org.wso2.carbon.identity.oauth.event.OauthEventListener" + * @scr.reference name="org.wso2.carbon.identity.oauth.event.OAuthEventListener" + * interface="org.wso2.carbon.identity.oauth.event.OAuthEventListener" * cardinality="0..n" policy="dynamic" * bind="setOauthEventListener" * unbind="unsetOauthEventListener" @@ -46,6 +46,7 @@ * policy="dynamic" bind="setRealmService" unbind="unsetRealmService" */ public class OAuthServiceComponent { + private static Log log = LogFactory.getLog(OAuthServiceComponent.class); private static IdentityOathEventListener listener = null; private ServiceRegistration serviceRegistration = null; @@ -76,6 +77,7 @@ protected void activate(ComponentContext context) { } protected void deactivate(ComponentContext context) { + if (serviceRegistration != null) { serviceRegistration.unregister(); } @@ -85,6 +87,7 @@ protected void deactivate(ComponentContext context) { } protected void setRegistryService(RegistryService registryService) { + if (log.isDebugEnabled()) { log.debug("RegistryService set in Identity OAuth bundle"); } @@ -92,6 +95,7 @@ protected void setRegistryService(RegistryService registryService) { } protected void unsetRegistryService(RegistryService registryService) { + if (log.isDebugEnabled()) { log.debug("RegistryService unset in Identity OAuth bundle"); } @@ -99,6 +103,7 @@ protected void unsetRegistryService(RegistryService registryService) { } protected void setRealmService(RealmService realmService) { + if (log.isDebugEnabled()) { log.debug("Setting the Realm Service"); } @@ -106,35 +111,36 @@ protected void setRealmService(RealmService realmService) { } protected void unsetRealmService(RealmService realmService) { + if (log.isDebugEnabled()) { log.debug("Unsetting the Realm Service"); } OAuthComponentServiceHolder.getInstance().setRealmService(null); } - protected void setOauthEventListener(OauthEventListener oauthEventListener) { + protected void setOauthEventListener(OAuthEventListener oAuthEventListener) { - if (oauthEventListener == null) { - log.warn("Null OauthEventListener received, hence not registering"); + if (oAuthEventListener == null) { + log.warn("Null OAuthEventListener received, hence not registering"); return; } if (log.isDebugEnabled()) { - log.debug("Setting OauthEventListener :" + oauthEventListener.getClass().getName()); + log.debug("Setting OAuthEventListener :" + oAuthEventListener.getClass().getName()); } - OAuthComponentServiceHolder.getInstance().addOauthEventListener(oauthEventListener); + OAuthComponentServiceHolder.getInstance().addOauthEventListener(oAuthEventListener); } - protected void unsetOauthEventListener(OauthEventListener oauthEventListener) { + protected void unsetOauthEventListener(OAuthEventListener oAuthEventListener) { - if (oauthEventListener == null) { - log.warn("Null OauthEventListener received, hence not unregistering"); + if (oAuthEventListener == null) { + log.warn("Null oAuthEventListener received, hence not unregistering"); return; } if (log.isDebugEnabled()) { - log.debug("Unsetting OauthEventListener :" + oauthEventListener.getClass().getName()); + log.debug("Unsetting oAuthEventListener :" + oAuthEventListener.getClass().getName()); } - OAuthComponentServiceHolder.getInstance().removeOauthEventListener(oauthEventListener); + OAuthComponentServiceHolder.getInstance().removeOauthEventListener(oAuthEventListener); } } \ No newline at end of file diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2Service.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2Service.java index aa095bb994f..e934729fc8d 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2Service.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2Service.java @@ -32,7 +32,7 @@ import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; import org.wso2.carbon.identity.oauth.dao.OAuthAppDAO; import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; -import org.wso2.carbon.identity.oauth.event.OauthEventListener; +import org.wso2.carbon.identity.oauth.event.OAuthEventListener; import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; import org.wso2.carbon.identity.oauth2.authz.AuthorizationHandlerManager; import org.wso2.carbon.identity.oauth2.dao.TokenMgtDAO; @@ -243,19 +243,17 @@ public OAuthRevocationResponseDTO revokeTokenByOAuthClient(OAuthRevocationReques //fix here remove associated cache entry TokenMgtDAO tokenMgtDAO = new TokenMgtDAO(); OAuthRevocationResponseDTO revokeResponseDTO = new OAuthRevocationResponseDTO(); - List oauthListeners = OAuthComponentServiceHolder.getInstance().getOauthEventListeners(); + List oauthListeners = OAuthComponentServiceHolder.getInstance().getoAuthEventListeners(); //Invoke pre listeners - for (OauthEventListener listener : oauthListeners) { - try { - listener.onPreTokenRevocationByClient(revokeRequestDTO); - } catch (IdentityOAuth2Exception e) { - log.error("Error occurred while invoking pre-revoke listener: " + listener.getClass().getName(), e); - revokeResponseDTO.setError(true); - revokeResponseDTO.setErrorCode(OAuth2ErrorCodes.SERVER_ERROR); - revokeResponseDTO.setErrorMsg("Error occurred while revoking authorization grant for applications"); - return revokeResponseDTO; - } + try { + invokePreRevocationListeners(oauthListeners, revokeRequestDTO); + } catch (IdentityOAuth2Exception e) { + log.error(e); + revokeResponseDTO.setError(true); + revokeResponseDTO.setErrorCode(OAuth2ErrorCodes.SERVER_ERROR); + revokeResponseDTO.setErrorMsg("Error occurred while revoking authorization grant for applications"); + return revokeResponseDTO; } RefreshTokenValidationDataDO refreshTokenDO = null; @@ -388,16 +386,29 @@ public OAuthRevocationResponseDTO revokeTokenByOAuthClient(OAuthRevocationReques } } - private void invokePostRevocationListeners(List listeners, OAuthRevocationRequestDTO + private void invokePreRevocationListeners(List listeners, OAuthRevocationRequestDTO + revokeRequestDTO) throws IdentityOAuth2Exception { + + for (OAuthEventListener listener : listeners) { + try { + listener.onPreTokenRevocationByClient(revokeRequestDTO); + } catch (IdentityOAuth2Exception e) { + throw new IdentityOAuth2Exception("Error occured when invoking pre token revoke listener " + listener + .getClass().getName(), e); + } + } + } + + private void invokePostRevocationListeners(List listeners, OAuthRevocationRequestDTO revokeRequestDTO, OAuthRevocationResponseDTO revokeResponseDTO, AccessTokenDO accessTokenDO, RefreshTokenValidationDataDO refreshTokenDO) { - for (OauthEventListener listener : listeners) { + for (OAuthEventListener listener : listeners) { try { listener.onPostTokenRevocationByClient(revokeRequestDTO, revokeResponseDTO, accessTokenDO, refreshTokenDO); } catch (IdentityOAuth2Exception e) { - log.error("Error occured when invoking post token revoke listner " + listener.getClass().getName(), e); + log.error("Error occured when invoking post token revoke listener " + listener.getClass().getName(), e); } } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2TokenValidationService.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2TokenValidationService.java index 500e2138733..0426a04de60 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2TokenValidationService.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/OAuth2TokenValidationService.java @@ -21,7 +21,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.core.AbstractAdmin; -import org.wso2.carbon.identity.oauth.event.OauthEventListener; +import org.wso2.carbon.identity.oauth.event.OAuthEventListener; import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; import org.wso2.carbon.identity.oauth2.dto.OAuth2ClientApplicationDTO; import org.wso2.carbon.identity.oauth2.dto.OAuth2IntrospectionResponseDTO; @@ -45,17 +45,16 @@ public class OAuth2TokenValidationService extends AbstractAdmin { public OAuth2TokenValidationResponseDTO validate(OAuth2TokenValidationRequestDTO validationReqDTO) { TokenValidationHandler validationHandler = TokenValidationHandler.getInstance(); - List oauthEventListeners = - OAuthComponentServiceHolder.getInstance().getOauthEventListeners(); - for (OauthEventListener oauthEventListener : oauthEventListeners) { - try { - oauthEventListener.onPreTokenValidation(validationReqDTO); - } catch (IdentityOAuth2Exception e) { - OAuth2TokenValidationResponseDTO errRespDTO = new OAuth2TokenValidationResponseDTO(); - errRespDTO.setValid(false); - errRespDTO.setErrorMsg(e.getMessage()); - return errRespDTO; - } + List oAuthEventListeners = + OAuthComponentServiceHolder.getInstance().getoAuthEventListeners(); + //trigger pre listeners + try { + triggerPreValidationListeners(oAuthEventListeners, validationReqDTO); + } catch (IdentityOAuth2Exception e) { + OAuth2TokenValidationResponseDTO errRespDTO = new OAuth2TokenValidationResponseDTO(); + errRespDTO.setValid(false); + errRespDTO.setErrorMsg(e.getMessage()); + return errRespDTO; } OAuth2TokenValidationResponseDTO responseDTO = null; try { @@ -67,15 +66,31 @@ public OAuth2TokenValidationResponseDTO validate(OAuth2TokenValidationRequestDTO errRespDTO.setErrorMsg("Server error occurred while validating the OAuth2 access token"); return errRespDTO; } + //trigger post listeners + triggerPostValidationListeners(oAuthEventListeners, validationReqDTO, responseDTO); + return responseDTO; + } + + private void triggerPreValidationListeners(List oAuthEventListeners, + OAuth2TokenValidationRequestDTO requestDTO) + throws IdentityOAuth2Exception { + + for (OAuthEventListener OAuthEventListener : oAuthEventListeners) { + OAuthEventListener.onPreTokenValidation(requestDTO); + } + } - for (OauthEventListener oauthEventListener : oauthEventListeners) { + private void triggerPostValidationListeners(List oAuthEventListeners, + OAuth2TokenValidationRequestDTO requestDTO, + OAuth2TokenValidationResponseDTO responseDTO) { + + for (OAuthEventListener OAuthEventListener : oAuthEventListeners) { try { - oauthEventListener.onPostTokenValidation(validationReqDTO, responseDTO); + OAuthEventListener.onPostTokenValidation(requestDTO, responseDTO); } catch (IdentityOAuth2Exception e) { - log.error("Oauth post listener " + oauthEventListener.getClass().getName() + " failed.", e); + log.error("Oauth post validation listener " + OAuthEventListener.getClass().getName() + " failed.", e); } } - return responseDTO; } /** diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/TokenResponseTypeHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/TokenResponseTypeHandler.java index 9cde901cc64..1789029fcc3 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/TokenResponseTypeHandler.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/authz/handlers/TokenResponseTypeHandler.java @@ -30,7 +30,7 @@ import org.wso2.carbon.identity.oauth.cache.OAuthCacheKey; import org.wso2.carbon.identity.oauth.common.OAuthConstants; import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; -import org.wso2.carbon.identity.oauth.event.OauthEventListener; +import org.wso2.carbon.identity.oauth.event.OAuthEventListener; import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext; @@ -53,12 +53,9 @@ public class TokenResponseTypeHandler extends AbstractResponseTypeHandler { public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx) throws IdentityOAuth2Exception { - List oauthListeners = OAuthComponentServiceHolder.getInstance().getOauthEventListeners(); - - for (OauthEventListener oauthListener : oauthListeners) { - oauthListener.onPreTokenIssue(oauthAuthzMsgCtx); - } + List oauthListeners = OAuthComponentServiceHolder.getInstance().getoAuthEventListeners(); + triggerPreListeners(oauthListeners, oauthAuthzMsgCtx); OAuth2AuthorizeRespDTO respDTO = new OAuth2AuthorizeRespDTO(); OAuth2AuthorizeReqDTO authorizationReqDTO = oauthAuthzMsgCtx.getAuthorizationReqDTO(); @@ -136,7 +133,7 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx respDTO.setScope(oauthAuthzMsgCtx.getApprovedScope()); respDTO.setTokenType(accessTokenDO.getTokenType()); buildIdToken(oauthAuthzMsgCtx, respDTO); - triggerPostListeners(oauthListeners,oauthAuthzMsgCtx,accessTokenDO,respDTO); + triggerPostListeners(oauthListeners, oauthAuthzMsgCtx, accessTokenDO, respDTO); return respDTO; } else { @@ -301,13 +298,13 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx // set refresh token issued time.this is needed by downstream handlers. oauthAuthzMsgCtx.setRefreshTokenIssuedTime(refreshTokenIssuedTime.getTime()); - try { - accessToken = oauthIssuerImpl.accessToken(oauthAuthzMsgCtx); + try { + accessToken = oauthIssuerImpl.accessToken(oauthAuthzMsgCtx); - // regenerate only if refresh token is null - if (refreshToken == null) { - refreshToken = oauthIssuerImpl.refreshToken(oauthAuthzMsgCtx); - } + // regenerate only if refresh token is null + if (refreshToken == null) { + refreshToken = oauthIssuerImpl.refreshToken(oauthAuthzMsgCtx); + } } catch (OAuthSystemException e) { throw new IdentityOAuth2Exception("Error occurred while generating access token and refresh token", e); @@ -384,10 +381,19 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx return respDTO; } - private void triggerPostListeners(List oauthListeners, OAuthAuthzReqMessageContext + private void triggerPreListeners(List oauthListeners, OAuthAuthzReqMessageContext + oauthAuthzMsgCtx) throws IdentityOAuth2Exception { + + for (OAuthEventListener oauthListener : oauthListeners) { + oauthListener.onPreTokenIssue(oauthAuthzMsgCtx); + } + + } + + private void triggerPostListeners(List oauthListeners, OAuthAuthzReqMessageContext oauthAuthzMsgCtx, AccessTokenDO tokenDO, OAuth2AuthorizeRespDTO respDTO) { - for (OauthEventListener oauthListener : oauthListeners) { + for (OAuthEventListener oauthListener : oauthListeners) { try { oauthListener.onPostTokenIssue(oauthAuthzMsgCtx, tokenDO, respDTO); } catch (IdentityOAuth2Exception e) { diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java index 8d1c11345ae..3f7cf4aaa6d 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/AccessTokenIssuer.java @@ -32,7 +32,7 @@ import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; import org.wso2.carbon.identity.oauth.dao.OAuthAppDAO; import org.wso2.carbon.identity.oauth.dao.OAuthAppDO; -import org.wso2.carbon.identity.oauth.event.OauthEventListener; +import org.wso2.carbon.identity.oauth.event.OAuthEventListener; import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder; import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; import org.wso2.carbon.identity.oauth2.ResponseHeader; @@ -112,25 +112,15 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) String grantType = tokenReqDTO.getGrantType(); OAuth2AccessTokenRespDTO tokenRespDTO; - List oauthEventListeners = - OAuthComponentServiceHolder.getInstance().getOauthEventListeners(); + List oAuthEventListeners = + OAuthComponentServiceHolder.getInstance().getoAuthEventListeners(); AuthorizationGrantHandler authzGrantHandler = authzGrantHandlers.get(grantType); OAuthTokenReqMessageContext tokReqMsgCtx = new OAuthTokenReqMessageContext(tokenReqDTO); boolean isRefreshRequest = GrantType.REFRESH_TOKEN.toString().equals(grantType); - if (isRefreshRequest) { - for (OauthEventListener eventListener : oauthEventListeners) { - //If listener fail, it will throw an exception and stop the token issue process - eventListener.onPreTokenRenewal(tokenReqDTO, tokReqMsgCtx); - } - } else { - for (OauthEventListener eventListener : oauthEventListeners) { - //If listener fail, it will throw an exception and stop the token issue process - eventListener.onPreTokenIssue(tokenReqDTO, tokReqMsgCtx); - } - } + triggerPreListeners(oAuthEventListeners, tokenReqDTO, tokReqMsgCtx, isRefreshRequest); // If multiple client authentication methods have been used the authorization server must reject the request @@ -144,7 +134,7 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) OAuthConstants.OAuthError.TokenResponse.UNSUPPORTED_CLIENT_AUTHENTICATION_METHOD, "Unsupported Client Authentication Method!", tokenReqDTO); setResponseHeaders(tokReqMsgCtx, tokenRespDTO); - triggerPostListeners(oauthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, + triggerPostListeners(oAuthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, isRefreshRequest); return tokenRespDTO; } @@ -158,7 +148,7 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) OAuthConstants.OAuthError.TokenResponse.UNSUPPORTED_CLIENT_AUTHENTICATION_METHOD, "Unsupported Client Authentication Method!", tokenReqDTO); setResponseHeaders(tokReqMsgCtx, tokenRespDTO); - triggerPostListeners(oauthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, + triggerPostListeners(oAuthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, isRefreshRequest); return tokenRespDTO; } @@ -180,7 +170,7 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) tokenRespDTO = handleError(OAuthError.TokenResponse.INVALID_CLIENT, "Client credentials are invalid.", tokenReqDTO); setResponseHeaders(tokReqMsgCtx, tokenRespDTO); - triggerPostListeners(oauthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, + triggerPostListeners(oAuthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, isRefreshRequest); return tokenRespDTO; } @@ -208,7 +198,7 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) } tokenRespDTO = handleError(OAuthError.TokenResponse.INVALID_GRANT, error, tokenReqDTO); setResponseHeaders(tokReqMsgCtx, tokenRespDTO); - triggerPostListeners(oauthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, + triggerPostListeners(oAuthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, isRefreshRequest); return tokenRespDTO; } @@ -221,7 +211,7 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) tokenRespDTO = handleError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT, "Unauthorized Client!", tokenReqDTO); setResponseHeaders(tokReqMsgCtx, tokenRespDTO); - triggerPostListeners(oauthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, + triggerPostListeners(oAuthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, isRefreshRequest); return tokenRespDTO; } @@ -233,7 +223,7 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) } tokenRespDTO = handleError(OAuthError.TokenResponse.INVALID_SCOPE, "Invalid Scope!", tokenReqDTO); setResponseHeaders(tokReqMsgCtx, tokenRespDTO); - triggerPostListeners(oauthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, + triggerPostListeners(oAuthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, isRefreshRequest); return tokenRespDTO; } @@ -243,7 +233,7 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) // IDENTITY-4111. OAuth2Util.setTokenRequestContext(tokReqMsgCtx); tokenRespDTO = authzGrantHandler.issue(tokReqMsgCtx); - triggerPostListeners(oauthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, + triggerPostListeners(oAuthEventListeners, tokenReqDTO, tokenRespDTO, tokReqMsgCtx, isRefreshRequest); } finally { // clears the token request context. @@ -282,12 +272,29 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) return tokenRespDTO; } - private void triggerPostListeners(List listeners, OAuth2AccessTokenReqDTO tokenReqDTO, + private void triggerPreListeners(List listeners, OAuth2AccessTokenReqDTO tokenReqDTO, + OAuthTokenReqMessageContext tokReqMsgCtx, + boolean isRefresh) throws IdentityOAuth2Exception { + + if (isRefresh) { + for (OAuthEventListener eventListener : listeners) { + //If listener fail, it will throw an exception and stop the token issue process + eventListener.onPreTokenRenewal(tokenReqDTO, tokReqMsgCtx); + } + } else { + for (OAuthEventListener eventListener : listeners) { + //If listener fail, it will throw an exception and stop the token issue process + eventListener.onPreTokenIssue(tokenReqDTO, tokReqMsgCtx); + } + } + } + + private void triggerPostListeners(List listeners, OAuth2AccessTokenReqDTO tokenReqDTO, OAuth2AccessTokenRespDTO tokenRespDTO, OAuthTokenReqMessageContext tokReqMsgCtx, boolean isRefresh) { if (isRefresh) { - for (OauthEventListener listener : listeners) { + for (OAuthEventListener listener : listeners) { try { listener.onPostTokenRenewal(tokenReqDTO, tokenRespDTO, tokReqMsgCtx); } catch (IdentityOAuth2Exception e) { @@ -295,7 +302,7 @@ private void triggerPostListeners(List listeners, OAuth2Acce } } } else { - for (OauthEventListener listener : listeners) { + for (OAuthEventListener listener : listeners) { try { listener.onPostTokenIssue(tokenReqDTO, tokenRespDTO, tokReqMsgCtx); } catch (IdentityOAuth2Exception e) {