Skip to content

pac4j-module: Can't apply a client directly to a POST route? #1972

Closed

Description

@GrandPoohBear

I am using the pac4j module to do JWT authentication on my API routes. I currently have a POST endpoint that is at a concrete route (/auth/register), and I want to add a pac4j client to that route:

        install(
            Pac4jModule()
                .client("/auth/register") { conf ->
                    DirectBearerAuthClient(get() as JwtAuthenticator) // (using koin to inject JwtAuthenticator)
                }
  ...

... but I have found that the endpoint doesn't actually authenticate credentials unless it's a GET instead of a POST. In debugging, I found this line:
https://github.com/jooby-project/jooby/blob/2.x/modules/jooby-pac4j/src/main/java/io/jooby/pac4j/Pac4jModule.java#L363

It looks to me that unless there are variables (or maybe wildcards?) in the path, the pac4j module assumes that it's a GET path.

It's entirely possible that I'm doing it wrong! Should I only apply the pac4j client to a larger path with a wildcard? Is there a trick to making it work? Am I doing something stupid without realizing it? :-P Any pointers appreciated!

Activity

  1. GrandPoohBear commented on Sep 4, 2020

    @GrandPoohBear
    Author
    /** For each client to a specific path, add a security handler. */
        for (Map.Entry<String, List<Client>> entry : allClients.entrySet()) {
          String pattern = entry.getKey();
          if (!pattern.equals("*")) {
            List<String> keys = Router.pathKeys(pattern);
            if (keys.size() == 0) {
              application.get(pattern, new SecurityFilterImpl(null, pac4j, options, entry.getValue(),
                  clientMap.get(pattern).authorizers));
            } else {
              application.decorator(new SecurityFilterImpl(pattern, pac4j, options, entry.getValue(),
                  clientMap.get(pattern).authorizers));
            }
          }
        }
    

    ... specifically the line that starts with application.get ... I'm sure there's a better way to quote things in this system!

  2. inzagher commented on Sep 7, 2020

    @inzagher

    Hi! I think, that solution can be found in DirectBearerAuthClient source code. As we can see below it uses BearerAuthExtractor to retreave credentials.

    @Override
    protected void clientInit() {
        assertNotBlank("realmName", this.realmName);
    
        defaultCredentialsExtractor(new BearerAuthExtractor());
    }
    

    BearerAuthExtractor has two constructors and delegates all work to HeaderExtractor:

    public class BearerAuthExtractor implements CredentialsExtractor<TokenCredentials> {
    
        private final HeaderExtractor extractor;
    
        public BearerAuthExtractor() {
            this(HttpConstants.AUTHORIZATION_HEADER, HttpConstants.BEARER_HEADER_PREFIX);
        }
    
        public BearerAuthExtractor(final String headerName, final String prefixHeader) {
            this.extractor = new HeaderExtractor(headerName, prefixHeader);
        }
    
        @Override
        public Optional<TokenCredentials> extract(WebContext context) {
            return this.extractor.extract(context);
        }
    }
    

    No matter is it GET or POST, extractor tries to get token with prefix from Header param.
    String AUTHORIZATION_HEADER = "Authorization";
    String BEARER_HEADER_PREFIX = "Bearer ";

    You should try to add Header param named "Authorization" with value "Bearer %some_jwt_token%". Hope it can help.

  3. inzagher commented on Sep 7, 2020

    @inzagher

    Another way is to store JWT in cookies. In my case it looks like this:

    private Client createJwtApiSecurityClient(com.typesafe.config.Config config) {
        RSASignatureConfiguration signatureConfiguration = new RSASignatureConfiguration(jwtKeyPair);
        return new CookieClient(ServerConstants.JWT_SESSION_COOKIE, new JwtAuthenticator(signatureConfiguration));
    }
    

    You can use HeaderClient:
    new HeaderClient(HEADER_NAME, PREFIX_HEADER, new JwtAuthenticator());

    DirectBearerAuthClient is not best solution for API JWT validation because it can redirect to default page after credentials check.

  4. added this to the 2.9.1 milestone on Sep 28, 2020
  5. added a commit that references this issue on Sep 28, 2020
    bffa22a
  6. added a commit that references this issue on Sep 28, 2020
    0960d75
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions