Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding customizable logoutUrl for generic oAuth2 / OpenId connect #2324

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringSubstitutor;
import org.springframework.core.io.Resource;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;

Expand Down Expand Up @@ -150,16 +154,19 @@ private void getRedirect_saml2(
private void getRedirect_oauth2(
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException {
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
String param = "logout=true";
String registrationId = null;
String issuer = null;
String clientId = null;
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
String issuer = oauth.getIssuer();
String clientId = oauth.getClientId();
String idToken = null;

if (authentication instanceof OAuth2AuthenticationToken) {
OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;
registrationId = oauthToken.getAuthorizedClientRegistrationId();

if (oauthToken.getPrincipal() instanceof OidcUser oidcUser) {
idToken = oidcUser.getIdToken().getTokenValue();
}
try {
// Get OAuth2 provider details from configuration
Provider provider = oauth.getClient().get(registrationId);
Expand Down Expand Up @@ -191,8 +198,7 @@ private void getRedirect_oauth2(
param = "error=badcredentials";
}

String redirect_url = UrlUtils.getOrigin(request) + "/login?" + param;

String defaultRedirectUrl = UrlUtils.getOrigin(request) + "/login?" + param;
// Redirect based on OAuth2 provider
switch (registrationId.toLowerCase()) {
case "keycloak":
Expand All @@ -203,7 +209,7 @@ private void getRedirect_oauth2(
+ "?client_id="
+ clientId
+ "&post_logout_redirect_uri="
+ response.encodeRedirectURL(redirect_url);
+ response.encodeRedirectURL(defaultRedirectUrl);
log.info("Redirecting to Keycloak logout URL: " + logoutUrl);
response.sendRedirect(logoutUrl);
break;
Expand All @@ -218,15 +224,28 @@ private void getRedirect_oauth2(
// String googleLogoutUrl =
// "https://accounts.google.com/Logout?continue=https://appengine.google.com/_ah/logout?continue="
// + response.encodeRedirectURL(redirect_url);
log.info("Google does not have a specific logout URL");
// log.info("Redirecting to Google logout URL: " + googleLogoutUrl);
// response.sendRedirect(googleLogoutUrl);
// break;
default:
String defaultRedirectUrl = request.getContextPath() + "/login?" + param;
log.info("Redirecting to default logout URL: " + defaultRedirectUrl);
log.info(
"Google does not have a specific logout URL, redirecting to default logout URL: "
+ defaultRedirectUrl);
response.sendRedirect(defaultRedirectUrl);
break;
default:
String customRedirectUrl = defaultRedirectUrl;
if (StringUtils.isNotBlank(oauth.getLogoutUrl())) {
customRedirectUrl =
issuer
+ StringSubstitutor.replace(
oauth.getLogoutUrl(),
Map.of(
"clientId", StringUtils.defaultString(clientId),
"tokenId", StringUtils.defaultString(idToken),
"redirectUrl", defaultRedirectUrl),
"{",
"}");
}
log.info("Redirecting to logout URL: " + customRedirectUrl);
response.sendRedirect(customRedirectUrl);
break;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ public static class OAUTH2 {
@ToString.Exclude private String clientSecret;
private Boolean autoCreateUser = false;
private Boolean blockRegistration = false;
private String logoutUrl;
private String useAsUsername;
private Collection<String> scopes = new ArrayList<>();
private String provider;
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/settings.yml.template
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ security:
useAsUsername: email # default is 'email'; custom fields can be used as the username
scopes: openid, profile, email # specify the scopes for which the application will request permissions
provider: google # set this to your OAuth provider's name, e.g., 'google' or 'keycloak'
logoutUrl: '' # logout URL to call at he issuer, may be used with 3 variables, for instance : '/connect/logout?id_token_hint={tokenId}&client_id={clientId}&post_logout_redirect_uri={redirectUrl}'
saml2:
enabled: false # currently in alpha, not recommended for use yet, enableAlphaFunctionality must be set to true
autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
Expand Down