From 021b9fee358af1015ed0d8bb6f01f2c17bd879d8 Mon Sep 17 00:00:00 2001 From: janakamarasena Date: Tue, 10 Dec 2024 18:27:09 +0530 Subject: [PATCH] Add app native auth support --- components/uaepass-authenticator/pom.xml | 18 +- .../uaepass/UAEPassAuthenticator.java | 354 +++++++++++++++++- .../UAEPassAuthenticatorConstants.java | 25 +- .../uaepass/UAEPassAuthenticatorTest.java | 168 ++++++++- pom.xml | 11 +- 5 files changed, 551 insertions(+), 25 deletions(-) diff --git a/components/uaepass-authenticator/pom.xml b/components/uaepass-authenticator/pom.xml index 4ff934d..e8a4c50 100644 --- a/components/uaepass-authenticator/pom.xml +++ b/components/uaepass-authenticator/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.uaepass.outbound identity-outbound-auth-uaepass ../../pom.xml - 1.0.5-SNAPSHOT + 1.1.0-SNAPSHOT 4.0.0 @@ -87,6 +87,11 @@ org.wso2.orbit.com.nimbusds nimbus-jose-jwt + + org.wso2.carbon.identity.outbound.auth.oidc + org.wso2.carbon.identity.application.authenticator.oidc + provided + org.jacoco org.jacoco.agent @@ -108,7 +113,8 @@ org.wso2.carbon.identity.authenticator.uaepass.internal - com.nimbusds.jose.util; version="${nimbusds.osgi.version.range}", + com.nimbusds.jose.*; version="${nimbusds.osgi.version.range}", + com.nimbusds.jwt; version="${nimbusds.osgi.version.range}", javax.servlet.http; version="${imp.pkg.version.javax.servlet}", net.minidev.json; version="${net.minidev.json.imp.pkg.version.range}", org.apache.commons.codec.binary; version="${commons-codec.wso2.osgi.version.range}", @@ -152,7 +158,13 @@ org.wso2.carbon.user.core; version="${carbon.kernel.package.import.version.range}", org.wso2.carbon.user.core.util; version="${carbon.kernel.package.import.version.range}", org.wso2.carbon.user.core.service; version="${carbon.kernel.package.import.version.range}", - org.wso2.carbon.user.core.tenant; version="${carbon.kernel.package.import.version.range}" + org.wso2.carbon.user.core.tenant; version="${carbon.kernel.package.import.version.range}", + org.wso2.carbon.identity.application.authenticator.oidc.*; + version="${identity.outbound.auth.oidc.version.range}", + org.wso2.carbon.identity.oauth2; + version="${carbon.identity.inbound.oauth.package.import.version.range}", + org.wso2.carbon.idp.mgt; version="${identity.framework.package.import.version.range}", + org.wso2.carbon.idp.mgt.util; version="${identity.framework.package.import.version.range}" !org.wso2.carbon.identity.authenticator.uaepass.internal, diff --git a/components/uaepass-authenticator/src/main/java/org/wso2/carbon/identity/authenticator/uaepass/UAEPassAuthenticator.java b/components/uaepass-authenticator/src/main/java/org/wso2/carbon/identity/authenticator/uaepass/UAEPassAuthenticator.java index f79b6ed..f0ddd8c 100644 --- a/components/uaepass-authenticator/src/main/java/org/wso2/carbon/identity/authenticator/uaepass/UAEPassAuthenticator.java +++ b/components/uaepass-authenticator/src/main/java/org/wso2/carbon/identity/authenticator/uaepass/UAEPassAuthenticator.java @@ -19,7 +19,10 @@ package org.wso2.carbon.identity.authenticator.uaepass; +import com.nimbusds.jose.JOSEException; import com.nimbusds.jose.util.JSONObjectUtils; +import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jwt.SignedJWT; import net.minidev.json.JSONArray; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang.ArrayUtils; @@ -37,13 +40,23 @@ import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.identity.application.authentication.framework.AbstractApplicationAuthenticator; import org.wso2.carbon.identity.application.authentication.framework.FederatedApplicationAuthenticator; +import org.wso2.carbon.identity.application.authentication.framework.config.model.ExternalIdPConfig; import org.wso2.carbon.identity.application.authentication.framework.context.AuthenticationContext; import org.wso2.carbon.identity.application.authentication.framework.exception.AuthenticationFailedException; import org.wso2.carbon.identity.application.authentication.framework.exception.LogoutFailedException; +import org.wso2.carbon.identity.application.authentication.framework.model.AdditionalData; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; +import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatorData; +import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatorMessage; +import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils; +import org.wso2.carbon.identity.application.authenticator.oidc.NativeSDKBasedFederatedOAuthClientResponse; +import org.wso2.carbon.identity.application.authenticator.oidc.util.OIDCTokenValidationUtil; import org.wso2.carbon.identity.application.common.model.ClaimMapping; +import org.wso2.carbon.identity.application.common.model.IdentityProvider; +import org.wso2.carbon.identity.application.common.model.IdentityProviderProperty; import org.wso2.carbon.identity.application.common.model.Property; +import org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants; import org.wso2.carbon.identity.authenticator.uaepass.exception.UAEPassAuthnFailedException; import org.wso2.carbon.identity.authenticator.uaepass.exception.UAEPassUserInfoFailedException; import org.wso2.carbon.identity.authenticator.uaepass.internal.UAEPassDataHolder; @@ -52,6 +65,10 @@ import org.wso2.carbon.identity.core.URLBuilderException; import org.wso2.carbon.identity.core.util.IdentityCoreConstants; import org.wso2.carbon.identity.core.util.IdentityUtil; +import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; +import org.wso2.carbon.idp.mgt.IdentityProviderManagementException; +import org.wso2.carbon.idp.mgt.IdentityProviderManager; +import org.wso2.carbon.idp.mgt.util.IdPManagementConstants; import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.UserStoreManager; @@ -68,10 +85,20 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; +import java.util.UUID; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import static org.wso2.carbon.identity.authenticator.uaepass.UAEPassAuthenticatorConstants.ACCESS_TOKEN_PARAM; +import static org.wso2.carbon.identity.authenticator.uaepass.UAEPassAuthenticatorConstants.AUTHENTICATOR_I18N_KEY; +import static org.wso2.carbon.identity.authenticator.uaepass.UAEPassAuthenticatorConstants.AUTHENTICATOR_MESSAGE; +import static org.wso2.carbon.identity.authenticator.uaepass.UAEPassAuthenticatorConstants.ID_TOKEN_PARAM; +import static org.wso2.carbon.identity.authenticator.uaepass.UAEPassAuthenticatorConstants.UAE.OAUTH2_GRANT_TYPE_CODE; +import static org.wso2.carbon.identity.authenticator.uaepass.UAEPassAuthenticatorConstants.UAE.OAUTH2_PARAM_STATE; + /** * The UAEPassAuthenticator class contains all the functional tasks handled by the authenticator with UAEPass IdP and * WSO2 Identity Server, such as obtaining an authorization code and access token, federated logout with @@ -92,7 +119,14 @@ public class UAEPassAuthenticator extends AbstractApplicationAuthenticator @Override public boolean canHandle(HttpServletRequest request) { - return UAEPassAuthenticatorConstants.UAE.LOGIN_TYPE.equals(getLoginType(request)); + boolean canHandle; + if (isNativeSDKBasedFederationCall(request)) { + canHandle = true; + } else { + canHandle = UAEPassAuthenticatorConstants.UAE.LOGIN_TYPE.equals(getLoginType(request)); + } + + return canHandle; } /** @@ -139,7 +173,11 @@ public String getClaimDialectURI() { @Override public String getContextIdentifier(HttpServletRequest request) { - String state = request.getParameter(UAEPassAuthenticatorConstants.UAE.OAUTH2_PARAM_STATE); + if (isAPIBasedAuthenticationFlow(request, null)) { + return request.getParameter(UAEPassAuthenticatorConstants.SESSION_DATA_KEY_PARAM); + } + + String state = request.getParameter(OAUTH2_PARAM_STATE); if (StringUtils.isNotBlank(state)) { return state.split(",")[0]; } else { @@ -152,6 +190,7 @@ public String getContextIdentifier(HttpServletRequest request) { } } + /** * Returns all user input fields of the authenticator. * @@ -244,12 +283,14 @@ protected void initiateAuthenticationRequest(HttpServletRequest request, HttpSer } String clientId = authenticatorProperties.get(UAEPassAuthenticatorConstants.UAE.CLIENT_ID); String authorizationEP = getAuthorizeUrl(envUAEPass); - String callBackUrl = authenticatorProperties.get(UAEPassAuthenticatorConstants.UAE.CALLBACK_URL); - String state = context.getContextIdentifier() + "," + UAEPassAuthenticatorConstants.UAE.LOGIN_TYPE; + String callBackUrl = getCallbackUrl(request, authenticatorProperties, context); + + String state = getStateParameter(request, context); + context.setProperty(getName() + UAEPassAuthenticatorConstants.STATE_PARAM_SUFFIX, state); OAuthClientRequest authzRequest = OAuthClientRequest.authorizationLocation(authorizationEP). setClientId(clientId).setRedirectURI(callBackUrl). - setResponseType(UAEPassAuthenticatorConstants.UAE.OAUTH2_GRANT_TYPE_CODE).setState(state). + setResponseType(OAUTH2_GRANT_TYPE_CODE).setState(state). buildQueryMessage(); if (LOG.isDebugEnabled()) { @@ -259,32 +300,42 @@ protected void initiateAuthenticationRequest(HttpServletRequest request, HttpSer if (StringUtils.isNotBlank(authenticatorProperties.get(UAEPassAuthenticatorConstants. UAE.QUERY_PARAMS))) { - loginPage = processAdditionalQueryParamSeperation(authenticatorProperties, loginPage); + loginPage = processAdditionalQueryParamSeperation(authenticatorProperties, loginPage, context); } else { Map paramMap = new HashMap<>(); paramMap.put(UAEPassAuthenticatorConstants.UAE.ACR_VALUES, UAEPassAuthenticatorConstants.UAEPassRuntimeConstants.DEFAULT_ACR_VALUES); paramMap.put(UAEPassAuthenticatorConstants.UAE.SCOPE, UAEPassAuthenticatorConstants.UAEPassRuntimeConstants.DEFAULT_SCOPES); + addScopeToContext(context, UAEPassAuthenticatorConstants.UAEPassRuntimeConstants.DEFAULT_SCOPES); loginPage = FrameworkUtils.buildURLWithQueryParams(loginPage, paramMap); } + context.setProperty(getName() + UAEPassAuthenticatorConstants.REDIRECT_URL_SUFFIX, loginPage); response.sendRedirect(loginPage); } else { - throw new AuthenticationFailedException("Error while retrieving properties. " - + "Authenticator properties cannot be null."); + setAuthenticatorMessageToContext(UAEPassAuthenticatorConstants.ErrorMessages + .RETRIEVING_AUTHENTICATOR_PROPERTIES_FAILED, context); + throw new AuthenticationFailedException(UAEPassAuthenticatorConstants.ErrorMessages + .RETRIEVING_AUTHENTICATOR_PROPERTIES_FAILED.getMessage()); } } catch (UAEPassAuthnFailedException e) { + setAuthenticatorMessageToContext(UAEPassAuthenticatorConstants.ErrorMessages. + AUTHENTICATION_FAILED_PROCESSING_ADDITIONAL_QUERY_PARAMS, context); throw new AuthenticationFailedException(UAEPassAuthenticatorConstants.ErrorMessages. AUTHENTICATION_FAILED_PROCESSING_ADDITIONAL_QUERY_PARAMS.getCode(), UAEPassAuthenticatorConstants. ErrorMessages.AUTHENTICATION_FAILED_PROCESSING_ADDITIONAL_QUERY_PARAMS.getMessage(), e); } catch (IOException e) { + setAuthenticatorMessageToContext(UAEPassAuthenticatorConstants.ErrorMessages. + AUTHENTICATION_FAILED_ENV_SELECTION, context); LOG.error("Authorization request building failed."); throw new AuthenticationFailedException( UAEPassAuthenticatorConstants.ErrorMessages.AUTHENTICATION_FAILED_ENV_SELECTION.getCode(), UAEPassAuthenticatorConstants.ErrorMessages.AUTHENTICATION_FAILED_ENV_SELECTION.getMessage(), e); } catch (OAuthSystemException e) { + setAuthenticatorMessageToContext(UAEPassAuthenticatorConstants.ErrorMessages. + AUTHENTICATION_FAILED_COMPULSORY_QUERY_PARAM_FAILURE, context); LOG.error("Unable to build the request with compulsory query parameters."); throw new AuthenticationFailedException(UAEPassAuthenticatorConstants.ErrorMessages. AUTHENTICATION_FAILED_COMPULSORY_QUERY_PARAM_FAILURE.getCode(), UAEPassAuthenticatorConstants. @@ -305,15 +356,22 @@ protected void processAuthenticationResponse(HttpServletRequest request, HttpSer AuthenticationContext context) throws AuthenticationFailedException { try { - OAuthAuthzResponse authzResponse = OAuthAuthzResponse.oauthCodeAuthzResponse(request); - OAuthClientRequest accessTokenRequest = getAccessTokenRequest(context, authzResponse); - OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient()); - OAuthClientResponse oAuthResponse = getOAuthResponse(oAuthClient, accessTokenRequest); + OAuthClientResponse oAuthResponse; + if (isTrustedTokenIssuer(context) && isNativeSDKBasedFederationCall(request)) { + oAuthResponse = getTokensForNativeAPIBasedAuthCall(request, context); + } else { + OAuthAuthzResponse authzResponse = OAuthAuthzResponse.oauthCodeAuthzResponse(request); + OAuthClientRequest accessTokenRequest = getAccessTokenRequest(context, authzResponse); + OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient()); + oAuthResponse = getOAuthResponse(oAuthClient, accessTokenRequest); + } String accessToken = oAuthResponse.getParam(UAEPassAuthenticatorConstants.UAE.ACCESS_TOKEN); if (StringUtils.isBlank(accessToken)) { - LOG.error("Access token is empty."); - throw new AuthenticationFailedException("Access token is empty."); + setAuthenticatorMessageToContext(UAEPassAuthenticatorConstants. + ErrorMessages.ACCESS_TOKEN_EMPTY, context); + throw new AuthenticationFailedException(UAEPassAuthenticatorConstants. + ErrorMessages.ACCESS_TOKEN_EMPTY.getMessage()); } String idToken = oAuthResponse.getParam(UAEPassAuthenticatorConstants.UAE.ID_TOKEN); @@ -340,8 +398,10 @@ protected void processAuthenticationResponse(HttpServletRequest request, HttpSer forEach(entry -> buildClaimMappings(claims, entry, attributeSeparator)); if (StringUtils.isBlank(authenticatedUserId)) { - throw new AuthenticationFailedException("Cannot find the userId from the id_token sent " - + "by the federated IDP."); + setAuthenticatorMessageToContext(UAEPassAuthenticatorConstants.ErrorMessages. + USER_ID_NOT_FOUND_IN_ID_TOKEN, context); + throw new AuthenticationFailedException(UAEPassAuthenticatorConstants.ErrorMessages. + USER_ID_NOT_FOUND_IN_ID_TOKEN.getMessage()); } authenticatedUser = AuthenticatedUser.createFederateAuthenticatedUserFromSubjectIdentifier (authenticatedUserId); @@ -349,15 +409,21 @@ protected void processAuthenticationResponse(HttpServletRequest request, HttpSer context.setSubject(authenticatedUser); } catch (UAEPassAuthnFailedException e) { + setAuthenticatorMessageToContext(UAEPassAuthenticatorConstants.ErrorMessages. + AUTHENTICATION_FAILED_RETRIEVING_OAUTH_CLIENT_RESPONSE, context); throw new AuthenticationFailedException(UAEPassAuthenticatorConstants.ErrorMessages. AUTHENTICATION_FAILED_RETRIEVING_OAUTH_CLIENT_RESPONSE.getCode(), UAEPassAuthenticatorConstants. ErrorMessages.AUTHENTICATION_FAILED_RETRIEVING_OAUTH_CLIENT_RESPONSE.getMessage(), e); } catch (UAEPassUserInfoFailedException e) { + setAuthenticatorMessageToContext(UAEPassAuthenticatorConstants.ErrorMessages. + AUTHENTICATION_FAILED_ACCESS_TOKEN_REQUEST_FAILURE, context); throw new AuthenticationFailedException(UAEPassAuthenticatorConstants.ErrorMessages. AUTHENTICATION_FAILED_ACCESS_TOKEN_REQUEST_FAILURE.getCode(), UAEPassAuthenticatorConstants. ErrorMessages.AUTHENTICATION_FAILED_ACCESS_TOKEN_REQUEST_FAILURE.getMessage(), e); } catch (OAuthProblemException e) { LOG.error("OAuth authorize response failure."); + setAuthenticatorMessageToContext(UAEPassAuthenticatorConstants.ErrorMessages. + AUTHENTICATION_FAILED_AUTHORIZED_RESPONSE_FAILURE, context); throw new AuthenticationFailedException(UAEPassAuthenticatorConstants.ErrorMessages. AUTHENTICATION_FAILED_AUTHORIZED_RESPONSE_FAILURE.getCode(), UAEPassAuthenticatorConstants. ErrorMessages.AUTHENTICATION_FAILED_AUTHORIZED_RESPONSE_FAILURE.getMessage(), e); @@ -367,6 +433,7 @@ protected void processAuthenticationResponse(HttpServletRequest request, HttpSer /** * Logout initialization will be handled by this method. This includes the functionality to support * common-auth logout of the UAEPass. + * API based logout is not supported. * * @param request The request that is received by the authenticator. * @param response Appends the logout redirect URI once logged out from authenticator. @@ -378,6 +445,10 @@ protected void processAuthenticationResponse(HttpServletRequest request, HttpSer protected void initiateLogoutRequest(HttpServletRequest request, HttpServletResponse response, AuthenticationContext context) throws LogoutFailedException { + if (isAPIBasedAuthenticationFlow(request, context)) { + LOG.debug("API based logout flow is not supported."); + return; + } if (isLogoutEnabled(context)) { try { Map paramMap = new HashMap<>(); @@ -385,7 +456,7 @@ protected void initiateLogoutRequest(HttpServletRequest request, HttpServletResp String callbackURI = authenticatorProperties.get(UAEPassAuthenticatorConstants.UAE.CALLBACK_URL); String sessionID = context.getContextIdentifier() + "," + UAEPassAuthenticatorConstants.UAE.LOGIN_TYPE; - paramMap.put(UAEPassAuthenticatorConstants.UAE.OAUTH2_PARAM_STATE, sessionID); + paramMap.put(OAUTH2_PARAM_STATE, sessionID); String envUAEPass = getUAEPassEnvironment(context); String logoutEndpoint = getLogoutUrl(envUAEPass); @@ -633,7 +704,7 @@ protected OAuthClientResponse getOAuthResponse(OAuthClient oAuthClient, OAuthCli */ protected String getLoginType(HttpServletRequest request) { - String state = request.getParameter(UAEPassAuthenticatorConstants.UAE.OAUTH2_PARAM_STATE); + String state = request.getParameter(OAUTH2_PARAM_STATE); if (StringUtils.isNotBlank(state)) { String[] stateElements = state.split(","); if (stateElements.length > 1) { @@ -654,7 +725,7 @@ protected String getLoginType(HttpServletRequest request) { * @return authzUrl Returns the modified authorized URL appending the additional query params. */ private String processAdditionalQueryParamSeperation(Map authenticatorProperties, String - loginPage) throws UAEPassAuthnFailedException { + loginPage, AuthenticationContext context) throws UAEPassAuthnFailedException { String additionalQueryParams = authenticatorProperties.get(UAEPassAuthenticatorConstants.UAE.QUERY_PARAMS); String[] splittedQueryParamsArr; @@ -671,6 +742,9 @@ private String processAdditionalQueryParamSeperation(Map authent keyValuePairs = (splittedQueryParamsArr[i]).split("="); paramMap.put(keyValuePairs[0], keyValuePairs[1]); } + if (paramMap.containsKey(UAEPassAuthenticatorConstants.UAE.SCOPE)) { + addScopeToContext(context, paramMap.get(UAEPassAuthenticatorConstants.UAE.SCOPE)); + } String finalAuthzUrl = null; try { String authzUrl = FrameworkUtils.buildURLWithQueryParams(loginPage, paramMap); @@ -681,7 +755,9 @@ private String processAdditionalQueryParamSeperation(Map authent if (!(authzUrl.contains(UAEPassAuthenticatorConstants.UAE.SCOPE))) { paramMap.put(UAEPassAuthenticatorConstants.UAE.SCOPE, UAEPassAuthenticatorConstants.UAEPassRuntimeConstants.DEFAULT_SCOPES); + addScopeToContext(context, UAEPassAuthenticatorConstants.UAEPassRuntimeConstants.DEFAULT_SCOPES); } + finalAuthzUrl = FrameworkUtils.buildURLWithQueryParams(loginPage, paramMap); } catch (IllegalArgumentException | UnsupportedEncodingException e) { LOG.error("Authorize URL creation failed due to an issue of additional query parameters."); @@ -972,4 +1048,244 @@ private String getFileConfigValue(String fileConfigKey) { return getAuthenticatorConfig().getParameterMap().get(fileConfigKey); } + + @Override + public boolean isAPIBasedAuthenticationSupported() { + + return true; + } + + /** + * This method is responsible for obtaining authenticator-specific data needed to + * initialize the authentication process within the provided authentication context. + * + * @param context The authentication context containing information about the current authentication attempt. + * @return An {@code Optional} containing an {@code AuthenticatorData} object representing the initiation data. + * If the initiation data is available, it is encapsulated within the {@code Optional}; otherwise, + * an empty {@code Optional} is returned. + */ + @Override + public Optional getAuthInitiationData(AuthenticationContext context) { + + AuthenticatorData authenticatorData = new AuthenticatorData(); + authenticatorData.setName(getName()); + authenticatorData.setDisplayName(getFriendlyName()); + authenticatorData.setI18nKey(getI18nKey()); + String idpName = context.getExternalIdP().getIdPName(); + authenticatorData.setIdp(idpName); + + List requiredParameterList = new ArrayList<>(); + if (isTrustedTokenIssuer(context)) { + requiredParameterList.add(ACCESS_TOKEN_PARAM); + requiredParameterList.add(ID_TOKEN_PARAM); + authenticatorData.setPromptType(FrameworkConstants.AuthenticatorPromptType.INTERNAL_PROMPT); + authenticatorData.setAdditionalData(getAdditionalData(context, true)); + } else { + requiredParameterList.add(OAUTH2_GRANT_TYPE_CODE); + requiredParameterList.add(OAUTH2_PARAM_STATE); + authenticatorData.setPromptType(FrameworkConstants.AuthenticatorPromptType.REDIRECTION_PROMPT); + authenticatorData.setAdditionalData(getAdditionalData(context, false)); + } + authenticatorData.setRequiredParams(requiredParameterList); + if (context.getProperty(AUTHENTICATOR_MESSAGE) != null) { + authenticatorData.setMessage((AuthenticatorMessage) context.getProperty(AUTHENTICATOR_MESSAGE)); + } + + return Optional.of(authenticatorData); + } + + /** + * Get the i18n key defined to represent the authenticator name. + * + * @return the 118n key. + */ + @Override + public String getI18nKey() { + + return AUTHENTICATOR_I18N_KEY; + } + + private boolean isTrustedTokenIssuer(AuthenticationContext context) { + + ExternalIdPConfig externalIdPConfig = context.getExternalIdP(); + if (externalIdPConfig == null) { + return false; + } + + IdentityProvider externalIdentityProvider = externalIdPConfig.getIdentityProvider(); + if (externalIdentityProvider == null) { + return false; + } + + IdentityProviderProperty[] identityProviderProperties = externalIdentityProvider.getIdpProperties(); + for (IdentityProviderProperty identityProviderProperty : identityProviderProperties) { + if (IdPManagementConstants.IS_TRUSTED_TOKEN_ISSUER.equals(identityProviderProperty.getName())) { + return Boolean.parseBoolean(identityProviderProperty.getValue()); + } + } + + return false; + } + + private boolean isNativeSDKBasedFederationCall(HttpServletRequest request) { + + return request.getParameter(ACCESS_TOKEN_PARAM) != null && request.getParameter(ID_TOKEN_PARAM) != null; + } + + private AdditionalData getAdditionalData(AuthenticationContext context, boolean isNativeSDKBasedFederationCall) { + + AdditionalData additionalData = new AdditionalData(); + String currentAuthenticator = getName(); + + if (isNativeSDKBasedFederationCall) { + Map additionalAuthenticationParams = new HashMap<>(); + + additionalAuthenticationParams.put(UAEPassAuthenticatorConstants.CLIENT_ID_PARAM, + context.getAuthenticatorProperties().get(UAEPassAuthenticatorConstants.UAE.CLIENT_ID)); + String scope = (String) context.getProperty(currentAuthenticator + + UAEPassAuthenticatorConstants.SCOPE_PARAM_SUFFIX); + additionalAuthenticationParams.put(UAEPassAuthenticatorConstants.SCOPE, scope); + additionalData.setAdditionalAuthenticationParams(additionalAuthenticationParams); + } else { + additionalData.setRedirectUrl((String) context.getProperty(currentAuthenticator + + UAEPassAuthenticatorConstants.REDIRECT_URL_SUFFIX)); + Map additionalAuthenticationParams = new HashMap<>(); + String state = (String) context.getProperty(currentAuthenticator + + UAEPassAuthenticatorConstants.STATE_PARAM_SUFFIX); + additionalAuthenticationParams.put(UAEPassAuthenticatorConstants.UAE.OAUTH2_PARAM_STATE, state); + additionalData.setAdditionalAuthenticationParams(additionalAuthenticationParams); + } + return additionalData; + } + + private static void setAuthenticatorMessageToContext(UAEPassAuthenticatorConstants.ErrorMessages errorMessage, + AuthenticationContext context) { + + AuthenticatorMessage authenticatorMessage = new AuthenticatorMessage(FrameworkConstants. + AuthenticatorMessageType.ERROR, errorMessage. + getCode(), errorMessage.getMessage(), null); + context.setProperty(AUTHENTICATOR_MESSAGE, authenticatorMessage); + } + + private static void setAuthenticatorMessageToContext(AuthenticatorMessage message, + AuthenticationContext context) { + + context.setProperty(AUTHENTICATOR_MESSAGE, message); + } + + private String getStateParameter(HttpServletRequest request, AuthenticationContext context) { + + String state; + if (isAPIBasedAuthenticationFlow(request, context)) { + state = UUID.randomUUID() + "," + UAEPassAuthenticatorConstants.UAE.LOGIN_TYPE; + } else { + state = context.getContextIdentifier() + "," + UAEPassAuthenticatorConstants.UAE.LOGIN_TYPE; + } + + return state; + } + + /** + * Returns the callback URL of the IdP Hub. + * + * @param authenticatorProperties Authentication properties configured in OIDC federated authenticator + * configuration. + * @param context Authentication context. + * @return If API based authn flow, returns the redirect URL from the authentication context. If not returns the + * callback URL configured in OIDC federated authenticator configuration and if it is empty returns + * /commonauth endpoint URL path as the default value. + */ + private String getCallbackUrl(HttpServletRequest request, Map authenticatorProperties, + AuthenticationContext context) { + + if (isAPIBasedAuthenticationFlow(request, context)) { + return (String) context.getProperty(UAEPassAuthenticatorConstants.REDIRECT_URL); + } + + return authenticatorProperties.get(UAEPassAuthenticatorConstants.UAE.CALLBACK_URL); + } + + private boolean isAPIBasedAuthenticationFlow(HttpServletRequest request, AuthenticationContext context) { + + if (context != null) { + return Boolean.parseBoolean((String) context.getProperty(FrameworkConstants.IS_API_BASED)); + } + return FrameworkUtils.isAPIBasedAuthenticationFlow(request); + } + + /** + * Add scopes to the context to be used with App Native Authentication. + * + * @param context Authentication context. + * @param scope Space separated scopes. + */ + private void addScopeToContext(AuthenticationContext context, String scope) { + + if (StringUtils.isNotBlank(scope)) { + context.setProperty(getName() + UAEPassAuthenticatorConstants.SCOPE_PARAM_SUFFIX, scope); + } + + } + + private OAuthClientResponse getTokensForNativeAPIBasedAuthCall(HttpServletRequest request, + AuthenticationContext context) + throws AuthenticationFailedException { + + String idToken = request.getParameter(ID_TOKEN_PARAM); + String accessToken = request.getParameter(ACCESS_TOKEN_PARAM); + try { + validateJWTToken(context, idToken); + } catch (Exception e) { + setAuthenticatorMessageToContext(UAEPassAuthenticatorConstants.ErrorMessages.JWT_TOKEN_VALIDATION_FAILED, + context); + throw new AuthenticationFailedException(UAEPassAuthenticatorConstants.ErrorMessages. + JWT_TOKEN_VALIDATION_FAILED.getMessage(), e); + } + NativeSDKBasedFederatedOAuthClientResponse nativeSDKBasedFederatedOAuthClientResponse + = new NativeSDKBasedFederatedOAuthClientResponse(); + nativeSDKBasedFederatedOAuthClientResponse.setAccessToken(accessToken); + nativeSDKBasedFederatedOAuthClientResponse.setIdToken(idToken); + + return nativeSDKBasedFederatedOAuthClientResponse; + } + + private void validateJWTToken(AuthenticationContext context, String idToken) throws AuthenticationFailedException, + IdentityOAuth2Exception, JOSEException, IdentityProviderManagementException, ParseException { + + SignedJWT signedJWT = SignedJWT.parse(idToken); + JWTClaimsSet claimsSet = signedJWT.getJWTClaimsSet(); + OIDCTokenValidationUtil.validateIssuerClaim(claimsSet); + String tenantDomain = context.getTenantDomain(); + String idpIdentifier = OIDCTokenValidationUtil.getIssuer(claimsSet); + IdentityProvider identityProvider = getIdentityProvider(idpIdentifier, tenantDomain); + + if (identityProvider == null) { + String msg = String.format( + UAEPassAuthenticatorConstants.ErrorMessages.NO_REGISTERED_IDP_FOR_ISSUER.getCode(), idpIdentifier); + AuthenticatorMessage authenticatorMessage = new AuthenticatorMessage( + FrameworkConstants.AuthenticatorMessageType.ERROR, + UAEPassAuthenticatorConstants.ErrorMessages.NO_REGISTERED_IDP_FOR_ISSUER.getCode(), + msg, + null); + setAuthenticatorMessageToContext(authenticatorMessage, context); + throw new AuthenticationFailedException(msg); + } + + OIDCTokenValidationUtil.validateSignature(signedJWT, identityProvider); + OIDCTokenValidationUtil.validateAudience(claimsSet.getAudience(), identityProvider, tenantDomain); + } + + private IdentityProvider getIdentityProvider(String jwtIssuer, String tenantDomain) + throws IdentityProviderManagementException { + + IdentityProvider identityProvider; + identityProvider = IdentityProviderManager.getInstance().getIdPByMetadataProperty( + IdentityApplicationConstants.IDP_ISSUER_NAME, jwtIssuer, tenantDomain, false); + + if (identityProvider == null) { + identityProvider = IdentityProviderManager.getInstance().getIdPByName(jwtIssuer, tenantDomain); + } + + return identityProvider; + } } diff --git a/components/uaepass-authenticator/src/main/java/org/wso2/carbon/identity/authenticator/uaepass/UAEPassAuthenticatorConstants.java b/components/uaepass-authenticator/src/main/java/org/wso2/carbon/identity/authenticator/uaepass/UAEPassAuthenticatorConstants.java index a774a9b..4a15393 100644 --- a/components/uaepass-authenticator/src/main/java/org/wso2/carbon/identity/authenticator/uaepass/UAEPassAuthenticatorConstants.java +++ b/components/uaepass-authenticator/src/main/java/org/wso2/carbon/identity/authenticator/uaepass/UAEPassAuthenticatorConstants.java @@ -24,6 +24,22 @@ */ public class UAEPassAuthenticatorConstants { + public static final String AUTHENTICATOR_I18N_KEY = "authenticator.uaepass"; + public static final String ACCESS_TOKEN_PARAM = "accessToken"; + public static final String ID_TOKEN_PARAM = "idToken"; + public static final String SESSION_DATA_KEY_PARAM = "sessionDataKey"; + public static final String CLIENT_ID_PARAM = "clientId"; + public static final String AUTHENTICATOR_MESSAGE = "authenticatorMessage"; + public static final String REDIRECT_URL_SUFFIX = "_redirect_url"; + public static final String STATE_PARAM_SUFFIX = "_state_param"; + public static final String SCOPE_PARAM_SUFFIX = "_scope_param"; + public static final String SCOPE = "scope"; + public static final String REDIRECT_URL = "REDIRECT_URL"; + + private UAEPassAuthenticatorConstants() { + + } + public enum ErrorMessages { USER_ID_NOT_FOUND_IN_ID_TOKEN_SENT_BY_FEDERATED_IDP("UAEPass-65001", @@ -49,7 +65,14 @@ public enum ErrorMessages { UAEPASS_AUTHN_FAILED_ACCESS_TOKEN_BUILD_FAILURE("UAEPass-65011", "UAEPass Authentication" + "Exception while building access token request with the request body"), UAEPASS_AUTHN_FAILED_ABSOLUTE_URL_BUILD_FAILURE("UAEPass-65012", "Error occurred while " + - "extracting the absolute public URL from the browser"); + "extracting the absolute public URL from the browser"), + ACCESS_TOKEN_EMPTY("UAEPass-65013", "Access token is empty"), + RETRIEVING_AUTHENTICATOR_PROPERTIES_FAILED("UAEPass-65014", "Error while retrieving properties. " + + "Authenticator properties cannot be null."), + USER_ID_NOT_FOUND_IN_ID_TOKEN("UAEPass-65015", "Cannot find the userId from the id_token sent " + + "by the federated IDP."), + NO_REGISTERED_IDP_FOR_ISSUER("UAEPass-65016", "No registered IdP found for the issuer: %s"), + JWT_TOKEN_VALIDATION_FAILED("UAEPass-65017", "Error while validating the JWT token"); private final String code; private final String message; diff --git a/components/uaepass-authenticator/src/test/java/org/wso2/carbon/identity/authenticator/uaepass/UAEPassAuthenticatorTest.java b/components/uaepass-authenticator/src/test/java/org/wso2/carbon/identity/authenticator/uaepass/UAEPassAuthenticatorTest.java index d06b13b..c94e994 100644 --- a/components/uaepass-authenticator/src/test/java/org/wso2/carbon/identity/authenticator/uaepass/UAEPassAuthenticatorTest.java +++ b/components/uaepass-authenticator/src/test/java/org/wso2/carbon/identity/authenticator/uaepass/UAEPassAuthenticatorTest.java @@ -19,6 +19,8 @@ package org.wso2.carbon.identity.authenticator.uaepass; +import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jwt.SignedJWT; import org.apache.commons.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.oltu.oauth2.client.OAuthClient; @@ -30,7 +32,9 @@ import org.apache.oltu.oauth2.common.exception.OAuthSystemException; import org.mockito.Matchers; import org.mockito.Mock; +import org.mockito.Mockito; import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; import org.powermock.modules.testng.PowerMockTestCase; import org.testng.Assert; import org.testng.annotations.BeforeTest; @@ -41,10 +45,16 @@ import org.wso2.carbon.identity.application.authentication.framework.config.model.ExternalIdPConfig; import org.wso2.carbon.identity.application.authentication.framework.context.AuthenticationContext; import org.wso2.carbon.identity.application.authentication.framework.exception.AuthenticationFailedException; +import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticationRequest; +import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatorData; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; +import org.wso2.carbon.identity.application.authenticator.oidc.util.OIDCTokenValidationUtil; import org.wso2.carbon.identity.application.common.model.ClaimMapping; +import org.wso2.carbon.identity.application.common.model.IdentityProvider; +import org.wso2.carbon.identity.application.common.model.IdentityProviderProperty; import org.wso2.carbon.identity.application.common.model.Property; import org.wso2.carbon.identity.application.common.model.SubProperty; +import org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants; import org.wso2.carbon.identity.authenticator.uaepass.exception.UAEPassAuthnFailedException; import org.wso2.carbon.identity.authenticator.uaepass.internal.UAEPassDataHolder; import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataManagementService; @@ -53,6 +63,8 @@ import org.wso2.carbon.identity.core.util.IdentityCoreConstants; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; import org.wso2.carbon.identity.core.util.IdentityUtil; +import org.wso2.carbon.idp.mgt.IdentityProviderManager; +import org.wso2.carbon.idp.mgt.util.IdPManagementConstants; import org.wso2.carbon.user.api.RealmConfiguration; import org.wso2.carbon.user.core.UserRealm; import org.wso2.carbon.user.core.UserStoreManager; @@ -63,10 +75,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; +import static org.powermock.api.mockito.PowerMockito.doNothing; import static org.powermock.api.mockito.PowerMockito.mock; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; @@ -79,7 +94,8 @@ @PrepareForTest({LogFactory.class, OAuthAuthzResponse.class, OAuthClientRequest.class, UAEPassDataHolder.class, URL.class, ServiceURLBuilder.class, OAuthClientResponse.class, IdentityUtil.class, UAEPassAuthenticator.class, UAEPassAuthenticatorConstants.class, AbstractApplicationAuthenticator.class, Property.class, Log.class, - IdentityTenantUtil.class}) + IdentityTenantUtil.class, OIDCTokenValidationUtil.class, IdentityProviderManager.class}) +@SuppressStaticInitializationFor({"org.wso2.carbon.idp.mgt.IdentityProviderManager"}) public class UAEPassAuthenticatorTest extends PowerMockTestCase { private static final String accessToken = "fd2fffca-b5e2-466d-aac9-207382497b88"; @@ -139,6 +155,18 @@ public class UAEPassAuthenticatorTest extends PowerMockTestCase { @Mock private UserRealm mockUserRealm; private Map paramValueMap; + @Mock + private IdentityProvider identityProvider; + @Mock + private IdentityProviderManager identityProviderManager; + + private static final String SESSION_DATA_KEY = "7b1c8131-c6bd-4682-892e-1a948a9e57e8"; + private static final String CLIENT_ID = "u5FIfG5xzLvBGiamoAYzzcqpBqga"; + private static final String SUPER_TENANT = "carbon.super"; + private AuthenticationRequest mockAuthenticationRequest = new AuthenticationRequest(); + private static final String REDIRECT_URL = "https://stg-id.uaepass.ae/idshub/authorize?scope=openid&" + + "response_type=code&redirect_uri=https%3A%2F%2Flocalhost%3A9443%2Fcommonauth&" + + "state=958e9049-8cd2-4580-8745-6679ac8d33f6%2COIDC&client_id=sample.client-id"; @BeforeTest public void init() { @@ -516,4 +544,142 @@ public void testGetConfigurationProperties() { Assert.assertNotEquals(expectedResult, result); } + + @Test + public void testCanHandleForNativeSDKBasedFederation() { + + when(mockServletRequest.getParameter(UAEPassAuthenticatorConstants.ACCESS_TOKEN_PARAM)) + .thenReturn(accessToken); + when(mockServletRequest.getParameter(UAEPassAuthenticatorConstants.ID_TOKEN_PARAM)).thenReturn(idToken); + when(mockServletRequest.getParameter(UAEPassAuthenticatorConstants.SESSION_DATA_KEY_PARAM)) + .thenReturn(SESSION_DATA_KEY); + when(mockServletRequest.getAttribute(FrameworkConstants.IS_API_BASED_AUTH_FLOW)).thenReturn(true); + + Assert.assertTrue(uaePassAuthenticator.canHandle(mockServletRequest)); + Assert.assertEquals(uaePassAuthenticator.getContextIdentifier(mockServletRequest), SESSION_DATA_KEY); + } + + @Test + public void testGetI18nKey() { + + String i18nKey = uaePassAuthenticator.getI18nKey(); + Assert.assertEquals(i18nKey, UAEPassAuthenticatorConstants.AUTHENTICATOR_I18N_KEY); + } + + @Test + public void testPassProcessAuthenticationResponseWithNativeSDKBaseFederation() throws Exception { + + setupTest(); + IdentityProviderProperty property = new IdentityProviderProperty(); + property.setName(IdPManagementConstants.IS_TRUSTED_TOKEN_ISSUER); + property.setValue("true"); + IdentityProviderProperty[] identityProviderProperties = new IdentityProviderProperty[1]; + identityProviderProperties[0] = property; + when(mockAuthenticationContext.getExternalIdP()).thenReturn(externalIdPConfig); + when(externalIdPConfig.getIdentityProvider()).thenReturn(identityProvider); + when(identityProvider.getIdpProperties()).thenReturn(identityProviderProperties); + when(mockAuthenticationContext.getExternalIdP()).thenReturn(externalIdPConfig); + when(mockServletRequest.getParameter(UAEPassAuthenticatorConstants.ID_TOKEN_PARAM)) + .thenReturn(idToken); + when(mockServletRequest.getParameter(UAEPassAuthenticatorConstants.ACCESS_TOKEN_PARAM)) + .thenReturn(accessToken); + + mockStatic(OIDCTokenValidationUtil.class); + doNothing().when(OIDCTokenValidationUtil.class, "validateIssuerClaim", Mockito.any((JWTClaimsSet.class))); + when(mockAuthenticationContext.getTenantDomain()).thenReturn(SUPER_TENANT); + mockStatic(IdentityProviderManager.class); + when(IdentityProviderManager.getInstance()).thenReturn(identityProviderManager); + when(identityProviderManager.getIdPByMetadataProperty( + Mockito.eq(IdentityApplicationConstants.IDP_ISSUER_NAME), anyString(), Mockito.eq(SUPER_TENANT), + Mockito.eq(false))).thenReturn(identityProvider); + doNothing().when(OIDCTokenValidationUtil.class, "validateSignature", Mockito.any(SignedJWT.class), + Mockito.any(IdentityProvider.class)); + doNothing().when(OIDCTokenValidationUtil.class, "validateAudience", Mockito.any(List.class), Mockito.any(), + anyString()); + + when(openIDConnectAuthenticatorDataHolder.getClaimMetadataManagementService()).thenReturn + (claimMetadataManagementService); + uaePassAuthenticator.processAuthenticationResponse(mockServletRequest, + mockServletResponse, mockAuthenticationContext); + + assertEquals(mockAuthenticationContext.getProperty(UAEPassAuthenticatorConstants.UAE.ACCESS_TOKEN), + accessToken, "Invalid access token in the authentication context."); + + assertEquals(mockAuthenticationContext.getProperty(UAEPassAuthenticatorConstants.UAE.ID_TOKEN), idToken, + "Invalid Id token in the authentication context."); + } + + @Test + public void testGetAuthInitiationDataForNativeSDKBasedFederation() { + + IdentityProviderProperty property = new IdentityProviderProperty(); + property.setName(IdPManagementConstants.IS_TRUSTED_TOKEN_ISSUER); + property.setValue("true"); + IdentityProviderProperty[] identityProviderProperties = new IdentityProviderProperty[1]; + identityProviderProperties[0] = property; + + when(mockAuthenticationContext.getExternalIdP()).thenReturn(externalIdPConfig); + when(externalIdPConfig.getIdPName()). + thenReturn(UAEPassAuthenticatorConstants.UAE.FEDERATED_IDP_COMPONENT_NAME); + when(externalIdPConfig.getIdentityProvider()).thenReturn(identityProvider); + when(identityProvider.getIdpProperties()).thenReturn(identityProviderProperties); + when(mockAuthenticationContext.getAuthenticationRequest()).thenReturn(mockAuthenticationRequest); + when(mockAuthenticationContext.getAuthenticatorProperties()).thenReturn(authenticatorProperties); + authenticatorProperties.put(UAEPassAuthenticatorConstants.UAE.CLIENT_ID, CLIENT_ID); + + Optional authenticatorData = uaePassAuthenticator.getAuthInitiationData + (mockAuthenticationContext); + + Assert.assertTrue(authenticatorData.isPresent()); + AuthenticatorData authenticatorDataObj = authenticatorData.get(); + + Assert.assertEquals(authenticatorDataObj.getName(), + UAEPassAuthenticatorConstants.UAE.FEDERATED_IDP_COMPONENT_NAME); + Assert.assertEquals(authenticatorDataObj.getI18nKey(), UAEPassAuthenticatorConstants.AUTHENTICATOR_I18N_KEY); + Assert.assertEquals(authenticatorDataObj.getDisplayName(), + UAEPassAuthenticatorConstants.UAE.FEDERATED_IDP_COMPONENT_FRIENDLY_NAME); + Assert.assertEquals(authenticatorDataObj.getRequiredParams().size(), + 2); + Assert.assertEquals(authenticatorDataObj.getPromptType(), + FrameworkConstants.AuthenticatorPromptType.INTERNAL_PROMPT); + Assert.assertTrue(authenticatorDataObj.getRequiredParams() + .contains(UAEPassAuthenticatorConstants.ACCESS_TOKEN_PARAM)); + Assert.assertTrue(authenticatorDataObj.getRequiredParams() + .contains(UAEPassAuthenticatorConstants.ID_TOKEN_PARAM)); + Assert.assertEquals(authenticatorDataObj.getAdditionalData() + .getAdditionalAuthenticationParams().get(UAEPassAuthenticatorConstants.CLIENT_ID_PARAM), CLIENT_ID); + } + + @Test + public void testGetAuthInitiationData() { + + when(mockAuthenticationContext.getExternalIdP()).thenReturn(externalIdPConfig); + when(externalIdPConfig.getIdPName()) + .thenReturn(UAEPassAuthenticatorConstants.UAE.FEDERATED_IDP_COMPONENT_NAME); + when(mockAuthenticationContext.getAuthenticationRequest()).thenReturn(mockAuthenticationRequest); + when(mockAuthenticationContext.getProperty( + UAEPassAuthenticatorConstants.UAE.FEDERATED_IDP_COMPONENT_NAME + + UAEPassAuthenticatorConstants.REDIRECT_URL_SUFFIX)) + .thenReturn(REDIRECT_URL); + Optional authenticatorData = uaePassAuthenticator.getAuthInitiationData + (mockAuthenticationContext); + + Assert.assertTrue(authenticatorData.isPresent()); + AuthenticatorData authenticatorDataObj = authenticatorData.get(); + + Assert.assertEquals(authenticatorDataObj.getName(), + UAEPassAuthenticatorConstants.UAE.FEDERATED_IDP_COMPONENT_NAME); + Assert.assertEquals(authenticatorDataObj.getI18nKey(), UAEPassAuthenticatorConstants.AUTHENTICATOR_I18N_KEY); + Assert.assertEquals(authenticatorDataObj.getDisplayName(), + UAEPassAuthenticatorConstants.UAE.FEDERATED_IDP_COMPONENT_FRIENDLY_NAME); + Assert.assertEquals(authenticatorDataObj.getRequiredParams().size(), + 2); + Assert.assertEquals(authenticatorDataObj.getPromptType(), + FrameworkConstants.AuthenticatorPromptType.REDIRECTION_PROMPT); + Assert.assertTrue(authenticatorDataObj.getRequiredParams() + .contains(UAEPassAuthenticatorConstants.UAE.OAUTH2_GRANT_TYPE_CODE)); + Assert.assertTrue(authenticatorDataObj.getRequiredParams() + .contains(UAEPassAuthenticatorConstants.UAE.OAUTH2_PARAM_STATE)); + Assert.assertEquals(authenticatorDataObj.getAdditionalData().getRedirectUrl(), REDIRECT_URL); + } } diff --git a/pom.xml b/pom.xml index 4d89598..da66bee 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ org.wso2.carbon.identity.uaepass.outbound 4.0.0 identity-outbound-auth-uaepass - 1.0.5-SNAPSHOT + 1.1.0-SNAPSHOT pom UAEPass Outbound Authenticator http://wso2.org @@ -124,6 +124,11 @@ nimbus-jose-jwt ${nimbusds.version} + + org.wso2.carbon.identity.outbound.auth.oidc + org.wso2.carbon.identity.application.authenticator.oidc + ${identity.outbound.auth.oidc.version} + org.jacoco org.jacoco.agent @@ -320,6 +325,10 @@ 2.3.1 3.0.4 findbugs-exclude-filter.xml + 5.12.3 + [5.12.3, 6.0.0) + [6.0.0, 8.0.0) +