Code Monkey home page Code Monkey logo

Comments (18)

afs avatar afs commented on June 1, 2024

Does RegistryRequestModifier, used by HttpLib.modifyByService work for you? It can add the header.
https://jena.apache.org/documentation/sparql-apis/#customization-of-http-requests

4.5.0 has been built and is currently awaiting the VOTE from the PMC.
The build uses the Apache release configuration of the maven release plugin. If the version moves on,

from jena.

Aklakan avatar Aklakan commented on June 1, 2024

Hi Andy, thanks alot - the snippet below works:

   String bearerToken = "SECRET";
   HttpRequestModifier modifier = (params, headers) -> {
       headers.put("Authorization", "Bearer " + bearerToken);
   };
   RegistryRequestModifier.get().add(url, modifier);

However, there is a minor follow up issue:
If the bearer token times out, then first a message is logged such as:

Bearer error="invalid_token", error_description="An error occurred while attempting to decode the Jwt: Jwt expired at 2022-05-03T20:22:50Z", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"

but then it causes a non-ideal NPE in AuthLib.authenticateHeader:

public class AuthLib {
    private static AuthChallenge authenticateHeader(HttpResponse<?> httpResponse) {
        List<String> headers = httpResponse.headers().allValues("WWW-Authenticate");
        if ( headers.size() == 0 )
            return null;
        // Choose first digest or first basic.
        AuthChallenge aHeader = null;
        String result = null;
        for ( String headerValue : headers ) {
            AuthChallenge aHeader2 = AuthChallenge.parse(headerValue);
            if ( aHeader2 == null )
                AuthEnv.LOG.warn("Bad authentication response - ignored: "+headerValue);
            // Prefer Digest
            switch(aHeader2.authScheme) { // BUG: If aHeader2 is null we get a NPE here
                case  DIGEST :
                    return aHeader2;
                case BASIC:
/* .. */

from jena.

afs avatar afs commented on June 1, 2024

That would have happened if an AuthModifier were used.

It needs AuthScheme extending and AuthChallenge.parse etc changing. Then there needs to be a recovery or more likely, passing on up the 401.

What else needs to accommodate that?

from jena.

afs avatar afs commented on June 1, 2024

Some context so we can build or simulate test cases:

  • What software system are you calling?
  • What WWW-Authentication header do you get back?

from jena.

Aklakan avatar Aklakan commented on June 1, 2024

The software is a commercial product from @eccenca called corporate memory (cmem) which is a knowledge graph platform - which means it combines sparql enpdoint, workflow engine, interlinking, vocabulary management, user management, etc + user interfaces. It also uses Apache Jena in the backend.

So far I haven't used auth much, therefore I am not very familiar with the issues that arise with latest Jena and how to best address them - but maybe @seebi and his team (from eccenca) have already done some deeper investigation with tasks/issues on their backlog.

curl -I on the currently private cmem instance yields:

HTTP/2 401 
server: nginx/1.21.6
date: Tue, 03 May 2022 21:32:52 GMT
vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers
www-authenticate: Bearer

from jena.

seebi avatar seebi commented on June 1, 2024

HI together, this is our architecture.

The sparql endpoint is a resource server in an oauth2 zone used together with keycloak.

You could do something similar e.g. with oauth2 proxy ...

from jena.

afs avatar afs commented on June 1, 2024

Could you test for other things that might be needed by avoiding the NPE so the system returns without NPE?

It really would be helpful to get all the points enumerated where "bearer" matters and not deal with them one by one.

from jena.

afs avatar afs commented on June 1, 2024

The new title is a bit broad. What is the scope? Just handling "Authorization: Bearer"? There isn't a general way to process a 401 because obtaining the token involves both local context and scheme-specific choices as well as timeouts.

On the Fuseki side, I'm adding a servlet filter for handling "Authorization: Bearer" (for the day job) for JWT. A fuseki module is probably the way to go because the token needs handling per-bearer scheme and local auth services.

from jena.

Aklakan avatar Aklakan commented on June 1, 2024

I've been working with oauth in the past days and IMHO just handling Authorization: Bearer should be enough.

I managed to use spring security to authenticate with my local test app that I registered with my gitlab account .

Because obtaining the bearer token is 'app-driven' I'd say its an application's concern to pass on the bearer token to components such as Jena remote sparql requests. It may make sense having a global callback registry in Jena for getting notified about failed authentications so that an application can then take action, such as redirecting the user to repeat the auth process.

from jena.

afs avatar afs commented on June 1, 2024

The application sees a failed authentication as an exception 401.

Fixes and improvements in #1301. HTTP authentication is a bit squirly because of legacy cases.

Adding challenge handling for bearer auth is probably doable but it's yet another step. Rather than delay everything PR #1301 at least fixes the original problems and should work when the bearer token is added - failure is a 401 exception.

One case is that the token is being passed along a path service requests and code in the 401 handler may find it hard to give transparent. PR #1301 at least fixes the original problems and should work when the bearer token is added.

@seebi -- I'm guessing that in your architecture, the token is added before the original request and not based on a HTTP challenge. Is that correct?

Testing the PR would be great - this is quite sensitive to the execution environment (and my reading of the RFCs!).

from jena.

seebi avatar seebi commented on June 1, 2024

@seebi -- I'm guessing that in your architecture, the token is added before the original request and not based on a HTTP challenge. Is that correct?

correct, the token is fetched from a different component (e.g. keycloak) and then added to all requests.

from jena.

seebi avatar seebi commented on June 1, 2024

@Aklakan Do you need help in testing this?

from jena.

afs avatar afs commented on June 1, 2024

The current PR needs the bearer token provided.

@seebi sounds like our setup - we don't involve 401, the token is known to be needed and is always added.

from jena.

seebi avatar seebi commented on June 1, 2024

mhmm .. In our case requests without a token return a 401

∴ curl -H "Authorization: Bearer $(cmemc admin token)" "$(cmemc config get DP_API_ENDPOINT)/proxy/default/sparql"
{"title":"Bad Request","status":400,"detail":"Required request parameter 'query' for method parameter type String is not present"}

∴ curl  "$(cmemc config get DP_API_ENDPOINT)/proxy/default/sparql"
{"title":"Unauthorized","status":401,"detail":"Full authentication is required to access this resource"}

from jena.

afs avatar afs commented on June 1, 2024

As it stand currently, the PR will not crash (NPE) in the Jena client-side code for SPARQL operations when encountering bearer auth. Challenges for basic and digest are handled internally with registered user-password (no change there). Bearer auth is different because the app needs to get the token and tokens may have a limited lifetime.

This PR is the necessary part : #1292 (comment)

Adding challenge handling for bearer auth is probably doable but it's yet another step. Rather than delay everything PR #1301 at least fixes the original problems and should work when the bearer token is added - failure is a 401 exception.

The first one is a 400 due to the lack of ?query=. Presumably authentication should have been done before request parsing and so did happen.

The second is 401 and the calling code should either have added the token (@Aklakan current solution) or caught the 401 and retried with a token added. There is no Jena there that I can see.

The best Jena client-library can do is have a registry of callbacks so 401 causes a call out to app code to provide the token (see the current AuthRequestModifier which can add HTTP headers based on target URI @Aklakan has been using). Something to do carefully to avoid security leaks in multi-tenant situations.

from jena.

afs avatar afs commented on June 1, 2024

#1335 provides code to handle a 401 challenge for bearer tokens. It calls back into the application to get a token.

from jena.

Aklakan avatar Aklakan commented on June 1, 2024

So I can confirm that the solution from more than an hour ago seems satisfactory to me - using an invalid token or none at all against a bearer-token-protected endpoint resulted in 401 rather than NPE:

Caused by: org.apache.jena.atlas.web.HttpException: 401 - Unauthorized
	at org.apache.jena.http.HttpLib.exception(HttpLib.java:231)
	at org.apache.jena.http.HttpLib.handleHttpStatusCode(HttpLib.java:161)

Andy just added a new PR like 30min ago which I haven't tried yet.

from jena.

afs avatar afs commented on June 1, 2024

Thanks.

The new commit adds some helper support (AuthEnv.setBearerToken, AuthEnv.setBearerTokenProvider) for ahead-of-time setting the token and challenge response handling.

The test suite covers requests with ahead of time registration of a token and with responses to a 401 challenge.

Almost everything to do with bearer auth involves application supplied code to access the deployment environment.

from jena.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.