Coder Social home page Coder Social logo

jwt-opa's People

Contributors

massenz avatar mmassenzio avatar seungykim avatar seunkim-adobe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

jwt-opa's Issues

Automated GH Build/Test fails

The GH Action to build the library fails, it should be fixed.

It is a spurious error:

A problem occurred evaluating project ':jwt-opa'.
> Could not get unknown property 'ossrhUsername' for Credentials [username: null] of type org.gradle.internal.credentials.DefaultPasswordCredentials_Decorated.

it is due to the credentials for Maven Central publish not being (correctly) available in the repository; we need to find a way to prevent the failure during the build/test process.

Route rules should support RegEx/Ant Matchers

Currently the routes configuration does an exact match against the URI path - this should be changed to suppor either RegEx or Ant matchers, so that something like this is possible:

routes:
  authorized:
    - "/users/*/accounts/**"
    - ...

This would also be necessary to support #11

As a Developer I want to add arbitrary data to API Tokens

The format of JWTs created by the JwtTokenProvider class is somewhat inflexible, in that it only allows to specify the username (sub field) and expiresAt (exp field).

There may be situations in which the application may want to carry additional information in the Token, so we should augment the ability to specify those (possibly as a set of {key, value} pairs).

As a User I want to store my secrets in Vault

We need to implement a KeypairLoader and SecretsResolver that supports a Vault store (alongside with the necessary configurations to connect to it, including the secret/permissions).

Add request body content to OPA request

It would often be useful, to evaluate an authorization policy, to inspect the body of the request and make assertions against certain fields' values.

Adding a body element to the OPA request (the relevant code is in the OpaReactiveAuthorizationManager class) is not as straightforward as it would appear.

There are a couple of issues:

  • the size of the request's body contents may be fairly large, multi-part, or even a full binary file upload;
  • converting arbitrary content to JSON in a way that could be evaluated in a Rego policy is not trivial.

