Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components/org.wso2.carbon.identity.oauth/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<configuration>
<excludes>**/IdentityOathEventListenerTest.java,**/AccessTokenIssuerTest.java,
<excludes>**/IdentityOathEventListenerTest.java,**/DeprecatedAccessTokenIssuerTest.java,
**/OAuthUserStoreConfigListenerImplTest.java,**/NTLMAuthenticationGrantHandlerWithHandshakeTest.java,
**/AuthorizationCodeGrantHandlerTest.java,**/OAuthTenantMgtListenerImplTest.java</excludes>
</configuration>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
import org.wso2.carbon.identity.oauth2.validators.JDBCPermissionBasedInternalScopeValidator;
import org.wso2.carbon.identity.oauth2.validators.RoleBasedInternalScopeValidator;
import org.wso2.carbon.identity.openidconnect.IDTokenBuilder;
import org.wso2.carbon.identity.openidconnect.OIDCConstants;
import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.common.AbstractUserStoreManager;
Expand Down Expand Up @@ -128,6 +129,7 @@
import static org.wso2.carbon.identity.oauth2.util.OAuth2Util.EXTENDED_REFRESH_TOKEN_DEFAULT_TIME;
import static org.wso2.carbon.identity.oauth2.util.OAuth2Util.INTERNAL_LOGIN_SCOPE;
import static org.wso2.carbon.identity.oauth2.util.OAuth2Util.validateRequestTenantDomain;
import static org.wso2.carbon.identity.openidconnect.OIDCConstants.EXISTING_TOKEN_USED;
import static org.wso2.carbon.identity.openidconnect.OIDCConstants.ID_TOKEN_USER_CLAIMS_PROP_KEY;

