/* * Copyright (c) 2014, 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.listener; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; import org.wso2.carbon.identity.core.AbstractIdentityUserOperationEventListener; import org.wso2.carbon.identity.core.model.IdentityErrorMsgContext; import org.wso2.carbon.identity.core.util.IdentityCoreConstants; import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.oauth.OAuthUtil; import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCache; import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCacheEntry; import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCacheKey; import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; import org.wso2.carbon.identity.oauth2.dao.TokenMgtDAO; import org.wso2.carbon.identity.oauth2.model.AccessTokenDO; import org.wso2.carbon.identity.oauth2.util.OAuth2Util; import org.wso2.carbon.user.core.UserCoreConstants; import org.wso2.carbon.user.core.UserStoreException; import org.wso2.carbon.user.core.UserStoreManager; import org.wso2.carbon.user.core.util.UserCoreUtil; import java.util.Map; import java.util.Set; /** * This is an implementation of UserOperationEventListener. This defines * additional operations * for some of the core user management operations */ public class IdentityOathEventListener extends AbstractIdentityUserOperationEventListener { private static final Log log = LogFactory.getLog(IdentityOathEventListener.class); /** * Bundle execution order id. */ @Override public int getExecutionOrderId() { int orderId = getOrderId(); if (orderId != IdentityCoreConstants.EVENT_LISTENER_ORDER_ID) { return orderId; } return 60; } /** * Deleting user from the identity database prerequisites. */ @Override public boolean doPreDeleteUser(java.lang.String username, org.wso2.carbon.user.core.UserStoreManager userStoreManager) throws org.wso2.carbon.user.core.UserStoreException { if (!isEnable()) { return true; } return revokeTokens(username, userStoreManager); } @Override public boolean doPreSetUserClaimValue(String userName, String claimURI, String claimValue, String profileName, UserStoreManager userStoreManager) throws UserStoreException { removeTokensFromCache(userName, userStoreManager); return true; } @Override public boolean doPreSetUserClaimValues(String userName, Map<String, String> claims, String profileName, UserStoreManager userStoreManager) throws UserStoreException { removeTokensFromCache(userName, userStoreManager); return true; } @Override public boolean doPostSetUserClaimValues(String userName, Map<String, String> claims, String profileName, UserStoreManager userStoreManager) throws UserStoreException { if (!isEnable()) { return true; } return revokeTokensOfLockedUser(userName, userStoreManager); } @Override public boolean doPostAuthenticate(String userName, boolean authenticated, UserStoreManager userStoreManager) throws UserStoreException { if (!isEnable()) { return true; } return revokeTokensOfLockedUser(userName, userStoreManager); } private boolean revokeTokensOfLockedUser(String userName, UserStoreManager userStoreManager){ IdentityErrorMsgContext errorContext = IdentityUtil.getIdentityErrorMsg(); if (errorContext != null && errorContext.getErrorCode() == UserCoreConstants.ErrorCode.USER_IS_LOCKED){ return revokeTokens(userName, userStoreManager); } return true; } private boolean revokeTokens(String username, UserStoreManager userStoreManager){ TokenMgtDAO tokenMgtDAO = new TokenMgtDAO(); String userStoreDomain = UserCoreUtil.getDomainName(userStoreManager.getRealmConfiguration()); String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); AuthenticatedUser authenticatedUser = new AuthenticatedUser(); authenticatedUser.setUserStoreDomain(userStoreDomain); authenticatedUser.setTenantDomain(tenantDomain); authenticatedUser.setUserName(username); /* This userStoreDomain variable is used for access token table partitioning. So it is set to null when access token table partitioning is not enabled.*/ userStoreDomain = null; if (OAuth2Util.checkAccessTokenPartitioningEnabled() && OAuth2Util.checkUserNameAssertionEnabled()) { try { userStoreDomain = OAuth2Util.getUserStoreDomainFromUserId(authenticatedUser.toString()); } catch (IdentityOAuth2Exception e) { log.error("Error occurred while getting user store domain for User ID : " + authenticatedUser, e); return true; } } Set<String> clientIds = null; try { // get all the distinct client Ids authorized by this user clientIds = tokenMgtDAO.getAllTimeAuthorizedClientIds(authenticatedUser); } catch (IdentityOAuth2Exception e) { log.error("Error occurred while retrieving apps authorized by User ID : " + authenticatedUser, e); return true; } for (String clientId : clientIds) { Set<AccessTokenDO> accessTokenDOs = null; try { // retrieve all ACTIVE or EXPIRED access tokens for particular client authorized by this user accessTokenDOs = tokenMgtDAO.retrieveAccessTokens(clientId, authenticatedUser, userStoreDomain, true); } catch (IdentityOAuth2Exception e) { String errorMsg = "Error occurred while retrieving access tokens issued for " + "Client ID : " + clientId + ", User ID : " + authenticatedUser; log.error(errorMsg, e); return true; } for (AccessTokenDO accessTokenDO : accessTokenDOs) { //Clear cache OAuthUtil.clearOAuthCache(accessTokenDO.getConsumerKey(), accessTokenDO.getAuthzUser(), OAuth2Util.buildScopeString(accessTokenDO.getScope())); OAuthUtil.clearOAuthCache(accessTokenDO.getConsumerKey(), accessTokenDO.getAuthzUser()); OAuthUtil.clearOAuthCache(accessTokenDO.getAccessToken()); AccessTokenDO scopedToken = null; try { // retrieve latest access token for particular client, user and scope combination if its ACTIVE or EXPIRED scopedToken = tokenMgtDAO.retrieveLatestAccessToken( clientId, authenticatedUser, userStoreDomain, OAuth2Util.buildScopeString(accessTokenDO.getScope()), true); } catch (IdentityOAuth2Exception e) { String errorMsg = "Error occurred while retrieving latest " + "access token issued for Client ID : " + clientId + ", User ID : " + authenticatedUser + " and Scope : " + OAuth2Util.buildScopeString(accessTokenDO.getScope()); log.error(errorMsg, e); return true; } if (scopedToken != null) { try { //Revoking token from database tokenMgtDAO.revokeTokens(new String[]{scopedToken.getAccessToken()}); } catch (IdentityOAuth2Exception e) { String errorMsg = "Error occurred while revoking " + "Access Token : " + scopedToken.getAccessToken(); log.error(errorMsg, e); return true; } } } } return true; } private void removeTokensFromCache(String userName, UserStoreManager userStoreManager) throws UserStoreException { String userStoreDomain = UserCoreUtil.getDomainName(userStoreManager.getRealmConfiguration()); String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); TokenMgtDAO tokenMgtDAO = new TokenMgtDAO(); Set<String> accessTokens; Set<String> authorizationCodes; AuthenticatedUser authenticatedUser = new AuthenticatedUser(); authenticatedUser.setUserStoreDomain(userStoreDomain); authenticatedUser.setTenantDomain(tenantDomain); authenticatedUser.setUserName(userName); try { accessTokens = tokenMgtDAO.getAccessTokensForUser(authenticatedUser); authorizationCodes = tokenMgtDAO.getAuthorizationCodesForUser(authenticatedUser); if (accessTokens != null && accessTokens.size() > 0) { for (String accessToken : accessTokens) { AuthorizationGrantCacheKey cacheKey = new AuthorizationGrantCacheKey(accessToken); AuthorizationGrantCacheEntry cacheEntry = (AuthorizationGrantCacheEntry) AuthorizationGrantCache .getInstance().getValueFromCacheByToken(cacheKey); if (cacheEntry != null) { AuthorizationGrantCache.getInstance().clearCacheEntryByToken(cacheKey); } } } if (authorizationCodes != null && authorizationCodes.size() > 0) { for (String accessToken : authorizationCodes) { AuthorizationGrantCacheKey cacheKey = new AuthorizationGrantCacheKey(accessToken); AuthorizationGrantCacheEntry cacheEntry = (AuthorizationGrantCacheEntry) AuthorizationGrantCache .getInstance().getValueFromCacheByToken(cacheKey); if (cacheEntry != null) { AuthorizationGrantCache.getInstance().clearCacheEntryByCode(cacheKey); } } } } catch (IdentityOAuth2Exception e) { String errorMsg = "Error occurred while retrieving access tokens issued for user : " + userName; log.error(errorMsg, e); } } }