use of org.wso2.carbon.identity.oidc.session.cache.OIDCSessionDataCacheEntry in project identity-inbound-auth-oauth by wso2-extensions.
the class OIDCLogoutServlet method generatePostLogoutRedirectUrl.
/**
* If postLogoutRedirectUri is send in Logout request parameter then set it as redirect URL.
*
* @param redirectURL Redirect URL.
* @param opBrowserStateCookieValue OP browser state cookie value.
* @param request HttpServletRequest.
* @return If postLogoutRedirectUri is sent in Logout request parameter then return it as redirect URL.
* @throws UnsupportedEncodingException
*/
private String generatePostLogoutRedirectUrl(String redirectURL, String opBrowserStateCookieValue, HttpServletRequest request) throws UnsupportedEncodingException {
// Set postLogoutRedirectUri as redirectURL.
boolean postLogoutRedirectUriRedirectIsEnabled = Boolean.parseBoolean(IdentityUtil.getProperty(OIDC_LOGOUT_CONSENT_DENIAL_REDIRECT_URL));
if (postLogoutRedirectUriRedirectIsEnabled) {
OIDCSessionDataCacheEntry cacheEntry = getSessionDataFromCache(opBrowserStateCookieValue);
if (cacheEntry != null && cacheEntry.getPostLogoutRedirectUri() != null) {
Map<String, String> params = new HashMap<>();
params.put(OAuthConstants.OAUTH_ERROR, OAuth2ErrorCodes.ACCESS_DENIED);
params.put(OAuthConstants.OAUTH_ERROR_DESCRIPTION, "End User denied the logout request");
if (cacheEntry.getState() != null) {
params.put(OAuthConstants.OAuth20Params.STATE, cacheEntry.getState());
}
redirectURL = FrameworkUtils.buildURLWithQueryParams(cacheEntry.getPostLogoutRedirectUri(), params);
}
}
return buildRedirectURLAfterLogout(redirectURL, request);
}
use of org.wso2.carbon.identity.oidc.session.cache.OIDCSessionDataCacheEntry in project identity-inbound-auth-oauth by wso2-extensions.
the class OIDCLogoutServlet method handleLogoutResponseFromFramework.
private void handleLogoutResponseFromFramework(HttpServletRequest request, HttpServletResponse response) throws IOException {
String sessionDataKey = request.getParameter(FrameworkConstants.SESSION_DATA_KEY);
OIDCSessionDataCacheEntry cacheEntry = getSessionDataFromCache(sessionDataKey);
String obpsCookieValue = getOPBrowserState(request);
String tenantDomain = OAuth2Util.resolveTenantDomain(request);
if (cacheEntry != null) {
if (log.isDebugEnabled()) {
String clientId = cacheEntry.getParamMap().get(OIDCSessionConstants.OIDC_CACHE_CLIENT_ID_PARAM);
String sidClaim;
log.debug("Logout request received from client: " + clientId);
if (StringUtils.isNotBlank(obpsCookieValue)) {
OIDCSessionState sessionState = OIDCSessionManagementUtil.getSessionManager().getOIDCSessionState(obpsCookieValue, tenantDomain);
if (sessionState != null) {
sidClaim = sessionState.getSidClaim();
log.debug("Logout request received for sessionId: " + sidClaim);
}
}
}
// BackChannel logout request.
doBackChannelLogout(obpsCookieValue, tenantDomain);
String redirectURL = cacheEntry.getPostLogoutRedirectUri();
if (redirectURL == null) {
redirectURL = OIDCSessionManagementUtil.getOIDCLogoutURL();
}
try {
triggerLogoutHandlersForPostLogout(request, response);
} catch (OIDCSessionManagementException e) {
log.error("Error executing logout handlers on post logout.");
if (log.isDebugEnabled()) {
log.debug("Error executing logout handlers on post logout.", e);
}
response.sendRedirect(getRedirectURL(getErrorPageURL(OAuth2ErrorCodes.SERVER_ERROR, "User logout failed."), request));
}
redirectURL = appendStateQueryParam(redirectURL, cacheEntry.getState());
removeSessionDataFromCache(sessionDataKey);
OIDCSessionManagementUtil.getSessionManager().removeOIDCSessionState(obpsCookieValue, tenantDomain);
// Clear binding elements from the response.
clearTokenBindingElements(cacheEntry.getParamMap().get(OIDCSessionConstants.OIDC_CACHE_CLIENT_ID_PARAM), request, response);
response.sendRedirect(buildRedirectURLAfterLogout(redirectURL, request));
} else {
response.sendRedirect(getRedirectURL(getErrorPageURL(OAuth2ErrorCodes.SERVER_ERROR, "User logout failed"), request));
}
}
use of org.wso2.carbon.identity.oidc.session.cache.OIDCSessionDataCacheEntry in project identity-inbound-auth-oauth by wso2-extensions.
the class OIDCLogoutServlet method doGet.
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/**
* Recommended Parameter : id_token_hint
* As per the specification https://openid.net/specs/openid-connect-session-1_0.html#RFC6454, it's recommended
* to expect id_token_hint parameter to determine which RP initiated the logout request.
* Otherwise, it could lead to DoS attacks. Thus, at least explicit user confirmation is needed to act upon
* such logout requests.
*
* Optional Parameter : post_logout_redirect_uri
* This denotes the RP URL to be redirected after logout has been performed. This value must be previously
* registered at IdP via post_logout_redirect_uris registration parameter or by some other configuration. And
* the received URL should be validated to be one of registered.
*/
/**
* todo: At the moment we do not persist id_token issued for clients, thus we could not retrieve the RP that
* todo: a specific id_token has been issued.
* todo: Since we use a browser cookie to track the session, for the moment, we
* todo: will validate if the logout request is being initiated by an active session via the cookie
* todo: This need to be fixed such that we do not rely on the cookie and the request is validated against
* todo: the id_token_hint received
*
* todo: Should provide a way to register post_logout_redirect_uris at IdP and should validate the received
* todo: parameter against the set of registered values. This depends on retrieving client for the received
* todo: id_token_hint value
*/
String redirectURL;
String opBrowserState = getOPBrowserState(request);
if (StringUtils.isBlank(opBrowserState)) {
String msg = OIDCSessionConstants.OPBS_COOKIE_ID + " cookie not received. Missing session state.";
if (log.isDebugEnabled()) {
log.debug(msg);
}
if (OIDCSessionManagementUtil.handleAlreadyLoggedOutSessionsGracefully()) {
handleMissingSessionStateGracefully(request, response);
return;
} else {
if (log.isDebugEnabled()) {
msg = "HandleAlreadyLoggedOutSessionsGracefully configuration disabled. Missing session state is " + "handled by redirecting to error page instead of default logout page.";
log.debug(msg);
}
redirectURL = getErrorPageURL(OAuth2ErrorCodes.ACCESS_DENIED, msg);
response.sendRedirect(getRedirectURL(redirectURL, request));
return;
}
}
if (!OIDCSessionManagementUtil.getSessionManager().sessionExists(opBrowserState, OAuth2Util.resolveTenantDomain(request))) {
String msg = "No valid session found for the received session state.";
if (log.isDebugEnabled()) {
log.debug(msg);
}
OIDCSessionManagementUtil.removeOPBrowserStateCookie(request, response);
if (OIDCSessionManagementUtil.handleAlreadyLoggedOutSessionsGracefully()) {
handleMissingSessionStateGracefully(request, response);
} else {
if (log.isDebugEnabled()) {
msg = "HandleAlreadyLoggedOutSessionsGracefully configuration enabled. No valid session found is " + "handled by redirecting to error page instead of default logout page.";
log.debug(msg);
}
redirectURL = getErrorPageURL(OAuth2ErrorCodes.ACCESS_DENIED, msg);
response.sendRedirect(getRedirectURL(redirectURL, request));
}
return;
}
String consent = request.getParameter(OIDCSessionConstants.OIDC_LOGOUT_CONSENT_PARAM);
if (StringUtils.isNotBlank(consent)) {
// User consent received for logout
if (consent.equals(OAuthConstants.Consent.APPROVE)) {
// User approved logout. Logout from authentication framework
sendToFrameworkForLogout(request, response);
return;
} else {
// User denied logout.
redirectURL = getErrorPageURL(OAuth2ErrorCodes.ACCESS_DENIED, "End User denied the logout request");
// If postlogoutUri is available then set it as redirectUrl
redirectURL = generatePostLogoutRedirectUrl(redirectURL, opBrowserState, request);
response.sendRedirect(redirectURL);
return;
}
} else {
// OIDC Logout response
String sessionDataKey = request.getParameter(OIDCSessionConstants.OIDC_SESSION_DATA_KEY_PARAM);
if (sessionDataKey != null) {
handleLogoutResponseFromFramework(request, response);
return;
}
String idTokenHint = request.getParameter(OIDCSessionConstants.OIDC_ID_TOKEN_HINT_PARAM);
boolean skipConsent;
// Get user consent to logout
try {
skipConsent = getOpenIDConnectSkipUserConsent(request);
} catch (ParseException e) {
if (log.isDebugEnabled()) {
log.debug("Error while getting clientId from the IdTokenHint.", e);
}
redirectURL = getErrorPageURL(OAuth2ErrorCodes.ACCESS_DENIED, "ID token signature validation failed.");
response.sendRedirect(getRedirectURL(redirectURL, request));
return;
} catch (IdentityOAuth2ClientException e) {
if (log.isDebugEnabled()) {
log.debug("Error while getting service provider from the clientId.", e);
}
redirectURL = getErrorPageURL(OAuth2ErrorCodes.ACCESS_DENIED, "ID token signature validation failed.");
response.sendRedirect(getRedirectURL(redirectURL, request));
return;
} catch (IdentityOAuth2Exception e) {
log.error("Error occurred while getting oauth application information.", e);
return;
}
if (skipConsent) {
if (StringUtils.isNotBlank(idTokenHint)) {
redirectURL = processLogoutRequest(request, response);
if (StringUtils.isNotBlank(redirectURL)) {
response.sendRedirect(getRedirectURL(redirectURL, request));
return;
}
} else {
// Add OIDC Cache entry without properties since OIDC Logout should work without id_token_hint
OIDCSessionDataCacheEntry cacheEntry = new OIDCSessionDataCacheEntry();
/*
Logout request without id_token_hint will redirected to an IDP's page once logged out, rather a
RP's callback endpoint. The state parameter is set here in the cache, so that it will be
available in the redirected IDP's page to support any custom requirement.
*/
setStateParameterInCache(request, cacheEntry);
addSessionDataToCache(opBrowserState, cacheEntry);
}
sendToFrameworkForLogout(request, response);
return;
} else {
sendToConsentUri(request, response);
return;
}
}
}
use of org.wso2.carbon.identity.oidc.session.cache.OIDCSessionDataCacheEntry in project identity-inbound-auth-oauth by wso2-extensions.
the class OIDCLogoutServlet method sendToFrameworkForLogout.
private void sendToFrameworkForLogout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
triggerLogoutHandlersForPreLogout(request, response);
} catch (OIDCSessionManagementException e) {
log.error("Error executing logout handlers on pre logout.");
if (log.isDebugEnabled()) {
log.debug("Error executing logout handlers on pre logout.", e);
}
response.sendRedirect(getRedirectURL(getErrorPageURL(OAuth2ErrorCodes.SERVER_ERROR, "User logout failed."), request));
}
// Generate a SessionDataKey. Authentication framework expects this parameter
String sessionDataKey = UUID.randomUUID().toString();
String opBrowserStateCookieValue = OIDCSessionManagementUtil.getOPBrowserStateCookie(request).getValue();
// Add all parameters to authentication context before sending to authentication framework
AuthenticationRequest authenticationRequest = new AuthenticationRequest();
Map<String, String[]> map = new HashMap<>();
map.put(OIDCSessionConstants.OIDC_SESSION_DATA_KEY_PARAM, new String[] { sessionDataKey });
authenticationRequest.setRequestQueryParams(map);
authenticationRequest.addRequestQueryParam(FrameworkConstants.RequestParams.LOGOUT, new String[] { "true" });
try {
authenticationRequest.setCommonAuthCallerPath(ServiceURLBuilder.create().addPath(OIDC_LOGOUT_ENDPOINT).build().getRelativeInternalURL());
} catch (URLBuilderException e) {
log.error("Error building commonauth caller path to send logout request to framework.", e);
response.sendRedirect(getRedirectURL(getErrorPageURL(OAuth2ErrorCodes.SERVER_ERROR, "User logout failed."), request));
}
authenticationRequest.setPost(true);
OIDCSessionDataCacheEntry cacheEntry = getSessionDataFromCache(opBrowserStateCookieValue);
if (cacheEntry != null) {
authenticationRequest.setRelyingParty(cacheEntry.getParamMap().get(OIDCSessionConstants.OIDC_CACHE_CLIENT_ID_PARAM));
authenticationRequest.setTenantDomain(cacheEntry.getParamMap().get(OIDCSessionConstants.OIDC_CACHE_TENANT_DOMAIN_PARAM));
addOPBSCookieValueToCacheEntry(opBrowserStateCookieValue, cacheEntry);
addSessionDataToCache(sessionDataKey, cacheEntry);
}
// Add headers to AuthenticationRequestContext
for (Enumeration e = request.getHeaderNames(); e.hasMoreElements(); ) {
String headerName = e.nextElement().toString();
authenticationRequest.addHeader(headerName, request.getHeader(headerName));
}
AuthenticationRequestCacheEntry authenticationRequestCacheEntry = new AuthenticationRequestCacheEntry(authenticationRequest);
addAuthenticationRequestToRequest(request, authenticationRequestCacheEntry);
OIDCSessionManagementUtil.removeOPBrowserStateCookie(request, response);
sendRequestToFramework(request, response, sessionDataKey, FrameworkConstants.RequestType.CLAIM_TYPE_OIDC);
}
use of org.wso2.carbon.identity.oidc.session.cache.OIDCSessionDataCacheEntry in project identity-inbound-auth-oauth by wso2-extensions.
the class OIDCLogoutServlet method sendToConsentUri.
/**
* Send request to consent URI.
*
* @param request Http servlet request
* @param response Http servlet response
* @throws IOException
*/
private void sendToConsentUri(HttpServletRequest request, HttpServletResponse response) throws IOException {
String idTokenHint = request.getParameter(OIDCSessionConstants.OIDC_ID_TOKEN_HINT_PARAM);
String redirectURL = OIDCSessionManagementUtil.getOIDCLogoutConsentURL();
if (idTokenHint != null) {
redirectURL = processLogoutRequest(request, response);
if (StringUtils.isNotBlank(redirectURL)) {
response.sendRedirect(getRedirectURL(redirectURL, request));
return;
} else {
redirectURL = OIDCSessionManagementUtil.getOIDCLogoutConsentURL();
}
} else {
// Add OIDC Cache entry without properties since OIDC Logout should work without id_token_hint
OIDCSessionDataCacheEntry cacheEntry = new OIDCSessionDataCacheEntry();
// Logout request without id_token_hint will redirected to an IDP's page once logged out, rather a RP's
// callback endpoint. The state parameter is set here in the cache, so that it will be available in the
// redirected IDP's page to support any custom requirement.
setStateParameterInCache(request, cacheEntry);
Cookie opBrowserStateCookie = OIDCSessionManagementUtil.getOPBrowserStateCookie(request);
addSessionDataToCache(opBrowserStateCookie.getValue(), cacheEntry);
}
response.sendRedirect(getRedirectURL(redirectURL, request));
}
Aggregations