/**
Expand All @@ -141,6 +143,7 @@ public class AccessTokenIssuer {
public static final String OAUTH_APP_DO = "OAuthAppDO";
private static final String SERVICE_PROVIDERS_SUB_CLAIM = "ServiceProviders.UseUsernameAsSubClaim";
private final AuthorizationDetailsValidator authorizationDetailsValidator;
private static final String ENABLE_POST_TOKEN_ISSUE_EVENT = "PostTokenIssueEvent.Enable";

/**
* Private constructor which will not allow to create objects of this class from outside
Expand Down Expand Up @@ -417,7 +420,7 @@ private AuthorizationGrantCacheEntry getAuthzGrantCacheEntryFromDeviceCode(OAuth
}

private void persistImpersonationInfoToTokenReqCtx(AuthorizationGrantCacheEntry authorizationGrantCacheEntry,
OAuthTokenReqMessageContext tokReqMsgCtx) {
OAuthTokenReqMessageContext tokReqMsgCtx) {

boolean isUserSessionImpersonationEnabled = OAuthServerConfiguration.getInstance()
.isUserSessionImpersonationEnabled();
Expand Down Expand Up @@ -1364,6 +1367,11 @@ private void triggerPostListeners(OAuth2AccessTokenReqDTO tokenReqDTO,

OAuthEventInterceptor oAuthEventInterceptorProxy = OAuthComponentServiceHolder.getInstance()
.getOAuthEventInterceptorProxy();
try {
triggerPostIssueTokenEvent(tokenReqDTO, tokenRespDTO, tokReqMsgCtx);
} catch (IdentityOAuth2Exception | OrganizationManagementException e) {
log.error("Error while triggering post issue token event.", e);
}

if (isRefresh) {
if (oAuthEventInterceptorProxy != null && oAuthEventInterceptorProxy.isEnabled()) {
Expand Down Expand Up @@ -1394,6 +1402,65 @@ private void triggerPostListeners(OAuth2AccessTokenReqDTO tokenReqDTO,
}
}

private static void triggerPostIssueTokenEvent(OAuth2AccessTokenReqDTO tokenReqDTO,
OAuth2AccessTokenRespDTO tokenRespDTO,
OAuthTokenReqMessageContext tokReqMsgCtx)
throws IdentityOAuth2Exception, OrganizationManagementException {

if (!Boolean.parseBoolean(IdentityUtil.getProperty(ENABLE_POST_TOKEN_ISSUE_EVENT))) {
if (log.isDebugEnabled()) {
log.debug("Token event publishing is disabled. Hence skipping the post issue token event.");
}
return;
}
if (tokenReqDTO == null || tokenRespDTO == null || tokReqMsgCtx == null) {
if (log.isDebugEnabled()) {
log.debug("Token request DTO, token response DTO or token request message context is null. " +
"Skipping the post issue token event.");
}
return;
}
if (tokenRespDTO.isError()) {
if (log.isDebugEnabled()) {
log.debug("Token response DTO is in error state. Hence skipping the post issue token event.");
}
return;
}

String tenantDomain = tokReqMsgCtx.getOauth2AccessTokenReqDTO().getTenantDomain();
String organizationId = OAuthComponentServiceHolder.getInstance().getOrganizationManager()
.resolveOrganizationId(tenantDomain);
String accessingOrganizationId = StringUtils.EMPTY;
if (tokReqMsgCtx.getAuthorizedUser() != null
&& tokReqMsgCtx.getAuthorizedUser().getAccessingOrganization() != null) {
accessingOrganizationId = tokReqMsgCtx.getAuthorizedUser().getAccessingOrganization();
}

Map<String, Object> eventProperties = new HashMap<>();
eventProperties.put(OIDCConstants.Event.TOKEN_ID, tokenRespDTO.getTokenId());
eventProperties.put(OIDCConstants.Event.TENANT_DOMAIN, tenantDomain);
eventProperties.put(OIDCConstants.Event.USER_TYPE, tokReqMsgCtx.getProperty(OAuthConstants.UserType.USER_TYPE));
eventProperties.put(OIDCConstants.Event.CLIENT_ID, tokReqMsgCtx.getOauth2AccessTokenReqDTO().getClientId());
eventProperties.put(OIDCConstants.Event.GRANT_TYPE, tokenReqDTO.getGrantType());
eventProperties.put(OIDCConstants.Event.ISSUED_TIME, String.valueOf(tokReqMsgCtx.getAccessTokenIssuedTime()));
eventProperties.put(OIDCConstants.Event.ISSUER_ORGANIZATION_ID, organizationId);
eventProperties.put(OIDCConstants.Event.ACCESSING_ORGANIZATION_ID, accessingOrganizationId);
eventProperties.put(OIDCConstants.Event.APP_RESIDENT_TENANT_ID, IdentityTenantUtil.getLoginTenantId());
eventProperties.put(OIDCConstants.Event.EXISTING_TOKEN_USED, String.valueOf(existingTokenUsed(tokReqMsgCtx)));
eventProperties.put(OIDCConstants.Event.SERVICE_PROVIDER, OAuth2Util.getServiceProvider(
tokReqMsgCtx.getOauth2AccessTokenReqDTO().getClientId(), tenantDomain).getApplicationName());
OAuth2TokenUtil.postIssueToken(eventProperties);
}

private static Boolean existingTokenUsed(OAuthTokenReqMessageContext tokReqMsgCtx) {

Boolean existingTokenUsed = (Boolean) tokReqMsgCtx.getProperty(EXISTING_TOKEN_USED);
if (existingTokenUsed == null) {
existingTokenUsed = false;
}
return existingTokenUsed;
}

/**
* Copies the cache entry against the authorization code/device code and adds an entry against the access token.
* This is done to reuse the calculated user claims for subsequent usages such as user info calls.
Expand Down Expand Up @@ -1474,8 +1541,8 @@ private void persistCustomizedAccessTokenAttributesForRefreshToken(OAuth2AccessT
AuthorizationGrantCache.getInstance().addToCacheByToken(newCacheKey, authorizationGrantCacheEntry);

log.debug("Customized audience list and access token attributes from pre issue access token actions " +
"are persisted in the AuthorizationGrantCache against the token id: " +
tokenRespDTO.getTokenId());
"are persisted in the AuthorizationGrantCache against the token id: " +
tokenRespDTO.getTokenId());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.wso2.carbon.identity.openidconnect.OIDCConstants.Event.IS_REQUEST_OBJECT_FLOW;
import static org.wso2.carbon.identity.openidconnect.OIDCConstants.Event.NEW_ACCESS_TOKEN;
Expand Down Expand Up @@ -82,6 +83,31 @@ public static void postIssueAccessToken(String tokenId, String sessionDataKey) t
}
}

/**
* Uses to publish token issuance details.
*
* @param eventProperties Map containing token issuance details.
* @throws IdentityOAuth2Exception when an error occurs while publishing the event.
*/
public static void postIssueToken(Map<String, Object> eventProperties) throws IdentityOAuth2Exception {

String eventName = OIDCConstants.Event.POST_ISSUE_ACCESS_TOKEN_V2;
Event postIssueTokenEvent = new Event(eventName, eventProperties);
IdentityEventService identityEventService = OpenIDConnectServiceComponentHolder.getIdentityEventService();
try {
if (identityEventService != null) {
identityEventService.handleEvent(postIssueTokenEvent);
if (log.isDebugEnabled()) {
log.debug("The event " + eventName + " triggered after the token "
+ eventProperties.get(OIDCConstants.Event.TOKEN_ID) + " is issued.");
}
}
} catch (IdentityEventException e) {
throw new IdentityOAuth2Exception("Error while invoking the request object persistence handler when " +
"issuing the access token id: " + eventProperties.get(OIDCConstants.Event.TOKEN_ID));
}
}

/**
* Uses to revoke access tokens from the request object related tables after token revocation
* happens from access token related tables.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class OIDCConstants {
public static final String IDN_OIDC_REQ_OBJECT_CLAIMS = "STORE_IDN_OIDC_REQ_OBJECT_CLAIMS";
public static final String HAS_NON_OIDC_CLAIMS = "hasNonOIDCClaims";
public static final String ID_TOKEN_USER_CLAIMS_PROP_KEY = "IDTokenUserClaims";
public static final String EXISTING_TOKEN_USED = "existingTokenUsed";

/**
* This class is used to define constants related to OIDC event specific features.
Expand All @@ -39,6 +40,7 @@ public class Event {
public static final String SESSION_DATA_KEY = "SESSION_DATA_KEY";
public static final String POST_ISSUE_CODE = "POST_ISSUE_CODE";
public static final String POST_ISSUE_ACCESS_TOKEN = "POST_ISSUE_ACCESS_TOKEN";
public static final String POST_ISSUE_ACCESS_TOKEN_V2 = "POST_ISSUE_ACCESS_TOKEN_V2";
public static final String HANDLE_REQUEST_OBJECT = "handleRequestObject";
public static final String POST_REVOKE_ACESS_TOKEN = "POST_REVOKE_ACESS_TOKEN";
public static final String POST_REVOKE_ACESS_TOKEN_BY_ID = "POST_REVOKE_ACESS_TOKEN_BY_ID";
Expand All @@ -47,10 +49,19 @@ public class Event {
public static final String ACEESS_TOKENS = "ACEESS_TOKENS";
public static final String CODES = "CODES";
public static final String TOKEN_STATE = "TOKEN_STATE";
public static final String GRANT_TYPE = "GRANT_TYPE";
public static final String CLIENT_ID = "CLIENT_ID";
public static final String TENANT_DOMAIN = "TENANT_DOMAIN";
public static final String USER_TYPE = "USER_TYPE";
public static final String NEW_ACCESS_TOKEN = "NEW_ACCESS_TOKEN";
public static final String OLD_ACCESS_TOKEN = "OLD_ACCESS_TOKEN";
public static final String POST_REFRESH_TOKEN = "POST_REFRESH_TOKEN";
public static final String IS_REQUEST_OBJECT_FLOW = "IS_REQUEST_OBJECT_FLOW";
public static final String APP_RESIDENT_TENANT_ID = "APP_RESIDENT_TENANT_ID";
public static final String ISSUED_TIME = "ISSUED_TIME";
public static final String ISSUER_ORGANIZATION_ID = "ISSUER_ORGANIZATION_ID";
public static final String ACCESSING_ORGANIZATION_ID = "ACCESSING_ORGANIZATION_ID";
public static final String EXISTING_TOKEN_USED = "EXISTING_TOKEN_USED";
public static final String SERVICE_PROVIDER = "SERVICE_PROVIDER";
}
}

Loading