On a local Wildfly server I have a simple Java servlet like below:
import javax.servlet.annotation.HttpMethodConstraint;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.http.HttpServlet;
@ServletSecurity(httpMethodConstraints = { @HttpMethodConstraint(value = "GET", rolesAllowed = { "debug" })})
public class DebugServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try ( PrintWriter out = response.getWriter()) {
/* TODO output your page here. You may use following sample code. */
...
Principal user = request.getUserPrincipal();
out.println("<p>" + (user != null ? user.getName() : "No user") + "</p>");
...
}
}
}
I have set up authentication with Wildfly's Elytron v1.17.2 using OpenID Connect (OIDC) with a third party authentication server. If it matters, it is not a Keycloak server, and changing the auth server isn't an option; using this auth server is a strict business requirement. The auth server has a bunch of users which we want to give access to, but for my particular client_id none of the users have any roles associated with them, and we want to avoid adding roles through the auth server because the process is...tedious at best. Bureaucratic red tape, every time, for every user. Our end goal is to have our own roles in this server's database and we're only going to the 3rd party to handle the login and then verify the login is valid and which user it is.
If I include rolesAllowed = { "debug" }
in the HttpMethodConstraint, authentication with the 3rd-party auth server gets triggered and works correctly. But because none of the users have roles associated with them, they don't have the required "debug" role. The processRequest
method is never reached and the user gets a "Forbidden" error page.
If I remove or empty the rolesAllowed
field of the constraint, authentication with the 3rd-party auth server is not triggered, and there's no UserPrincipal
which we can use to identify the user.
I've tried putting a javax.servlet.Filter
in to intercept the request before it gets to my Servlet, but if the "debug" role is required then the filter doesn't get reached either. I had hoped to intercept the request after the user authenticates and then add roles to the user, or a session variable, or something which my servlet would then check for permission to do various actions.
I've tried a few other combinations which have not triggered authentication:
@ServletSecurity(httpMethodConstraints = { @HttpMethodConstraint(value = "GET", emptyRoleSemantic = ServletSecurity.EmptyRoleSemantic.PERMIT)})
and
@ServletSecurity(httpMethodConstraints = { @HttpMethodConstraint(value = "GET", transportGuarantee = ServletSecurity.TransportGuarantee.CONFIDENTIAL)})
No luck.
Is there a way I can trigger 3rd-party authentication, and get a UserPrincipal with the authenticated user's username/user id, without requiring a specific role? -OR- Is there a way I can add roles to the authenticated user after authenticating but before being blocked by the HttpMethodConstraint?
The reason your custom filter approach will not work is because the elytron security framework handles this well before your filter chain is invoked. You might try custom role mapper within elytron security as explained here (Section 3.2.9) and here to add some predefined roles.
RoleMapper - After the roles have been decoded for an identity further mapping can be applied, this could be as simple at normalising the format of the names through to adding or removing specific role names.
You would obviously need to configure the elytron subsystem to use your custom role mapper. You can take a look at an example configuration for regex-role-mapper here ( in your case you need a custom RoleMapper instead of regex-role-mapper)