From 4321a02d12058f2c8de5c88f6c3a306998aabe00 Mon Sep 17 00:00:00 2001 From: Indeewai Wijesiri Date: Tue, 5 Mar 2024 14:39:12 +0530 Subject: [PATCH 1/4] Sharing the federated token in oidc authentication --- .../endpoint/authz/OAuth2AuthzEndpoint.java | 27 +++++++ .../cache/AuthorizationGrantCacheEntry.java | 13 ++++ .../oauth/cache/SessionDataCacheEntry.java | 14 ++++ .../internal/OAuth2ServiceComponent.java | 4 + .../FederatedTokenResponseHandler.java | 74 +++++++++++++++++++ 5 files changed, 132 insertions(+) create mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/response/FederatedTokenResponseHandler.java diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java index e310704fc7e..0188c0ee3df 100644 --- a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java +++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java @@ -61,6 +61,7 @@ import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticationResult; import org.wso2.carbon.identity.application.authentication.framework.model.CommonAuthRequestWrapper; import org.wso2.carbon.identity.application.authentication.framework.model.CommonAuthResponseWrapper; +import org.wso2.carbon.identity.application.authentication.framework.model.FederatedToken; import org.wso2.carbon.identity.application.authentication.framework.model.auth.service.AuthServiceRequest; import org.wso2.carbon.identity.application.authentication.framework.model.auth.service.AuthServiceResponse; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; @@ -195,6 +196,7 @@ import static org.wso2.carbon.identity.application.authentication.endpoint.util.Constants.MANDATORY_CLAIMS; import static org.wso2.carbon.identity.application.authentication.endpoint.util.Constants.REQUESTED_CLAIMS; import static org.wso2.carbon.identity.application.authentication.endpoint.util.Constants.USER_CLAIMS_CONSENT_ONLY; +import static org.wso2.carbon.identity.application.authentication.framework.handler.request.impl.DefaultAuthenticationRequestHandler.FEDERATED_TOKENS; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.REQUEST_PARAM_SP; import static org.wso2.carbon.identity.client.attestation.mgt.utils.Constants.CLIENT_ATTESTATION_CONTEXT; import static org.wso2.carbon.identity.oauth.common.OAuthConstants.LogConstants.InputKeys.RESPONSE_TYPE; @@ -388,7 +390,29 @@ public Response authorize(@Context HttpServletRequest request, @Context HttpServ } } + /** + * Add the federated tokens comes with the authentication result to the session data cache. + * + * @param oAuthMessage The OAuthMessage with the session data cache entry. + * @param authenticationResult The authentication result of authorization call. + */ + private void addFederatedTokensToAuthCache(OAuthMessage oAuthMessage, AuthenticationResult authenticationResult) { + List federatedTokens = + (List) authenticationResult.getProperty(FEDERATED_TOKENS); + + SessionDataCacheEntry sessionDataCacheEntry = oAuthMessage.getSessionDataCacheEntry(); + if (sessionDataCacheEntry == null || CollectionUtils.isEmpty(federatedTokens)) { + return; + } + if (CollectionUtils.isEmpty(sessionDataCacheEntry.getFederatedTokens())) { + sessionDataCacheEntry.setFederatedTokens(new ArrayList<>()); + } + sessionDataCacheEntry.getFederatedTokens().addAll(federatedTokens); + if (log.isDebugEnabled()) { + log.debug("Added the federated tokens to the authorization grant cache."); + } + } private void setCommonAuthIdToRequest(HttpServletRequest request, HttpServletResponse response) { @@ -1335,6 +1359,8 @@ private void addToAuthenticationResultDetailsToOAuthMessage(OAuthMessage oAuthMe oAuthMessage.getSessionDataCacheEntry().setAuthenticatedIdPs(authnResult.getAuthenticatedIdPs()); oAuthMessage.getSessionDataCacheEntry().setSessionContextIdentifier((String) authnResult.getProperty(FrameworkConstants.AnalyticsAttributes.SESSION_ID)); + // Adding federated tokens come with the authorize authentication result. + addFederatedTokensToAuthCache(oAuthMessage, authnResult); } private void updateAuthTimeInSessionDataCacheEntry(OAuthMessage oAuthMessage) { @@ -2025,6 +2051,7 @@ private void addUserAttributesToOAuthMessage(OAuthMessage oAuthMessage, String c authorizationGrantCacheEntry.setAuthorizationCode(code); boolean isRequestObjectFlow = sessionDataCacheEntry.getoAuth2Parameters().isRequestObjectFlow(); authorizationGrantCacheEntry.setRequestObjectFlow(isRequestObjectFlow); + authorizationGrantCacheEntry.setFederatedTokens(sessionDataCacheEntry.getFederatedTokens()); oAuthMessage.setAuthorizationGrantCacheEntry(authorizationGrantCacheEntry); } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/AuthorizationGrantCacheEntry.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/AuthorizationGrantCacheEntry.java index 6305e11fb15..d4f27d0b8b5 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/AuthorizationGrantCacheEntry.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/AuthorizationGrantCacheEntry.java @@ -18,6 +18,7 @@ package org.wso2.carbon.identity.oauth.cache; +import org.wso2.carbon.identity.application.authentication.framework.model.FederatedToken; import org.wso2.carbon.identity.application.common.model.ClaimMapping; import org.wso2.carbon.identity.oauth2.model.AccessTokenExtendedAttributes; import org.wso2.carbon.identity.openidconnect.model.RequestObject; @@ -81,6 +82,8 @@ public class AuthorizationGrantCacheEntry extends CacheEntry { private AccessTokenExtendedAttributes accessTokenExtendedAttributes; private boolean isApiBasedAuthRequest; + private List federatedTokens; + public String getSubjectClaim() { return subjectClaim; } @@ -193,6 +196,16 @@ public void setPkceCodeChallengeMethod(String pkceCodeChallengeMethod) { this.pkceCodeChallengeMethod = pkceCodeChallengeMethod; } + public List getFederatedTokens() { + + return federatedTokens; + } + + public void setFederatedTokens(List federatedTokens) { + + this.federatedTokens = federatedTokens; + } + /** * To check whether particular cache entry has non OIDC claims in it. * diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/SessionDataCacheEntry.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/SessionDataCacheEntry.java index f1b40b74861..3f0d4024631 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/SessionDataCacheEntry.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/SessionDataCacheEntry.java @@ -19,11 +19,13 @@ package org.wso2.carbon.identity.oauth.cache; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; +import org.wso2.carbon.identity.application.authentication.framework.model.FederatedToken; import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext; import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters; import java.io.Serializable; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -50,6 +52,7 @@ public class SessionDataCacheEntry extends CacheEntry { private ConcurrentMap paramMap = new ConcurrentHashMap(); private Map endpointParams = new HashMap<>(); + private List federatedTokens; public OAuthAuthzReqMessageContext getAuthzReqMsgCtx() { return authzReqMsgCtx; @@ -159,4 +162,15 @@ public void setRemoveOnConsume(boolean removeOnConsume) { this.removeOnConsume = removeOnConsume; } + + public List getFederatedTokens() { + + return federatedTokens; + } + + public void setFederatedTokens( + List federatedTokens) { + + this.federatedTokens = federatedTokens; + } } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponent.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponent.java index cb219ccd02e..a0fe233faa6 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponent.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/internal/OAuth2ServiceComponent.java @@ -86,6 +86,8 @@ import org.wso2.carbon.identity.oauth2.token.bindings.impl.DeviceFlowTokenBinder; import org.wso2.carbon.identity.oauth2.token.bindings.impl.SSOSessionBasedTokenBinder; import org.wso2.carbon.identity.oauth2.token.handlers.claims.JWTAccessTokenClaimProvider; +import org.wso2.carbon.identity.oauth2.token.handlers.response.AccessTokenResponseHandler; +import org.wso2.carbon.identity.oauth2.token.handlers.response.FederatedTokenResponseHandler; import org.wso2.carbon.identity.oauth2.util.OAuth2Util; import org.wso2.carbon.identity.oauth2.validators.scope.RoleBasedScopeIssuer; import org.wso2.carbon.identity.oauth2.validators.scope.ScopeValidator; @@ -382,6 +384,8 @@ protected void activate(ComponentContext context) { bundleContext.registerService(ScopeValidationHandler.class, new RoleBasedScopeValidationHandler(), null); bundleContext.registerService(ScopeValidationHandler.class, new NoPolicyScopeValidationHandler(), null); bundleContext.registerService(ScopeValidationHandler.class, new M2MScopeValidationHandler(), null); + bundleContext.registerService(AccessTokenResponseHandler.class, new FederatedTokenResponseHandler(), + null); // Note : DO NOT add any activation related code below this point, // to make sure the server doesn't start up if any activation failures occur diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/response/FederatedTokenResponseHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/response/FederatedTokenResponseHandler.java new file mode 100644 index 00000000000..e8700e53c1b --- /dev/null +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/response/FederatedTokenResponseHandler.java @@ -0,0 +1,74 @@ +/* + * + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). All Rights Reserved. + * + * This software is the property of WSO2 LLC. and its suppliers, if any. + * Dissemination of any information or reproduction of any material contained + * herein in any form is strictly forbidden, unless permitted by WSO2 expressly. + * You may not alter or remove any copyright or other notice from copies of this content. + * + */ + +package org.wso2.carbon.identity.oauth2.token.handlers.response; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.application.authentication.framework.handler.request.impl.DefaultAuthenticationRequestHandler; +import org.wso2.carbon.identity.application.authentication.framework.model.FederatedToken; +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.token.OAuthTokenReqMessageContext; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This class is used to get the federated tokens for the token response. + * This expects the authorization code is available in the token request message context + * so that the federated tokens can be retrieved from the auth grant cache. + */ +public class FederatedTokenResponseHandler implements AccessTokenResponseHandler { + + private static final Log LOG = LogFactory.getLog(FederatedTokenResponseHandler.class); + + /** + * This method returns the federated tokens in the auth grant cache. + * + * @param tokReqMsgCtx {@link OAuthTokenReqMessageContext} Token request message context with a token request DTO. + * @return Map of the federated tokens. + */ + @Override + public Map getAdditionalTokenResponseAttributes(OAuthTokenReqMessageContext tokReqMsgCtx) { + + if (StringUtils.isBlank(tokReqMsgCtx.getOauth2AccessTokenReqDTO().getAuthorizationCode())) { + return null; + } + AuthorizationGrantCacheEntry cacheEntry = + AuthorizationGrantCache.getInstance().getValueFromCacheByCode(new AuthorizationGrantCacheKey( + tokReqMsgCtx.getOauth2AccessTokenReqDTO().getAuthorizationCode())); + + if (cacheEntry == null) { + return null; + } + + List federatedTokens = cacheEntry.getFederatedTokens(); + if (CollectionUtils.isEmpty(federatedTokens)) { + return null; + } + // Removing the federated token from the auth grant cache entry since it is no longer required. + cacheEntry.setFederatedTokens(null); + // Add federated tokens to the token response if available. + Map additionalAttributes = new HashMap<>(); + + additionalAttributes.putIfAbsent(DefaultAuthenticationRequestHandler.FEDERATED_TOKENS, federatedTokens); + if (LOG.isDebugEnabled()) { + LOG.debug("Federated tokens will be added to the additional attributes of the token response."); + } + + return additionalAttributes; + } +} From 0bfd7bffa4ff9aa96331ce33aa8032308fa1e4f9 Mon Sep 17 00:00:00 2001 From: Indeewai Wijesiri Date: Thu, 7 Mar 2024 09:21:54 +0530 Subject: [PATCH 2/4] Addresing the review comment of using a seperate object for federated token in oauth --- .../endpoint/authz/OAuth2AuthzEndpoint.java | 42 +++++++-- .../cache/AuthorizationGrantCacheEntry.java | 8 +- .../oauth/cache/SessionDataCacheEntry.java | 9 +- .../oauth2/model/FederatedTokenDO.java | 87 +++++++++++++++++++ .../FederatedTokenResponseHandler.java | 6 +- 5 files changed, 132 insertions(+), 20 deletions(-) create mode 100644 components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/model/FederatedTokenDO.java diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java index 0188c0ee3df..33cee091614 100644 --- a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java +++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java @@ -130,6 +130,7 @@ import org.wso2.carbon.identity.oauth2.dto.OAuth2ClientValidationResponseDTO; import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder; import org.wso2.carbon.identity.oauth2.model.AccessTokenExtendedAttributes; +import org.wso2.carbon.identity.oauth2.model.FederatedTokenDO; import org.wso2.carbon.identity.oauth2.model.HttpRequestHeaderHandler; import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters; import org.wso2.carbon.identity.oauth2.responsemode.provider.AuthorizationResponseDTO; @@ -174,6 +175,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; +import java.util.stream.Collectors; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; @@ -396,7 +398,8 @@ public Response authorize(@Context HttpServletRequest request, @Context HttpServ * @param oAuthMessage The OAuthMessage with the session data cache entry. * @param authenticationResult The authentication result of authorization call. */ - private void addFederatedTokensToAuthCache(OAuthMessage oAuthMessage, AuthenticationResult authenticationResult) { + private void addFederatedTokensToSessionCache(OAuthMessage oAuthMessage, + AuthenticationResult authenticationResult) { List federatedTokens = (List) authenticationResult.getProperty(FEDERATED_TOKENS); @@ -405,15 +408,37 @@ private void addFederatedTokensToAuthCache(OAuthMessage oAuthMessage, Authentica if (sessionDataCacheEntry == null || CollectionUtils.isEmpty(federatedTokens)) { return; } - if (CollectionUtils.isEmpty(sessionDataCacheEntry.getFederatedTokens())) { - sessionDataCacheEntry.setFederatedTokens(new ArrayList<>()); - } - sessionDataCacheEntry.getFederatedTokens().addAll(federatedTokens); + sessionDataCacheEntry.setFederatedTokens(getFederatedTokenDO(federatedTokens)); if (log.isDebugEnabled()) { - log.debug("Added the federated tokens to the authorization grant cache."); + log.debug("Added the federated tokens to the session data cache. Session context identifier: " + + sessionDataCacheEntry.getSessionContextIdentifier()); } } + /** + * This method creates a list of FederatedTokenDO objects from the list of FederatedToken objects. + * + * @param federatedTokens List of FederatedToken objects to be transformed as a list of FederatedTokenDO. + * @return List of FederatedTokenDO objects. + */ + private List getFederatedTokenDO(List federatedTokens) { + + if (CollectionUtils.isEmpty(federatedTokens)) { + return null; + } + + List federatedTokenDOs = federatedTokens.stream().map(federatedToken -> { + FederatedTokenDO federatedTokenDO = + new FederatedTokenDO(federatedToken.getIdp(), federatedToken.getAccessToken()); + federatedTokenDO.setRefreshToken(federatedToken.getRefreshToken()); + federatedTokenDO.setScope(federatedToken.getScope()); + federatedTokenDO.setTokenValidityPeriod(federatedToken.getTokenValidityPeriod()); + return federatedTokenDO; + }).collect(Collectors.toList()); + + return federatedTokenDOs; + } + private void setCommonAuthIdToRequest(HttpServletRequest request, HttpServletResponse response) { // Issue https://github.com/wso2/product-is/issues/11065 needs to addressed. @@ -1359,8 +1384,8 @@ private void addToAuthenticationResultDetailsToOAuthMessage(OAuthMessage oAuthMe oAuthMessage.getSessionDataCacheEntry().setAuthenticatedIdPs(authnResult.getAuthenticatedIdPs()); oAuthMessage.getSessionDataCacheEntry().setSessionContextIdentifier((String) authnResult.getProperty(FrameworkConstants.AnalyticsAttributes.SESSION_ID)); - // Adding federated tokens come with the authorize authentication result. - addFederatedTokensToAuthCache(oAuthMessage, authnResult); + // Adding federated tokens come with the authentication result of the authorization call. + addFederatedTokensToSessionCache(oAuthMessage, authnResult); } private void updateAuthTimeInSessionDataCacheEntry(OAuthMessage oAuthMessage) { @@ -2052,6 +2077,7 @@ private void addUserAttributesToOAuthMessage(OAuthMessage oAuthMessage, String c boolean isRequestObjectFlow = sessionDataCacheEntry.getoAuth2Parameters().isRequestObjectFlow(); authorizationGrantCacheEntry.setRequestObjectFlow(isRequestObjectFlow); authorizationGrantCacheEntry.setFederatedTokens(sessionDataCacheEntry.getFederatedTokens()); + sessionDataCacheEntry.setFederatedTokens(null); oAuthMessage.setAuthorizationGrantCacheEntry(authorizationGrantCacheEntry); } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/AuthorizationGrantCacheEntry.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/AuthorizationGrantCacheEntry.java index d4f27d0b8b5..5f562c565fd 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/AuthorizationGrantCacheEntry.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/AuthorizationGrantCacheEntry.java @@ -18,9 +18,9 @@ package org.wso2.carbon.identity.oauth.cache; -import org.wso2.carbon.identity.application.authentication.framework.model.FederatedToken; import org.wso2.carbon.identity.application.common.model.ClaimMapping; import org.wso2.carbon.identity.oauth2.model.AccessTokenExtendedAttributes; +import org.wso2.carbon.identity.oauth2.model.FederatedTokenDO; import org.wso2.carbon.identity.openidconnect.model.RequestObject; import java.util.ArrayList; @@ -82,7 +82,7 @@ public class AuthorizationGrantCacheEntry extends CacheEntry { private AccessTokenExtendedAttributes accessTokenExtendedAttributes; private boolean isApiBasedAuthRequest; - private List federatedTokens; + private List federatedTokens; public String getSubjectClaim() { return subjectClaim; @@ -196,12 +196,12 @@ public void setPkceCodeChallengeMethod(String pkceCodeChallengeMethod) { this.pkceCodeChallengeMethod = pkceCodeChallengeMethod; } - public List getFederatedTokens() { + public List getFederatedTokens() { return federatedTokens; } - public void setFederatedTokens(List federatedTokens) { + public void setFederatedTokens(List federatedTokens) { this.federatedTokens = federatedTokens; } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/SessionDataCacheEntry.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/SessionDataCacheEntry.java index 3f0d4024631..b2febaedfb5 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/SessionDataCacheEntry.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth/cache/SessionDataCacheEntry.java @@ -19,8 +19,8 @@ package org.wso2.carbon.identity.oauth.cache; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; -import org.wso2.carbon.identity.application.authentication.framework.model.FederatedToken; import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext; +import org.wso2.carbon.identity.oauth2.model.FederatedTokenDO; import org.wso2.carbon.identity.oauth2.model.OAuth2Parameters; import java.io.Serializable; @@ -52,7 +52,7 @@ public class SessionDataCacheEntry extends CacheEntry { private ConcurrentMap paramMap = new ConcurrentHashMap(); private Map endpointParams = new HashMap<>(); - private List federatedTokens; + private List federatedTokens; public OAuthAuthzReqMessageContext getAuthzReqMsgCtx() { return authzReqMsgCtx; @@ -163,13 +163,12 @@ public void setRemoveOnConsume(boolean removeOnConsume) { this.removeOnConsume = removeOnConsume; } - public List getFederatedTokens() { + public List getFederatedTokens() { return federatedTokens; } - public void setFederatedTokens( - List federatedTokens) { + public void setFederatedTokens(List federatedTokens) { this.federatedTokens = federatedTokens; } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/model/FederatedTokenDO.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/model/FederatedTokenDO.java new file mode 100644 index 00000000000..844993c4791 --- /dev/null +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/model/FederatedTokenDO.java @@ -0,0 +1,87 @@ +/* + * + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). All Rights Reserved. + * + * This software is the property of WSO2 LLC. and its suppliers, if any. + * Dissemination of any information or reproduction of any material contained + * herein in any form is strictly forbidden, unless permitted by WSO2 expressly. + * You may not alter or remove any copyright or other notice from copies of this content. + * + */ + +package org.wso2.carbon.identity.oauth2.model; + +import java.io.Serializable; + +/** + * This class is model class of a federated token. + * A federated token is an external token obtained via an OIDC federated authenticator + * after a successful authentication. + */ +public class FederatedTokenDO implements Serializable { + + private static final long serialVersionUID = 2717725650850067925L; + private String idp; + private String tokenValidityPeriod; + private String scope; + private String accessToken; + private String refreshToken; + + // Constructor + public FederatedTokenDO(String idp, String accessToken) { + + this.idp = idp; + this.accessToken = accessToken; + } + + // Getters and setters + public String getIdp() { + + return idp; + } + + public void setIdp(String idp) { + + this.idp = idp; + } + + public String getTokenValidityPeriod() { + + return tokenValidityPeriod; + } + + public void setTokenValidityPeriod(String tokenValidityPeriod) { + + this.tokenValidityPeriod = tokenValidityPeriod; + } + + public String getScope() { + + return scope; + } + + public void setScope(String scope) { + + this.scope = scope; + } + + public String getAccessToken() { + + return accessToken; + } + + public void setAccessToken(String accessToken) { + + this.accessToken = accessToken; + } + + public String getRefreshToken() { + + return refreshToken; + } + + public void setRefreshToken(String refreshToken) { + + this.refreshToken = refreshToken; + } +} diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/response/FederatedTokenResponseHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/response/FederatedTokenResponseHandler.java index e8700e53c1b..ac3171ee5b7 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/response/FederatedTokenResponseHandler.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/response/FederatedTokenResponseHandler.java @@ -16,10 +16,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.identity.application.authentication.framework.handler.request.impl.DefaultAuthenticationRequestHandler; -import org.wso2.carbon.identity.application.authentication.framework.model.FederatedToken; 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.model.FederatedTokenDO; import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext; import java.util.HashMap; @@ -55,11 +55,11 @@ public Map getAdditionalTokenResponseAttributes(OAuthTokenReqMes return null; } - List federatedTokens = cacheEntry.getFederatedTokens(); + List federatedTokens = cacheEntry.getFederatedTokens(); if (CollectionUtils.isEmpty(federatedTokens)) { return null; } - // Removing the federated token from the auth grant cache entry since it is no longer required. + // Removing the federated token from the session cache entry since it is no longer required. cacheEntry.setFederatedTokens(null); // Add federated tokens to the token response if available. Map additionalAttributes = new HashMap<>(); From f7da3db475a6513728fdc6a2d49c8e17e3076bab Mon Sep 17 00:00:00 2001 From: Indeewai Wijesiri Date: Fri, 8 Mar 2024 08:24:09 +0530 Subject: [PATCH 3/4] Addressing the review comments --- .../endpoint/authz/OAuth2AuthzEndpoint.java | 11 +++++--- .../oauth2/model/FederatedTokenDO.java | 17 ++++++++---- .../FederatedTokenResponseHandler.java | 26 ++++++++++++------- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java index 33cee091614..a09ed069eb4 100644 --- a/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java +++ b/components/org.wso2.carbon.identity.oauth.endpoint/src/main/java/org/wso2/carbon/identity/oauth/endpoint/authz/OAuth2AuthzEndpoint.java @@ -198,7 +198,6 @@ import static org.wso2.carbon.identity.application.authentication.endpoint.util.Constants.MANDATORY_CLAIMS; import static org.wso2.carbon.identity.application.authentication.endpoint.util.Constants.REQUESTED_CLAIMS; import static org.wso2.carbon.identity.application.authentication.endpoint.util.Constants.USER_CLAIMS_CONSENT_ONLY; -import static org.wso2.carbon.identity.application.authentication.framework.handler.request.impl.DefaultAuthenticationRequestHandler.FEDERATED_TOKENS; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.REQUEST_PARAM_SP; import static org.wso2.carbon.identity.client.attestation.mgt.utils.Constants.CLIENT_ATTESTATION_CONTEXT; import static org.wso2.carbon.identity.oauth.common.OAuthConstants.LogConstants.InputKeys.RESPONSE_TYPE; @@ -401,17 +400,21 @@ public Response authorize(@Context HttpServletRequest request, @Context HttpServ private void addFederatedTokensToSessionCache(OAuthMessage oAuthMessage, AuthenticationResult authenticationResult) { + if (!(authenticationResult.getProperty(FrameworkConstants.FEDERATED_TOKENS) instanceof List)) { + return; + } List federatedTokens = - (List) authenticationResult.getProperty(FEDERATED_TOKENS); + (List) authenticationResult.getProperty(FrameworkConstants.FEDERATED_TOKENS); SessionDataCacheEntry sessionDataCacheEntry = oAuthMessage.getSessionDataCacheEntry(); if (sessionDataCacheEntry == null || CollectionUtils.isEmpty(federatedTokens)) { return; } sessionDataCacheEntry.setFederatedTokens(getFederatedTokenDO(federatedTokens)); - if (log.isDebugEnabled()) { + if (log.isDebugEnabled() && authenticationResult.getSubject() != null) { log.debug("Added the federated tokens to the session data cache. Session context identifier: " + - sessionDataCacheEntry.getSessionContextIdentifier()); + sessionDataCacheEntry.getSessionContextIdentifier() + " for the user: " + + authenticationResult.getSubject().getLoggableMaskedUserId()); } } diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/model/FederatedTokenDO.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/model/FederatedTokenDO.java index 844993c4791..c6613fc4644 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/model/FederatedTokenDO.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/model/FederatedTokenDO.java @@ -1,12 +1,19 @@ /* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). * - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). All Rights Reserved. + * WSO2 LLC. 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 * - * This software is the property of WSO2 LLC. and its suppliers, if any. - * Dissemination of any information or reproduction of any material contained - * herein in any form is strictly forbidden, unless permitted by WSO2 expressly. - * You may not alter or remove any copyright or other notice from copies of this content. + * 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.oauth2.model; diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/response/FederatedTokenResponseHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/response/FederatedTokenResponseHandler.java index ac3171ee5b7..1f01b281ac0 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/response/FederatedTokenResponseHandler.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/handlers/response/FederatedTokenResponseHandler.java @@ -1,12 +1,19 @@ /* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). * - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). All Rights Reserved. + * WSO2 LLC. 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 * - * This software is the property of WSO2 LLC. and its suppliers, if any. - * Dissemination of any information or reproduction of any material contained - * herein in any form is strictly forbidden, unless permitted by WSO2 expressly. - * You may not alter or remove any copyright or other notice from copies of this content. + * 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.oauth2.token.handlers.response; @@ -15,7 +22,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.identity.application.authentication.framework.handler.request.impl.DefaultAuthenticationRequestHandler; +import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCache; import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCacheEntry; import org.wso2.carbon.identity.oauth.cache.AuthorizationGrantCacheKey; @@ -64,9 +71,10 @@ public Map getAdditionalTokenResponseAttributes(OAuthTokenReqMes // Add federated tokens to the token response if available. Map additionalAttributes = new HashMap<>(); - additionalAttributes.putIfAbsent(DefaultAuthenticationRequestHandler.FEDERATED_TOKENS, federatedTokens); - if (LOG.isDebugEnabled()) { - LOG.debug("Federated tokens will be added to the additional attributes of the token response."); + additionalAttributes.putIfAbsent(FrameworkConstants.FEDERATED_TOKENS, federatedTokens); + if (LOG.isDebugEnabled() && tokReqMsgCtx.getAuthorizedUser() != null) { + LOG.debug("Federated tokens will be added to the additional attributes of the token response." + + " for the user: " + tokReqMsgCtx.getAuthorizedUser().getLoggableMaskedUserId()); } return additionalAttributes; From 840d5ad409bba4915bb429b2fd792c4a8c49e30b Mon Sep 17 00:00:00 2001 From: Indeewai Wijesiri Date: Mon, 11 Mar 2024 09:29:16 +0530 Subject: [PATCH 4/4] Framework version bump for the federated token sharing --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5cd64d34142..64dca2d9d7e 100644 --- a/pom.xml +++ b/pom.xml @@ -901,7 +901,7 @@ [1.0.1, 2.0.0) - 7.0.75 + 7.0.93 [5.25.234, 8.0.0)