13

We have developed a REST API using the resteasy. (deployed in wildfly 10)

Basically these REST APIs are called internally from another application and end points are secured with keycloak.

But one endpoint is exposed to outside party (that endpoint is also secured with keycloak).

But since the outside party can't provide the Keycloak Autherization code, we have done an implementation where client is registerred with application generated auth_key and client will call the endpoint with that auth_key.

Then in the a web filter (a javax.servlet.Filter), using tha auth_key we get the relevant keycloak authntication Bearer token. If needed (eg : token expired) we call the Keycloak Server also. Once it is received we add that Autherization token to the httpRequest within the web filter and proceed to the end point application.

But the problem is, KeyCloak authentication is called before Web Filter. What I'm looking for is "how to get Web Filter called before keycloak authentication?"

EDIT :

Now I'm trying to find a way as mentioned in here. Setting Request Header to Request Before Authentication Happens in Keycloak. There I could get the call before authentication happens. But I'm unable to set the Request Header there.

web.xml

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    <display-name>Restful Web Application</display-name>
    <context-param>
        <param-name>resteasy.scan</param-name>
        <param-value>true</param-value>
    </context-param>

    <!-- keycloak -->

    <context-param>
        <param-name>keycloak.config.resolver</param-name>
        <param-value>package.to.HeaderBasedKeycloakConfigResolver</param-value>
    </context-param>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>REST endpoints</web-resource-name>
            <url-pattern>/ep-name/resource-name</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>resource-name</role-name>
        </auth-constraint>
    </security-constraint>

    <!-- more security-constraint -->
    <!-- more security-constraint -->
    <!-- more security-constraint -->

    <login-config>
        <auth-method>KEYCLOAK</auth-method>
        <realm-name>realm-name</realm-name>
    </login-config>

    <security-role>
        <role-name>role-name-for-resource-1</role-name>
        <role-name>role-name-for-resource-2</role-name>
        <!-- more security-role -->
        <!-- more security-role -->
        <!-- more security-role -->
    </security-role>

    <listener>
        <listener-class>
            org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
    </listener>

    <servlet>
        <servlet-name>resteasy-servlet</servlet-name>
        <servlet-class>
            org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
        </servlet-class>
        <init-param>
            <param-name>resteasy.servlet.mapping.prefix</param-name>
            <param-value>/ep-name</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>resteasy-servlet</servlet-name>
        <url-pattern>/ep-name/*</url-pattern>
    </servlet-mapping>

    <filter>
      <filter-name>WebFilter</filter-name>
      <filter-class>package.to.filter.WebFilter</filter-class>
   </filter>

   <filter-mapping>
      <filter-name>WebFilter</filter-name>
      <url-pattern>/desired-ep-name/*</url-pattern>
   </filter-mapping>

</web-app>

enter image description here

ironwood
  • 8,936
  • 15
  • 65
  • 114
  • did you find a solution to your problem? – tryingToLearn Sep 27 '18 at 10:29
  • Still I didn't find a response. I managed it another way. But now I'm trying to find a way as mentioned in here. https://stackoverflow.com/questions/52551723/setting-request-header-to-request-before-authentication-happens-in-keycloak There I could get the call before authentication happens. But I'm unable to set the Request Header. – ironwood Sep 28 '18 at 08:57
  • For a nice solution see https://arjan-tijms.omnifaces.org/2012/12/bridging-undertows-authentication.html works for undertow only, but it illustrates the idea quite nicely – leonardkraemer Oct 12 '20 at 13:03

3 Answers3

6

Have you tried to change the order of the elements in the web.xml (eg put filter definitions BEFORE servlet definitions) ?

Not sure it will works, but the doc says: "The order of the filters in the chain is the same as the order that filter mappings appear in the web application deployment descriptor"

The principle may be also true for the order between servlets and filters...

TacheDeChoco
  • 3,683
  • 1
  • 14
  • 17
  • Thanx for the answer @TacheDeChoco. But it doesn't work. – ironwood Jul 23 '18 at 12:41
  • Accepts since it is helpful although not the correct solution for my problem – ironwood Aug 07 '18 at 05:46
  • @namalfernandolk did you find the solution to your problem? In comments above you mentioned that this solution did not work – tryingToLearn Sep 27 '18 at 10:29
  • 1
    @tryingToLearn : Yes still I didn't find a response. I managed it another way. But now I'm trying to find a way as mentioned in here. https://stackoverflow.com/questions/52551723/setting-request-header-to-request-before-authentication-happens-in-keycloak. There I could get the call before authentication happens. But I'm unable to set the Request Header. – ironwood Sep 28 '18 at 08:56
4

It may be because Tomcat Authentication Valve kick in before Filters. Check Authenticators.properties file. You may need to wrap your filter class as Valve

Adrian0
  • 51
  • 3
1

I know this is 2 years old, but I found a solutuon for this problem: Change your adapter to the servlet filter, mine was jboss/wildfly, and add to web.xml below your filter to change the request or response. In the case of jboss/wildfly, the authentication happens in a valve, so the authentication happens before any filters execute. Once you do this, you can control when keycloak does its work and put your filter before it.

web.xml

<filter>
        <filter-name>Keycloak Filter</filter-name>
        <filter-class>org.keycloak.adapters.servlet.KeycloakOIDCFilter</filter-class>
</filter>
    <filter-mapping>
        <filter-name>Keycloak Filter</filter-name>
        <url-pattern>/restricted/*</url-pattern>
        <url-pattern>/restricted/</url-pattern>
</filter-mapping>

Add appropriate version of keycloak-servlet-filter-adapter to your pom, and remove all the other security-constraints, auth-method, etc from web.xml.

Jordan Walsh
  • 1,505
  • 2
  • 9
  • 8