Skip to content

Commit

Permalink
Remember idp switch choice after stepup
Browse files Browse the repository at this point in the history
  • Loading branch information
oharsta committed Jun 18, 2024
1 parent 19d10ce commit 06181b5
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package dashboard.control;

import dashboard.domain.CoinUser;
import dashboard.domain.IdentityProvider;
import dashboard.util.SpringSecurity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
Expand All @@ -8,6 +11,7 @@
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
Expand All @@ -17,21 +21,26 @@
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@RestController
public class LoginController {

public final static String IDP_ID_COOKIE_NAME = "IDP_ID_COOKIE_NAME";

private final String mailBaseUrl;
private final Map<Integer, String> loaLevels;
private final boolean secureCookie;

public LoginController(@Value("${mailBaseUrl}") String mailBaseUrl,
@Value("${loa_values_supported}") String loaLevels) {
@Value("${loa_values_supported}") String loaLevels,
@Value("${server.servlet.session.cookie.secure}") boolean secureCookie) {
this.mailBaseUrl = mailBaseUrl;
this.loaLevels = Arrays.stream(loaLevels.replaceAll("\"", "").split(","))
.map(String::trim)
.collect(Collectors.toMap(level -> Integer.valueOf(level.substring(level.length() - 1)), level -> level));
this.secureCookie = secureCookie;
}

@RequestMapping(value = "/startSSO")
Expand All @@ -49,8 +58,23 @@ public void start(HttpServletRequest request,
@RequestParam("redirect_url") String redirectUrl,
@RequestParam(value = "loa", required = false) Integer loa)
throws IOException, ServletException {
//Need to remember the switched IdP, we will check if the IdP is allowed on login again
CoinUser currentUser = SpringSecurity.getCurrentUser();
Optional<IdentityProvider> switchedToIdp = currentUser.getSwitchedToIdp();
switchedToIdp.ifPresentOrElse(idp -> {
Cookie cookie = new Cookie(IDP_ID_COOKIE_NAME, idp.getId());
cookie.setSecure(secureCookie);
cookie.setHttpOnly(true);
response.addCookie(cookie);
}, () -> {
Cookie cookie = new Cookie(IDP_ID_COOKIE_NAME, "");
cookie.setSecure(secureCookie);
cookie.setMaxAge(0);
cookie.setHttpOnly(true);
response.addCookie(cookie);
});
SecurityContextHolder.clearContext();
request.logout();

//We could do this client side, but one extra redirect is not a problem
String target = "/startSSO?redirect_url=" + redirectUrl;
String shibbolethLogin = String.format("/Shibboleth.sso/Login?target=%s%s",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public IdentityProvider(String id, String institutionId, String name, Long eid)

public IdentityProvider(Map<String, Object> metaData) {
super(metaData);
this.institutionId = (String) metaData.get("coin:institution_id");
this.institutionId = (String) metaData.get("coin:institution_guid");
this.disableConsent = (List<Consent>) metaData.getOrDefault("disableConsent", new ArrayList<>());
addKeywords("en", (String) metaData.get("keywords:en"));
addKeywords("nl", (String) metaData.get("keywords:nl"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public ServiceProvider(Map<String, Object> metaData) {
super(metaData);
this.dashboardConnectOption = DashboardConnectOption.fromOption((String) metaData.getOrDefault("coin:dashboard_connect_option", "connect_with_interaction"));
this.applicationUrl = (String) metaData.get("coin:application_url");
this.institutionId = (String) metaData.get("coin:institution_id");
this.institutionId = (String) metaData.get("coin:institution_guid");
this.eulaURL = (String) metaData.get("coin:eula");
this.interfedSource = (String) metaData.getOrDefault("coin:interfed_source", "SURFconext");
this.privacyStatementUrlEn = (String) metaData.get("mdui:PrivacyStatementURL:en");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class UrlResourceManage implements Manage {
private final String body = "{" + requestedAttributes + "}";
private final String bodyForEntity = "{\"entityid\":\"@@entityid@@\", " + requestedAttributes + "}";
private final String bodyForInstitutionId =
"{\"metaDataFields.coin:institution_id\":\"@@institution_id@@\", \"ALL_ATTRIBUTES\":true}";
"{\"metaDataFields.coin:institution_guid\":\"@@institution_id@@\", \"ALL_ATTRIBUTES\":true}";

private final String linkedQuery = "{$and: [{$or:[{\"data.allowedEntities.name\": {$in: [\"@@entityid@@\"]}}, {\"data" +
".allowedall\": true}]}]}";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.stream.Stream;

import static com.google.common.base.Preconditions.checkState;
import static dashboard.control.LoginController.IDP_ID_COOKIE_NAME;
import static dashboard.domain.CoinAuthority.Authority.*;
import static dashboard.shibboleth.ShibbolethHeader.*;
import static java.util.Collections.singletonList;
Expand Down Expand Up @@ -150,7 +152,6 @@ protected Object getPreAuthenticatedPrincipal(final HttpServletRequest request)
String idpId = authorityOptional.orElseThrow(() -> new IllegalArgumentException(String.format("Missing %s Shibboleth header (%s)",
Shib_Authenticating_Authority.getValue(), request.getRequestURL())));


CoinUser coinUser = new CoinUser();
coinUser.setUid(uid);
coinUser.setDisplayName(getFirstShibHeaderValue(Shib_DisplayName, request).orElse(null));
Expand Down Expand Up @@ -181,6 +182,16 @@ protected Object getPreAuthenticatedPrincipal(final HttpServletRequest request)
coinUser.setIdp(getCurrentIdp(idpId, institutionIdentityProviders));
coinUser.getInstitutionIdps().addAll(institutionIdentityProviders);
Collections.sort(coinUser.getInstitutionIdps(), Comparator.comparing(Provider::getName));
Cookie[] cookies = request.getCookies();
if (cookies != null) {
Stream.of(cookies).filter(cookie -> IDP_ID_COOKIE_NAME.equals(cookie.getName()))
.findAny()
.ifPresent(cookie -> {
IdentityProvider switchedToIdp = institutionIdentityProviders.stream()
.filter(idp -> idp.getId().equals(cookie.getValue())).findAny().orElse(null);
coinUser.setSwitchedToIdp(switchedToIdp);
});
}
}

Optional<SabRoleHolder> roles = sab.getRoles(uid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ public class MockShibbolethFilter extends GenericFilterBean {
public static final String idp = "http://mock-idp";//,"https://idp.surfnet.nl";//"https://localhost.surf.id"; //"https://idp.surf.nl"
public final String authnContextClass = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password";
// public final String authnContextClass = "http://test2.surfconext.nl/assurance/loa2";
// public String role = "admin";
public String role = "super";
public String role = "admin";
// public String role = "super";

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse response, FilterChain chain) throws IOException,
Expand Down Expand Up @@ -57,7 +57,8 @@ public void doFilter(ServletRequest servletRequest, ServletResponse response, Fi
wrapper.setHeader(Shib_EduPersonScopedAffiliation.getValue(),
"urn:mace:terena.org:tcs:eduPersonScopedAffiliation");
wrapper.setHeader(Shib_SURFEckid.getValue(), "some surf eckid value");
wrapper.setHeader(HTTP_X_IDP_ENTITY_ID, idp);
String entityIdHeader = request.getHeader(HTTP_X_IDP_ENTITY_ID);
wrapper.setHeader(HTTP_X_IDP_ENTITY_ID, StringUtils.hasText(entityIdHeader) ? entityIdHeader : idp);
wrapper.setHeader(Shib_AuthnContext_Class.getValue(), authnContextClass);

switch (role) {
Expand Down
2 changes: 1 addition & 1 deletion dashboard-server/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ static.baseurl=http://localhost:8280/

# 8 hours
server.servlet.session.timeout=28800

server.servlet.session.cookie.secure=false
manage.username=dashboard
manage.password=secret
manage.manageBaseUrl=https://manage.test2.surfconext.nl
Expand Down

0 comments on commit 06181b5

Please sign in to comment.