Repository navigation
Unilogin error #189
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
Unilogin error #189
Changes from all commits
7e1c218
900d080
1fb9261
ec163ba
d0fabd4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,8 +2,6 @@ | |
| *.iml | ||
| out/ | ||
|
|
||
| WSDL | ||
| resources/wsdl/ | ||
| dk/acto/auth/generated/ | ||
|
|
||
| # Gradle | ||
|
|
||
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,114 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package dk.acto.fafnir.sso.provider.unilogin; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import jakarta.servlet.http.HttpSession; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.extern.slf4j.Slf4j; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.Collections; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.Map; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.stream.Collectors; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Slf4j | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public final class UniLoginFlowTrace { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public static final String TRACE_UNIID_SESSION_KEY = "trace_uniid"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public enum Branch { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| intro_failed, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| userinfo_ok, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| userinfo_empty, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| soap_fallback, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dedup_applied, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| error_no_institutions, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| direct_jwt, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| direct_jwt_no_org, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| org_picker, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| org_empty_list, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| org_render, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| org_post, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jwt_built, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jwt_cached, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logout_redirect, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logout_complete_no_token, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logout_complete_cache_miss, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logout_complete_success | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private UniLoginFlowTrace() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public static void log(String step, Branch branch, String uniid, HttpSession session, Map<String, Object> extra) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| StringBuilder message = new StringBuilder("UniLogin trace: step=") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .append(step) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .append(" branch=") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .append(branch) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .append(" uniid=") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .append(uniid != null ? uniid : "-") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .append(" session=") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .append(sessionId(session)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (session != null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Object aktoerGruppe = session.getAttribute("aktoer_gruppe"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (aktoerGruppe != null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| message.append(" aktoer_gruppe=").append(aktoerGruppe); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (extra != null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (Map.Entry<String, Object> entry : extra.entrySet()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| message.append(' ').append(entry.getKey()).append('=').append(entry.getValue()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info(message.toString()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+40
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Sanitize/redact identity fields before writing to the trace log.
Consider stripping/escaping control characters and truncating/pseudonymizing 🔒 Suggested sanitization public static void log(String step, Branch branch, String uniid, HttpSession session, Map<String, Object> extra) {
+ String safeUniid = sanitize(uniid);
StringBuilder message = new StringBuilder("UniLogin trace: step=")
.append(step)
.append(" branch=")
.append(branch)
.append(" uniid=")
- .append(uniid != null ? uniid : "-")
+ .append(safeUniid)
.append(" session=")
.append(sessionId(session));
if (session != null) {
Object aktoerGruppe = session.getAttribute("aktoer_gruppe");
if (aktoerGruppe != null) {
- message.append(" aktoer_gruppe=").append(aktoerGruppe);
+ message.append(" aktoer_gruppe=").append(sanitize(aktoerGruppe.toString()));
}
}
if (extra != null) {
for (Map.Entry<String, Object> entry : extra.entrySet()) {
- message.append(' ').append(entry.getKey()).append('=').append(entry.getValue());
+ message.append(' ').append(entry.getKey()).append('=')
+ .append(sanitize(String.valueOf(entry.getValue())));
}
}
log.info(message.toString());
}
+
+ private static String sanitize(String value) {
+ if (value == null) {
+ return "-";
+ }
+ return value.replaceAll("[\\r\\n]", "_");
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public static String sessionId(HttpSession session) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (session == null || session.getId() == null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return "-"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String id = session.getId(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return id.length() <= 8 ? id : id.substring(0, 8); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public static boolean hasUserInfoInSession(HttpSession session) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (session == null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UserInfoResponse userInfo = (UserInfoResponse) session.getAttribute("userInfo"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return userInfo != null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| && userInfo.getInstBrugere() != null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| && !userInfo.getInstBrugere().isEmpty(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public static List<String> instnrList(List<Institution> institutions) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (institutions == null || institutions.isEmpty()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Collections.emptyList(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return institutions.stream() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map(inst -> inst.id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .filter(id -> id != null && !id.isBlank()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .collect(Collectors.toList()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public static String tokenPrefix(String token) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (token == null || token.isEmpty()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return "-"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return token.substring(0, Math.min(8, token.length())); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public static void rememberUniid(HttpSession session, String uniid) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (session != null && uniid != null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| session.setAttribute(TRACE_UNIID_SESSION_KEY, uniid); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public static String uniidFromSession(HttpSession session) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (session == null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Object value = session.getAttribute(TRACE_UNIID_SESSION_KEY); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return value != null ? value.toString() : null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |||||||||||||||||||||||||||||||||||||
| import dk.acto.fafnir.api.model.FailureReason; | ||||||||||||||||||||||||||||||||||||||
| import dk.acto.fafnir.api.model.conf.FafnirConf; | ||||||||||||||||||||||||||||||||||||||
| import dk.acto.fafnir.sso.provider.UniLoginProvider; | ||||||||||||||||||||||||||||||||||||||
| import dk.acto.fafnir.sso.provider.unilogin.UniLoginFlowTrace; | ||||||||||||||||||||||||||||||||||||||
| import dk.acto.fafnir.sso.provider.unilogin.UniloginTokenCredentials; | ||||||||||||||||||||||||||||||||||||||
| import io.vavr.control.Try; | ||||||||||||||||||||||||||||||||||||||
| import jakarta.annotation.PostConstruct; | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -20,6 +21,7 @@ | |||||||||||||||||||||||||||||||||||||
| import java.io.IOException; | ||||||||||||||||||||||||||||||||||||||
| import java.security.NoSuchAlgorithmException; | ||||||||||||||||||||||||||||||||||||||
| import java.util.Collections; | ||||||||||||||||||||||||||||||||||||||
| import java.util.Map; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| @Controller | ||||||||||||||||||||||||||||||||||||||
| @Slf4j | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -69,11 +71,27 @@ public String getOrg(@RequestParam String user, Model model, HttpServletResponse | |||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (institutionList.isEmpty()) { | ||||||||||||||||||||||||||||||||||||||
| if (provider.canIssueJwtWithoutInstitution(session)) { | ||||||||||||||||||||||||||||||||||||||
| log.info("No institutions for employee user {}, issuing JWT without org", user); | ||||||||||||||||||||||||||||||||||||||
| UniLoginFlowTrace.log("getOrg", UniLoginFlowTrace.Branch.direct_jwt_no_org, user, session, Map.of( | ||||||||||||||||||||||||||||||||||||||
| "inst_count", 0, | ||||||||||||||||||||||||||||||||||||||
| "session_has_userInfo", UniLoginFlowTrace.hasUserInfoInSession(session))); | ||||||||||||||||||||||||||||||||||||||
| AuthenticationResult result = provider.callbackWithoutInstitution(user, session); | ||||||||||||||||||||||||||||||||||||||
| response.sendRedirect(result.getUrl(uniloginConf)); | ||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| log.warn("No institutions found for user: {}, redirecting to failure URL", user); | ||||||||||||||||||||||||||||||||||||||
| UniLoginFlowTrace.log("getOrg", UniLoginFlowTrace.Branch.org_empty_list, user, session, Map.of( | ||||||||||||||||||||||||||||||||||||||
| "inst_count", 0, | ||||||||||||||||||||||||||||||||||||||
| "session_has_userInfo", UniLoginFlowTrace.hasUserInfoInSession(session))); | ||||||||||||||||||||||||||||||||||||||
| response.sendRedirect(provider.getFailureUrl(FailureReason.CONNECTION_FAILED)); | ||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||
| log.info("Adding {} institution(s) to model for template rendering", institutionList.size()); | ||||||||||||||||||||||||||||||||||||||
| UniLoginFlowTrace.log("getOrg", UniLoginFlowTrace.Branch.org_render, user, session, Map.of( | ||||||||||||||||||||||||||||||||||||||
| "inst_count", institutionList.size(), | ||||||||||||||||||||||||||||||||||||||
| "session_has_userInfo", UniLoginFlowTrace.hasUserInfoInSession(session), | ||||||||||||||||||||||||||||||||||||||
| "instnr_list", UniLoginFlowTrace.instnrList(institutionList))); | ||||||||||||||||||||||||||||||||||||||
| model.addAttribute("user", user); | ||||||||||||||||||||||||||||||||||||||
| model.addAttribute("institutionList", institutionList); | ||||||||||||||||||||||||||||||||||||||
| log.info("Model attributes set - user: {}, institutionList size: {}", user, institutionList.size()); | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -86,6 +104,8 @@ public String getOrg(@RequestParam String user, Model model, HttpServletResponse | |||||||||||||||||||||||||||||||||||||
| @ResponseBody | ||||||||||||||||||||||||||||||||||||||
| public RedirectView postOrg(@RequestParam String user, @RequestParam String institution, | ||||||||||||||||||||||||||||||||||||||
| HttpSession session, HttpServletResponse response) { | ||||||||||||||||||||||||||||||||||||||
| UniLoginFlowTrace.log("org_post", UniLoginFlowTrace.Branch.org_post, user, session, | ||||||||||||||||||||||||||||||||||||||
| Map.of("institution", institution)); | ||||||||||||||||||||||||||||||||||||||
| AuthenticationResult result = provider.callbackWithInstitution(user, institution, null, session); | ||||||||||||||||||||||||||||||||||||||
| String redirectUrl = result.getUrl(uniloginConf); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
@@ -97,7 +117,8 @@ public RedirectView postOrg(@RequestParam String user, @RequestParam String inst | |||||||||||||||||||||||||||||||||||||
| cookie.setPath("/"); | ||||||||||||||||||||||||||||||||||||||
| cookie.setMaxAge(300); // 5 minutes | ||||||||||||||||||||||||||||||||||||||
| cookie.setHttpOnly(true); | ||||||||||||||||||||||||||||||||||||||
| cookie.setSecure(true); // Use secure cookies in production | ||||||||||||||||||||||||||||||||||||||
| String fafnirUrl = System.getenv("FAFNIR_URL"); | ||||||||||||||||||||||||||||||||||||||
| cookie.setSecure(fafnirUrl != null && fafnirUrl.startsWith("https://")); | ||||||||||||||||||||||||||||||||||||||
| response.addCookie(cookie); | ||||||||||||||||||||||||||||||||||||||
| log.debug("Set logout token cookie as backup"); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -117,40 +138,52 @@ public RedirectView postOrg(@RequestParam String user, @RequestParam String inst | |||||||||||||||||||||||||||||||||||||
| @GetMapping("logout-complete") | ||||||||||||||||||||||||||||||||||||||
| public RedirectView logoutComplete(HttpSession session, jakarta.servlet.http.HttpServletRequest request) { | ||||||||||||||||||||||||||||||||||||||
| log.info("Logout complete callback - retrieving JWT from cache"); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| String uniid = UniLoginFlowTrace.uniidFromSession(session); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Try to get token from session first | ||||||||||||||||||||||||||||||||||||||
| String token = session != null ? (String) session.getAttribute("logout_token") : null; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| String tokenSource = token != null && !token.isEmpty() ? "session" : null; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Fallback to cookie if session doesn't have it | ||||||||||||||||||||||||||||||||||||||
| if ((token == null || token.isEmpty()) && request.getCookies() != null) { | ||||||||||||||||||||||||||||||||||||||
| for (jakarta.servlet.http.Cookie cookie : request.getCookies()) { | ||||||||||||||||||||||||||||||||||||||
| if ("fafnir_logout_token".equals(cookie.getName())) { | ||||||||||||||||||||||||||||||||||||||
| token = cookie.getValue(); | ||||||||||||||||||||||||||||||||||||||
| tokenSource = "cookie"; | ||||||||||||||||||||||||||||||||||||||
| log.debug("Retrieved logout token from cookie"); | ||||||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (token == null || token.isEmpty()) { | ||||||||||||||||||||||||||||||||||||||
| log.warn("No logout token found in session or cookie after logout, redirecting to failure"); | ||||||||||||||||||||||||||||||||||||||
| UniLoginFlowTrace.log("logout_complete", UniLoginFlowTrace.Branch.logout_complete_no_token, | ||||||||||||||||||||||||||||||||||||||
| uniid, session, Map.of("token_source", "none")); | ||||||||||||||||||||||||||||||||||||||
| return new RedirectView(uniloginConf.getFailureRedirect() + "#" + dk.acto.fafnir.api.model.FailureReason.AUTHENTICATION_FAILED.getErrorCode()); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Clear the token from session and cookie | ||||||||||||||||||||||||||||||||||||||
| if (session != null) { | ||||||||||||||||||||||||||||||||||||||
| session.removeAttribute("logout_token"); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Retrieve the JWT from cache using one-time token | ||||||||||||||||||||||||||||||||||||||
| String jwt = provider.retrieveJwtFromCache(token); | ||||||||||||||||||||||||||||||||||||||
| String jwt = provider.retrieveJwtFromCache(token, uniid, session); | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
166
to
+172
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Cookie is not cleared despite the comment. The comment states the token is cleared "from session and cookie", but only ✏️ Minimal fix: align the comment with actual behavior- // Clear the token from session and cookie
+ // Clear the token from session (the one-time token is also removed from cache below,
+ // so the backup cookie becomes inert even though it is not explicitly expired here)
if (session != null) {
session.removeAttribute("logout_token");
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (jwt != null && !jwt.isEmpty()) { | ||||||||||||||||||||||||||||||||||||||
| log.debug("JWT retrieved from cache, redirecting to success page"); | ||||||||||||||||||||||||||||||||||||||
| // Redirect to success page with JWT in hash | ||||||||||||||||||||||||||||||||||||||
| log.info("JWT retrieved from cache, redirecting to success page"); | ||||||||||||||||||||||||||||||||||||||
| UniLoginFlowTrace.log("logout_complete", UniLoginFlowTrace.Branch.logout_complete_success, | ||||||||||||||||||||||||||||||||||||||
| uniid, session, Map.of( | ||||||||||||||||||||||||||||||||||||||
| "token_source", tokenSource != null ? tokenSource : "unknown", | ||||||||||||||||||||||||||||||||||||||
| "cache_token_prefix", UniLoginFlowTrace.tokenPrefix(token))); | ||||||||||||||||||||||||||||||||||||||
| return new RedirectView(uniloginConf.getSuccessRedirect() + "#" + jwt); | ||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||
| log.warn("No valid JWT found in cache after logout (token may be expired or invalid), redirecting to failure"); | ||||||||||||||||||||||||||||||||||||||
| UniLoginFlowTrace.log("logout_complete", UniLoginFlowTrace.Branch.logout_complete_cache_miss, | ||||||||||||||||||||||||||||||||||||||
| uniid, session, Map.of( | ||||||||||||||||||||||||||||||||||||||
| "token_source", tokenSource != null ? tokenSource : "unknown", | ||||||||||||||||||||||||||||||||||||||
| "cache_token_prefix", UniLoginFlowTrace.tokenPrefix(token))); | ||||||||||||||||||||||||||||||||||||||
| return new RedirectView(uniloginConf.getFailureRedirect() + "#" + dk.acto.fafnir.api.model.FailureReason.AUTHENTICATION_FAILED.getErrorCode()); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
genWsiInstis missing adownloadXsdSchemaCommondependency.wsiinst-schema.xsdimportscommon/schema-common.xsddirectly, andwsiinst_v5.wsdltransitively needs it viacommon/ws-common.xsd's include.genWsiBrugercorrectly depends ondownloadXsdSchemaCommon(Line 150) for the equivalent transitive need, butgenWsiInstdoes not. If this task runs standalone before the checked-in XSD is present (e.g. after deleting generated resources), Wsdl2Java code generation would fail on an unresolvedcommon/schema-common.xsdimport.🛠️ Proposed fix
dependsOn(tasks.getByName("downloadWSDLWsiInst")) dependsOn(tasks.getByName("downloadXsdWsCommon")) + dependsOn(tasks.getByName("downloadXsdSchemaCommon")) dependsOn(tasks.getByName("downloadXsdWsiInst")) dependsOn(tasks.getByName("downloadXsdWsiinstSchema")) }📝 Committable suggestion
🤖 Prompt for AI Agents