Joaquín Reñé
2026-03-27 4ee50e257b32f6ec0f72907305d1f2b1212808a4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
 * Copyright @ 2013 CurisTEC, S.A.S. All Rights Reserved.
 */
package net.curisit.securis;
import java.io.IOException;
import java.security.Principal;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* AuthFilter
* <p>
* Simple authentication/role wrapper for development and lightweight scenarios.
* If a request parameter <code>user</code> or a session attribute <code>user</code>
* is present, this filter wraps the current request with a custom {@link Principal}
* and an ad-hoc role. The role assignment is temporary and follows the rule:
* <ul>
* <li>user == "advance" → role "advance"</li>
* <li>otherwise → role "normal"</li>
* </ul>
* If no user is present, the request continues unmodified.
*
* <p><b>Security note:</b> This filter trusts a user name coming from a request parameter,
* which must not be used in production. Replace with a proper authentication mechanism
* (e.g., JWT, container security, SSO) and derive roles from authoritative claims.
*
* @author JRA
* Last reviewed by JRA on Oct 6, 2025.
*/
@ApplicationScoped
@WebFilter(urlPatterns = "/*")
public class AuthFilter implements Filter {
    private static final Logger LOG = LogManager.getLogger(AuthFilter.class);
    // ---------------------------------------------------------------------
    // Lifecycle
    // ---------------------------------------------------------------------
    
    /** 
     * init<p>
     * Filter initialization hook (unused). 
     */
    @Override
    public void init(FilterConfig fc) throws ServletException {
    }
    // ---------------------------------------------------------------------
    // Filtering
    // ---------------------------------------------------------------------
    /**
     * doFilter
     * <p>
     * If a user is detected (request param or session attribute), wrap the request to:
     * <ul>
     * <li>Expose a {@link Principal} with the provided username.</li>
     * <li>Report a single role through {@link HttpServletRequest#isUserInRole(String)}.</li>
     * </ul>
     * Otherwise, pass-through.
     *
     * @param sr incoming request
     * @param sr1 outgoing response
     * @param fc filter chain
     */
    @Override
    public void doFilter(ServletRequest sr, ServletResponse sr1, FilterChain fc) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) sr;
        if (sr.getParameter("user") != null || req.getSession().getAttribute("user") != null) {
            String username = sr.getParameter("user");
            if (username == null) {
                username = (String) req.getSession().getAttribute("user");
            }
            // Role management is temporal
            String role = "advance".equals(username) ? "advance" : "normal";
            LOG.info("Role for user: {} = {}", username, role);
            fc.doFilter(new UserRoleRequestWrapper(role, sr.getParameter("user"), req), sr1);
        } else {
            fc.doFilter(req, sr1);
        }
    }
    /** 
     * destroy<p>
     * Filter destruction hook (unused). 
     */
    @Override
    public void destroy() {
    }
     // ---------------------------------------------------------------------
     // Wrapper
     // ---------------------------------------------------------------------
     /**
      * UserRoleRequestWrapper
      * <p>
      * Wrapper that overrides role checks and the user principal when a synthetic user is present.
      */
    private class UserRoleRequestWrapper extends HttpServletRequestWrapper {
        private String role;
        private String user;
        /**
        * Constructor
        * <p>
        * @param role single role to expose via {@link #isUserInRole(String)}
        * @param user user name to expose via {@link #getUserPrincipal()}
        * @param request original request to wrap
        */
        public UserRoleRequestWrapper(String role, String user, HttpServletRequest request) {
            super(request);
            this.role = role;
            this.user = user;
        }
        /**
        * isUserInRole
        * <p>
        * Returns {@code true} if the requested role equals the configured synthetic role.
        */
        @Override
        public boolean isUserInRole(String role) {
            LOG.info("isUserRole METHOD: {}, {}", role, this.role);
            if (this.role == null) {
                return super.isUserInRole(role);
            }
            return this.role.equals(role);
        }
        /**
        * getUserPrincipal
        * <p>
        * Returns a minimal {@link Principal} with the configured user name; delegates otherwise.
        */
        @Override
        public Principal getUserPrincipal() {
            if (this.user == null) {
                return super.getUserPrincipal();
            }
            return new Principal() {
                @Override
                public String getName() {
                    return user;
                }
            };
        }
    }
}