|
4 | 4 | * ***** |
5 | 5 | * Concord |
6 | 6 | * ----- |
7 | | - * Copyright (C) 2020 Ivan Bodrov |
| 7 | + * Copyright (C) 2017 - 2025 Walmart Inc. |
8 | 8 | * ----- |
9 | 9 | * Licensed under the Apache License, Version 2.0 (the "License"); |
10 | 10 | * you may not use this file except in compliance with the License. |
|
20 | 20 | * ===== |
21 | 21 | */ |
22 | 22 |
|
23 | | -import org.pac4j.core.config.Config; |
24 | | -import org.pac4j.core.context.JEEContext; |
25 | | -import org.pac4j.core.context.session.SessionStore; |
26 | | -import org.pac4j.core.engine.CallbackLogic; |
27 | | -import org.pac4j.core.exception.TechnicalException; |
28 | | -import org.pac4j.core.util.Pac4jConstants; |
29 | 23 | import org.slf4j.Logger; |
30 | 24 | import org.slf4j.LoggerFactory; |
31 | 25 |
|
32 | 26 | import javax.inject.Inject; |
33 | | -import javax.inject.Named; |
34 | | -import javax.servlet.*; |
| 27 | +import javax.servlet.Filter; |
| 28 | +import javax.servlet.FilterChain; |
| 29 | +import javax.servlet.ServletRequest; |
| 30 | +import javax.servlet.ServletResponse; |
35 | 31 | import javax.servlet.http.HttpServletRequest; |
36 | 32 | import javax.servlet.http.HttpServletResponse; |
37 | | -import javax.servlet.http.HttpSession; |
38 | 33 | import java.io.IOException; |
39 | 34 |
|
40 | 35 | public class OidcCallbackFilter implements Filter { |
41 | 36 |
|
42 | 37 | private static final Logger log = LoggerFactory.getLogger(OidcCallbackFilter.class); |
43 | 38 |
|
44 | 39 | public static final String URL = "/api/service/oidc/callback"; |
| 40 | + private static final String SESSION_STATE_KEY = "OIDC_STATE"; |
| 41 | + private static final String SESSION_REDIRECT_KEY = "OIDC_REDIRECT_URL"; |
| 42 | + private static final String SESSION_PROFILE_KEY = "OIDC_USER_PROFILE"; |
45 | 43 |
|
46 | 44 | private final PluginConfiguration cfg; |
47 | | - private final Config pac4jConfig; |
| 45 | + private final OidcService oidcService; |
48 | 46 |
|
49 | 47 | @Inject |
50 | | - public OidcCallbackFilter(PluginConfiguration cfg, |
51 | | - @Named("oidc") Config pac4jConfig) { |
52 | | - |
| 48 | + public OidcCallbackFilter(PluginConfiguration cfg, OidcService oidcService) { |
53 | 49 | this.cfg = cfg; |
54 | | - this.pac4jConfig = pac4jConfig; |
| 50 | + this.oidcService = oidcService; |
55 | 51 | } |
56 | 52 |
|
57 | 53 | @Override |
58 | | - @SuppressWarnings("unchecked") |
59 | 54 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException { |
60 | | - HttpServletRequest req = (HttpServletRequest) request; |
61 | | - HttpServletResponse resp = (HttpServletResponse) response; |
| 55 | + var req = (HttpServletRequest) request; |
| 56 | + var resp = (HttpServletResponse) response; |
62 | 57 |
|
63 | 58 | if (!cfg.isEnabled()) { |
64 | 59 | resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "OIDC disabled"); |
65 | 60 | return; |
66 | 61 | } |
67 | 62 |
|
68 | | - JEEContext context = new JEEContext(req, resp, pac4jConfig.getSessionStore()); |
| 63 | + var session = req.getSession(false); |
| 64 | + if (session == null) { |
| 65 | + resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "No session"); |
| 66 | + return; |
| 67 | + } |
69 | 68 |
|
70 | | - String postLoginUrl = removeRequestedUrl(context); |
| 69 | + var postLoginUrl = (String) session.getAttribute(SESSION_REDIRECT_KEY); |
71 | 70 | if (postLoginUrl == null || postLoginUrl.trim().isEmpty()) { |
72 | 71 | postLoginUrl = cfg.getAfterLoginUrl(); |
73 | 72 | } |
74 | 73 |
|
75 | | - String error = req.getParameter("error"); |
| 74 | + var error = req.getParameter("error"); |
76 | 75 | if (error != null) { |
77 | | - String derivedError = "unknown"; |
| 76 | + var derivedError = "unknown"; |
78 | 77 | if ("access_denied".equals(error)) { |
79 | 78 | derivedError = "oidc_access_denied"; |
80 | 79 | } |
81 | 80 | resp.sendRedirect(resp.encodeRedirectURL(cfg.getOnErrorUrl() + "?from=" + postLoginUrl + "&error=" + derivedError)); |
82 | 81 | return; |
83 | 82 | } |
84 | 83 |
|
85 | | - try { |
86 | | - CallbackLogic<?, JEEContext> callback = pac4jConfig.getCallbackLogic(); |
87 | | - callback.perform(context, pac4jConfig, pac4jConfig.getHttpActionAdapter(), postLoginUrl, true, false, true, OidcPluginModule.CLIENT_NAME); |
88 | | - } catch (TechnicalException e) { |
89 | | - log.warn("OIDC callback error: {}", e.getMessage()); |
90 | | - HttpSession session = req.getSession(false); |
91 | | - if (session != null) { |
92 | | - session.invalidate(); |
93 | | - } |
| 84 | + var code = req.getParameter("code"); |
| 85 | + var state = req.getParameter("state"); |
| 86 | + var expectedState = (String) session.getAttribute(SESSION_STATE_KEY); |
| 87 | + |
| 88 | + if (code == null || state == null || !state.equals(expectedState)) { |
| 89 | + log.warn("Invalid callback parameters: code={}, state={}, expectedState={}", code != null, state, expectedState); |
| 90 | + session.invalidate(); |
94 | 91 | resp.sendRedirect(resp.encodeRedirectURL(OidcAuthFilter.URL + "?from=" + postLoginUrl)); |
| 92 | + return; |
95 | 93 | } |
96 | | - } |
97 | 94 |
|
98 | | - @Override |
99 | | - public void init(FilterConfig filterConfig) { |
100 | | - // do nothing |
101 | | - } |
| 95 | + try { |
| 96 | + var redirectUri = cfg.getUrlBase() + URL + "?client_name=oidc"; |
| 97 | + var profile = oidcService.exchangeCodeForProfile(code, redirectUri); |
102 | 98 |
|
103 | | - @Override |
104 | | - public void destroy() { |
105 | | - // do nothing |
106 | | - } |
| 99 | + session.setAttribute(SESSION_PROFILE_KEY, profile); |
| 100 | + session.removeAttribute(SESSION_STATE_KEY); |
| 101 | + session.removeAttribute(SESSION_REDIRECT_KEY); |
| 102 | + |
| 103 | + resp.sendRedirect(resp.encodeRedirectURL(postLoginUrl)); |
107 | 104 |
|
108 | | - @SuppressWarnings("unchecked") |
109 | | - private static String removeRequestedUrl(JEEContext context) { |
110 | | - SessionStore<JEEContext> sessionStore = context.getSessionStore(); |
111 | | - Object result = sessionStore.get(context, Pac4jConstants.REQUESTED_URL).orElse(null); |
112 | | - sessionStore.set(context, Pac4jConstants.REQUESTED_URL, ""); |
113 | | - if (result instanceof String) { |
114 | | - return (String) result; |
| 105 | + } catch (Exception e) { |
| 106 | + log.warn("OIDC callback error: {}", e.getMessage()); |
| 107 | + session.invalidate(); |
| 108 | + resp.sendRedirect(resp.encodeRedirectURL(OidcAuthFilter.URL + "?from=" + postLoginUrl)); |
115 | 109 | } |
116 | | - return null; |
117 | 110 | } |
118 | 111 | } |
0 commit comments