|
28 | 28 | import javax.servlet.http.HttpServletRequest; |
29 | 29 | import javax.servlet.http.HttpServletResponse; |
30 | 30 |
|
| 31 | +import org.keycloak.adapters.OIDCAuthenticationError; |
31 | 32 | import org.springframework.http.HttpStatus; |
32 | 33 | import org.springframework.http.ResponseEntity; |
33 | 34 | import org.springframework.security.authentication.AccountStatusException; |
|
39 | 40 |
|
40 | 41 | import eu.openanalytics.containerproxy.api.BaseController; |
41 | 42 |
|
| 43 | +import static eu.openanalytics.containerproxy.auth.impl.keycloak.AuthenticationFaillureHandler.SP_KEYCLOAK_ERROR_REASON; |
| 44 | + |
42 | 45 | @Controller |
43 | 46 | @RequestMapping("/error") |
44 | 47 | public class ErrorController extends BaseController implements org.springframework.boot.web.servlet.error.ErrorController { |
45 | | - |
| 48 | + |
46 | 49 | @RequestMapping(produces = "text/html") |
47 | 50 | public String handleError(ModelMap map, HttpServletRequest request, HttpServletResponse response) { |
| 51 | + |
| 52 | + // handle keycloak errors |
| 53 | + Object obj = request.getSession().getAttribute(SP_KEYCLOAK_ERROR_REASON); |
| 54 | + if (obj instanceof OIDCAuthenticationError.Reason) { |
| 55 | + request.getSession().removeAttribute(SP_KEYCLOAK_ERROR_REASON); |
| 56 | + OIDCAuthenticationError.Reason reason = (OIDCAuthenticationError.Reason) obj; |
| 57 | + if (reason == OIDCAuthenticationError.Reason.INVALID_STATE_COOKIE || |
| 58 | + reason == OIDCAuthenticationError.Reason.STALE_TOKEN) { |
| 59 | + // These errors are typically caused by users using wrong bookmarks (e.g. bookmarks with states in) |
| 60 | + // or when some cookies got stale. However, the user is logged into the IDP, therefore it's enough to |
| 61 | + // send the user to the main page and they will get logged in automatically. |
| 62 | + return "redirect:/"; |
| 63 | + } else { |
| 64 | + return "redirect:/auth-error"; |
| 65 | + } |
| 66 | + } |
| 67 | + |
48 | 68 | Throwable exception = (Throwable) request.getAttribute("javax.servlet.error.exception"); |
49 | | - if (exception == null) exception = (Throwable) request.getAttribute("SPRING_SECURITY_LAST_EXCEPTION"); |
| 69 | + if (exception == null) { |
| 70 | + exception = (Throwable) request.getAttribute("SPRING_SECURITY_LAST_EXCEPTION"); |
| 71 | + } |
50 | 72 |
|
51 | 73 | String[] msg = createMsgStack(exception); |
52 | | - if (exception == null) msg[0] = HttpStatus.valueOf(response.getStatus()).getReasonPhrase(); |
| 74 | + if (exception == null) { |
| 75 | + msg[0] = HttpStatus.valueOf(response.getStatus()).getReasonPhrase(); |
| 76 | + } |
53 | 77 |
|
54 | | - if (response.getStatus() == 200 && isAccountStatusException(exception)) { |
55 | | - return "/"; |
| 78 | + if (response.getStatus() == 200 && (exception != null) && isAccountStatusException(exception)) { |
| 79 | + return "redirect:/"; |
56 | 80 | } |
57 | 81 |
|
58 | 82 | map.put("message", msg[0]); |
@@ -102,7 +126,7 @@ private String[] createMsgStack(Throwable exception) { |
102 | 126 |
|
103 | 127 | return new String[] { message, stackTrace }; |
104 | 128 | } |
105 | | - |
| 129 | + |
106 | 130 | private boolean isAccountStatusException(Throwable exception) { |
107 | 131 | if (exception instanceof AccountStatusException) return true; |
108 | 132 | if (exception.getCause() != null) return isAccountStatusException(exception.getCause()); |
|
0 commit comments