While the former problem could be solved naively (just ignore any request whose Content-Length is greater than a given, configurable threshold) and the latter could be left as a "problem for the reader" (in this case, the Rego policy author(s)), we choose here a different approach:

  • we add a body element (object) to the TokenBasedAuthorizationRequest if the ContentType is application/json;
  • we add a body string if ContentType is text/*;
  • we ignore anything else (for now anyway);
  • the ContentType will be added to the headers section (see #36).

Consider adding support for OAuth2 authentication

The design currently assumes that the application will provide user management and authentication (eg, via username/password)
It would be great to have support and direct integration for OAuth2 servers, using Spring Security facilities.

Remove all dependencies JARs from published artifacts

We currently publish "fat" JARs, including all dependencies (most notably Spring Framework).
Quite apart from being bad practice and making the artifacts unnecessarily bloated, this prevents applications that import our JAR to correctly import code/sources and navigate to them in IDEs.

Our published JAR should only contain our code, and there should be clear documentation as to what additional imports are needed (including correct version information).

Create a better demo API app

The webapp-example demo application only brushes the surface of what is possible with jwt-opa and also has a lot of unnecessary "other stuff" that is no longer relevant.

It should be updated with a couple of "interesting" use cases and also to better showcase the usage of jwt-opa; it is also apparent that a number of other supporting activities are necessary to use the library proficiently (eg, configuring the OPA server, designing Rego policies): those should be added too, or at least documented.

Should allow multiple Policy endpoints

We currently have a single opa.policy.rule configuration; this is not flexible enough.
Ideally, API endpoints should be "grouped" under distinct rule endpoints, and such groups be configurable.

This could be done in the routes.authorized configuration, by grouping the routes under OPA authorization control in "groups" and each point having a distinct opa.policy.rule configuration:

opa:
  policy: kapsules/rules

routes:
  ...
  authorized:
    users:
       rule: "users-auth"
       endpoints:
         - /users/**
         - /users/*/accounts
     orders:
       rule: "orders"
       endpoints:
         - /orders/**
         - /users/*/orders/**
         - ...

When user is authenticated via password (BASIC) we should still try and validate the API Token

If a user is already authenticated (typically, it has entered the password in a browser window) we get this error:

2022-01-20 22:04:38.686 ERROR 29783 --- [oundedElastic-3] c.a.o.s.OpaReactiveAuthorizationManager  : Unexpected user not authenticated, or Authentication type (UsernamePasswordAuthenticationToken) not an instance of ApiTokenAuthentication, cannot progress authorization

(this happens while using the OpenAPI documentation pages, for example)

We should still try and authorize the request, if the API Token is present.

Should be discussed whether to generate a fresh JWT if the auth is valid.

Allow for different sources of KeyPair

Currently KeyMaterialConfiguration assumes that keypair property must be non-null and it has two attributes (priv and pub) which point to respective key material files.

We should allow for different configurations (e.g., a secret-name from AWS Secrets Manager, or Hashicorp Vault) to be used to specify how to retrieve the key material.

Add the ability to arbitrarily set the expiry of a token

Currently JwtProvider configures the expires_at at a set time based on the expires_after_sec configuration value.
We should add the ability to either not expiring the token, or to set an arbitrary expiration time (or duration)

Add audit logs

There should be a boolean configuration option (something like logging.audits.enabled).
When enabled, each request should be logged with sufficient detail so that requests, users, and outcomes can be logged and stored for future audits.

At a minimum, we should log (in JSON format) the request body sent to OPA, the policy endpoint being queried, and the outcome (result) from the OPA server.

The JWT API token should be "unwrapped" to report (at a minimum) the user making the request, their roles and the token expiration date.

Add request Headers to OPA authorization request

We currently only send the path and method to OPA for authorization (alongside the JWT); we should also send "relevant" (as defined by the user) headers.

This could be a mix of "well-known" as well as "custom" headers:

opa:
  headers:
    - x-org-id
    - x-user-def
    - ContentType

If any (or all) of the headers are missing in the API call, they are simply ignored and the authorization is sent to OPA: auth policies will decide if those are required and access ought to be denied if missing.

The headers will be sent in the OPA request as key-value pairs (we assume single-valued headers):

      {
        "input": {
            "api_token": ".... API Token Base-64 encoded ...",
            "resource": {
                "method": "POST",
                "path": "/path/to/resource",
                "headers": [
                  { "name": "x-org-id", "value": "123456"},
                  { "name": "ContentType", "value": "application/json"},
                  ...
                ]
           }
        }
      }

and will be available as an array of objects in the Rego policy at input.resource.headers, and each header will be accessible as, for example input.resource.headers["x-org-id"].

Specify how to handle KeyPair in Configurations

Currently the KeypairReader is implemented by a file reader and an AWS (Secrets Manager) reader.
While the implementation is reasonably straightforward, the configuration of the client(s) (via a @Configuration class) is "left to the implementer" - which is not a desirable state of affairs.

Also, there is some cruft left over from moving the key configuration out of the tokens configuration - so that needs cleaning up too.

The challenge is how to define both @Properties and @Configuration classes (and the associated structure of the YAML properties) without constraining too much what can be added later on (and also without making the Bean instantiation too cumbersome).

This task is partly designing the above, as well as a "reference implementation", including providing documentation and examples.

Need better logs when auth request fails

Even at DEBUG level for com.alertavert when the auth fails we don't get good logging to figure out what went wrong during development/testing.

We recently tested and the JWT was expired, but it was not clear at all that that was the issue.

Fix Deprecation Warnings

Upgrading to the most recent Spring version, raises a number of deprecation warnings:

> Task :jwt-opa:compileJava
/home/marco/Development/jwt-opa/jwt-opa/src/main/java/com/alertavert/opa/configuration/JwtSecurityConfiguration.java:65: warning: [removal] csrf() in ServerHttpSecurity has been deprecated and marked for removal
        .csrf().disable()
        ^
/home/marco/Development/jwt-opa/jwt-opa/src/main/java/com/alertavert/opa/configuration/JwtSecurityConfiguration.java:73: warning: [removal] httpBasic() in ServerHttpSecurity has been deprecated and marked for removal
        .httpBasic()
        ^
/home/marco/Development/jwt-opa/jwt-opa/src/main/java/com/alertavert/opa/configuration/JwtSecurityConfiguration.java:74: warning: [removal] and() in ServerHttpSecurity.HttpBasicSpec has been deprecated and marked for removal
        .and()
        ^
/home/marco/Development/jwt-opa/jwt-opa/src/main/java/com/alertavert/opa/configuration/JwtSecurityConfiguration.java:76: warning: [removal] authorizeExchange() in ServerHttpSecurity has been deprecated and marked for removal
        .authorizeExchange()
        ^
/home/marco/Development/jwt-opa/jwt-opa/src/main/java/com/alertavert/opa/configuration/JwtSecurityConfiguration.java:81: warning: [removal] and() in ServerHttpSecurity.AuthorizeExchangeSpec has been deprecated and marked for removal
        .and()
        ^
/home/marco/Development/jwt-opa/jwt-opa/src/main/java/com/alertavert/opa/security/OpaReactiveAuthorizationManager.java:160: warning: [removal] getMethodValue() in HttpRequest has been deprecated and marked for removal
                    request.getMethodValue(),
                           ^
6 warnings

This must be fixed.

Enable authentication via "Reference" Tokens

Using an UUID (e.g, an ObjectId) that references an actual JWT (Token) stored in a service's DB (for example)
Similarly to UserDetails we could define an interface TokenDetails which, when implemented as a Bean returns a JWT (if it exists) when requested by UUID.

This would allow use cases around rotating and revoking tokens.

Allow injection of Private/Public key pair

This library currently assumes the keypair to be stored in the filesystem, while in reality, keys may be obtained instead from, e.g., secure vaults (such as Hashicorp Vault or AWS Secrets Manager).

We should allow for the ability for the users of the library to provide the keypair in ways other than filesystem storage.

Add more flexibility on the `endpoint` in the OPA request

We currently build the OPA request path following the static definition in the opa property:

# This is used to build the Rule validation endpoint:
#   http://localhost:8181/v1/data/com/alertavert/policies/allow
#
opa:
  policy: com.alertavert.policies
  rule: allow
  server: "localhost:8181"

and this is used for all API calls, regardless of the request path (see the OpaReactiveAuthorizationManager class).

It should be possible to define a "matching pattern" between URL path and OPA Rule to evaluate policies more flexibly; something like:

opa:
  server: ...
  policies:
    - path_glob: "/users/**"
      policy: com.alertavert.users
      rule: allow
    - path_glob: "/orders/*/status"
      policy: com.alertavert.orders
      rule: inspect
    - path_glob: "*"
      policy: com.alertavert.policies
      rule: allow

Paths' globs are "ant patterns" similarly to what is being used in the routes configuration (see the JwtSecurityConfiguration class)

Enable service-to-service Tokens

We currently only generate Tokens upon validating credentials (typically, username/password).
We should augment the functionality for this library users to generate "Refresh Tokens," which have a much longer validity (eg., weeks or even months) but cannot be used for API authorization, only to obtain new API Tokens.

This would be useful when enabling services/bot to access APIs via JWTs, but not wanting to have to acquire a new token every time on expires by submitting credentials.

Service A trying to access Service B would then try to authenticate with a Token, and in case it receives a 401 (or a 403) they could try and refresh their token, and try again the request (assuming they successfully authenticate and obtain a valid new token).

Support for JDK17

Open JDK 17 has now been out for several months, and it is a LTS release; we should adopt it fully and then make it the default supported JDK release.

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.