couper icon indicating copy to clipboard operation
couper copied to clipboard

couper-examples test configuration edge failing

Open johakoch opened this issue 1 year ago • 3 comments

See https://github.com/coupergateway/couper-examples/actions/workflows/test.yaml

This results from oidcConfig.GetIssuer() (creating a sync request for the OIDC configuration) now (after https://github.com/coupergateway/couper/pull/796) being in the path for couper verify:

  • Verify.Execute()
  • runtime.NewServerConfiguration()
  • configureAccessControls()
  • oauth2.NewOidcClient()
  • oidcConfig.GetIssuer()

Another minor issue:

  issuer, err := oidcConfig.GetIssuer()
  if err != nil {
    return nil, errors.Oauth2.With(err)
                ^^^^^^^^^^^^^^^^^^^^^^^

If we keep the JWT parser being created in NewOidcClient(), err should not be wrapped here, as errors.Oauth2 is for runtime errors.

johakoch avatar Feb 19 '24 10:02 johakoch

@malud Would it be safe to ignore backend errors with couper verify?

johakoch avatar Mar 06 '24 13:03 johakoch

We could skip the "oidc" example directory for the usual verification and do a

docker-compose up --abort-on-container-exit

instead.

That would require creating different docker-compose.yaml files for the two image-tags to be checked.

johakoch avatar Apr 19 '24 17:04 johakoch

A way to solve this in couper itself: lazy-initialize the JWT parser for OIDC:

func NewOidcClient(evalCtx *hcl.EvalContext, oidcConfig *oidc.Config) (*OidcClient, error) {
	backends := oidcConfig.Backends()
	acClient, err := NewAuthCodeClient(evalCtx, oidcConfig, oidcConfig, backends["token_backend"])
	if err != nil {
		return nil, err
	}

	o := &OidcClient{
		AuthCodeClient: acClient,
		backends:       backends,
		config:         oidcConfig,
		// don't create JWT parser here
	}

// ...

func (o *OidcClient) getJwtParser() (*jwt.Parser, error) {
	if o.jwtParser == nil {
		issuer, err := o.config.GetIssuer()
		if err != nil {
			return nil, err
		}
		options := []jwt.ParserOption{
// ...
		}
		o.jwtParser = jwt.NewParser(options...)
	}
	return o.jwtParser, nil
}

// ...

func (o *OidcClient) validateTokenResponseData(ctx context.Context, tokenResponseData map[string]interface{}, hashedVerifierValue, verifierValue, accessToken string) error {
	idTokenString, ok := tokenResponseData["id_token"].(string)
	if !ok {
		return errors.Oauth2.Message("missing id_token in token response")
	}

	jwtParser, err := o.getJwtParser()
	if err != nil {
		return err
	}

	idTokenClaims := jwt.MapClaims{}
	_, err = jwtParser.ParseWithClaims(idTokenString, idTokenClaims, o.keyfunc)
// ...

johakoch avatar Apr 20 '24 09:04 johakoch