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 61a202f281..7a458591fa 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; @@ -138,6 +140,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 { @@ -167,6 +170,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 { @@ -182,7 +186,7 @@ public OAuthConsumerAppDTO getOAuthApplicationDataByAppName(String appName) thro dto.setPkceSupportPlain(app.isPkceSupportPlain()); } return dto; - }catch (InvalidOAuthClientException | IdentityOAuth2Exception e){ + } catch (InvalidOAuthClientException | IdentityOAuth2Exception e) { throw new IdentityOAuthAdminException("Error while retrieving the app information by app name", e); } } @@ -193,7 +197,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); @@ -246,7 +251,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)) { @@ -272,6 +277,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(); @@ -315,6 +321,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 @@ -383,7 +390,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 { @@ -405,7 +412,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) { @@ -429,6 +436,10 @@ public OAuthConsumerAppDTO[] getAppsAuthorizedByUser() throws IdentityOAuthAdmin public OAuthRevocationResponseDTO revokeAuthzForAppsByResoureOwner( OAuthRevocationRequestDTO revokeRequestDTO) throws IdentityOAuthAdminException { + List oauthListeners = OAuthComponentServiceHolder.getInstance().getoAuthEventListeners(); + + triggerPreRevokeListeners(oauthListeners, revokeRequestDTO); + TokenMgtDAO tokenMgtDAO = new TokenMgtDAO(); if (revokeRequestDTO.getApps() != null && revokeRequestDTO.getApps().length > 0) { String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); @@ -498,13 +509,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); } @@ -516,12 +529,44 @@ 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 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) { + 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 115d6fc4ac..7553db4049 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 @@ -143,7 +143,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; @@ -461,4 +461,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 0000000000..9e4d1bb04b --- /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 d671cc0b11..c4875a131a 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 OAuthComponentServiceHolder(){ + 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 OAuthComponentServiceHolder getInstance() { + return instance; } - public static RegistryService getRegistryService() { + 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 0d4caf5daf..271bbeb8db 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,11 +36,17 @@ * 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" */ public class OAuthServiceComponent { + private static Log log = LogFactory.getLog(OAuthServiceComponent.class); private static IdentityOathEventListener listener = null; private ServiceRegistration serviceRegistration = null; @@ -65,44 +72,75 @@ 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"); } } protected void deactivate(ComponentContext context) { + if (serviceRegistration != null) { 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.debug("Unsetting the Realm Service"); + } + 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.info("Unsetting the Realm Service"); + log.debug("Unsetting oAuthEventListener :" + oAuthEventListener.getClass().getName()); } - OAuthComponentServiceHolder.setRealmService(null); + 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 e3f63d37c6..e934729fc8 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."); } @@ -193,7 +196,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 { @@ -203,7 +207,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); @@ -213,10 +218,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); @@ -237,6 +243,21 @@ 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 + 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; + AccessTokenDO accessTokenDO = null; try { if (StringUtils.isNotEmpty(revokeRequestDTO.getConsumerKey()) && @@ -247,19 +268,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; @@ -278,6 +296,8 @@ public OAuthRevocationResponseDTO revokeTokenByOAuthClient(OAuthRevocationReques .equals(refreshTokenDO.getRefreshTokenState()) || OAuthConstants.TokenStates.TOKEN_STATE_EXPIRED .equals(refreshTokenDO.getRefreshTokenState()))) { + invokePostRevocationListeners(oauthListeners, revokeRequestDTO, revokeResponseDTO, + accessTokenDO, refreshTokenDO); return revokeResponseDTO; } } @@ -300,43 +320,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; } @@ -346,6 +371,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); @@ -353,10 +380,40 @@ 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 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) { + try { + listener.onPostTokenRevocationByClient(revokeRequestDTO, revokeResponseDTO, accessTokenDO, + refreshTokenDO); + } catch (IdentityOAuth2Exception e) { + log.error("Error occured when invoking post token revoke listener " + listener.getClass().getName(), e); + } + } + + } + /** * Returns an array of claims of the authorized user. This is for the * OpenIDConnect user-end-point implementation. @@ -419,7 +476,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()); @@ -481,7 +538,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 fb889a7f25..0426a04de6 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,95 @@ public class OAuth2TokenValidationService extends AbstractAdmin { */ public OAuth2TokenValidationResponseDTO validate(OAuth2TokenValidationRequestDTO validationReqDTO) { - TokenValidationHandler validationHandler = TokenValidationHandler.getInstance(); - - 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; - } + TokenValidationHandler validationHandler = TokenValidationHandler.getInstance(); + 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 { + 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; + } + //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); + } + } + + private void triggerPostValidationListeners(List oAuthEventListeners, + OAuth2TokenValidationRequestDTO requestDTO, + OAuth2TokenValidationResponseDTO responseDTO) { + + for (OAuthEventListener OAuthEventListener : oAuthEventListeners) { + try { + OAuthEventListener.onPostTokenValidation(requestDTO, responseDTO); + } catch (IdentityOAuth2Exception e) { + log.error("Oauth post validation listener " + OAuthEventListener.getClass().getName() + " failed.", e); + } + } } /** * @param validationReqDTO * @return */ - public OAuth2ClientApplicationDTO findOAuthConsumerIfTokenIsValid(OAuth2TokenValidationRequestDTO validationReqDTO) { - - 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; - } + public OAuth2ClientApplicationDTO findOAuthConsumerIfTokenIsValid( + OAuth2TokenValidationRequestDTO validationReqDTO) { + + 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; + } } /** * returns back the introspection response, which is compatible with RFC 7662. + * * @param validationReq * @return */ public OAuth2IntrospectionResponseDTO buildIntrospectionResponse(OAuth2TokenValidationRequestDTO validationReq) { - 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; - } + 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; + } } } 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 fc2c518e08..2dc00f0fa8 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 309db5fc62..54a17c6828 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 e160893adf..1789029fcc 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,10 @@ public class TokenResponseTypeHandler extends AbstractResponseTypeHandler { public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx) throws IdentityOAuth2Exception { + List oauthListeners = OAuthComponentServiceHolder.getInstance().getoAuthEventListeners(); + + triggerPreListeners(oauthListeners, oauthAuthzMsgCtx); + OAuth2AuthorizeRespDTO respDTO = new OAuth2AuthorizeRespDTO(); OAuth2AuthorizeReqDTO authorizationReqDTO = oauthAuthzMsgCtx.getAuthorizationReqDTO(); @@ -91,6 +98,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 +116,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 +126,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 +187,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 +204,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 +214,7 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx respDTO.setTokenType(existingAccessTokenDO.getTokenType()); buildIdToken(oauthAuthzMsgCtx, respDTO); - + triggerPostListeners(oauthListeners, oauthAuthzMsgCtx, existingAccessTokenDO, respDTO); return respDTO; } else { @@ -224,7 +234,8 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx } refreshToken = existingAccessTokenDO.getRefreshToken(); refreshTokenIssuedTime = existingAccessTokenDO.getRefreshTokenIssuedTime(); - refreshTokenValidityPeriodInMillis = existingAccessTokenDO.getRefreshTokenValidityPeriodInMillis(); + refreshTokenValidityPeriodInMillis = + existingAccessTokenDO.getRefreshTokenValidityPeriodInMillis(); } if (log.isDebugEnabled()) { @@ -249,7 +260,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 +276,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(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); - } + } 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 +320,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 +335,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 +362,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 +377,33 @@ public OAuth2AuthorizeRespDTO issue(OAuthAuthzReqMessageContext oauthAuthzMsgCtx } buildIdToken(oauthAuthzMsgCtx, respDTO); + triggerPostListeners(oauthListeners, oauthAuthzMsgCtx, tokenDO, respDTO); return respDTO; } + 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) { + 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 53b77f32ac..3f7cf4aaa6 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,16 @@ 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); + + triggerPreListeners(oAuthEventListeners, tokenReqDTO, tokReqMsgCtx, isRefreshRequest); + // If multiple client authentication methods have been used the authorization server must reject the request int authenticatorHandlerIndex = -1; @@ -125,6 +134,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 +148,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 +164,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 +186,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 +198,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 +272,46 @@ public OAuth2AccessTokenRespDTO issue(OAuth2AccessTokenReqDTO tokenReqDTO) return tokenRespDTO; } + 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) { + 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 +319,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 +349,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 +373,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 +389,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 6798e28f31..27060e802e 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 b894becb54..31f84179e5 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 17d1a5ae6a..e81046571a 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());