CERIT-SC / funnel-gdi

MIT License
1 stars 3 forks source link

OIDC/OAuth2 authentication support #3

Closed mrtamm closed 7 months ago

mrtamm commented 8 months ago

Added support for performing JWT-based user authentication (#2). The service API just validates that the provided Bearer token is issued by the configured OIDC service, the token is valid (calls introspection endpoint), and optionally can also check for specific values in audience (aud) and scope (scope) claims.

Note that the authentication just permits the request but does not associate the executed task with that specific user.

To verify that the token has not been invalidated before expiring, Funnel server also calls the introspection_endpoint defined in the OIDC configuration JSON (unless it's missing from there). For this call, ClientId and ClientSecret (specified in the YAML configuration file) are also sent in Basic authentication format (unless the client information is not defined in the configuration file).

The command-line client picks the JWT value from environment variable: FUNNEL_SERVER_BEARER. However, when there are also Basic credentials defined in the environment variables, these will be preferred over JWT.

Basic authentication is still supported. Note that RPC service (provided at port 9090) goes through the same authentication validation steps. Therefore, enabled OIDC-based authentication without Basic authentication credentials is problematic, since the server's RPC client would also need a JWT. To overcome this obstacle, the server automatically generates and adds Basic authentication credentials (see: cmd/util/config.go), which will be used with the RPC client. In addition, now the configuration loader also checks that RPC client configuration also has credentials defined (in the file) when at least one Basic credential is defined.

Other minor comments:

  1. used github.com/lestrrat-go/jwx library for parsing JWT and loading JWK keys: the good part of this library is that it provides a cache for storing JWK keys and refreshing them periodically after 15 minutes.
  2. added problem logging using fmt.Print for rare scenarios. Not sure if this is the best practice in this project, at least there are something to rely on for debugging.
  3. added website documentation page for OAuth2 authentication, demonstrating how to configure.

Feel free to comment, change, or make recommendations.

mrtamm commented 8 months ago

I updated the PR description to include the fact that now the OIDC introspection_endpoint is also called on validated tokens to make sure the token has not been invalidated before expiring.

mrtamm commented 7 months ago

I updated authentication test TestBasicAuthFail() in tests/auth/auth_test.go. I noticed that my code changed the status code from 403 (PermissionDenied) to 401 (Unauthenticated) when user does not provide credentials in the request. Although it's a minor API change, I find it more correct than the 403 status.

I also reviewed linter errors, and fixed one linter issue in my changes.