cloudfoundry/cf-k8s-controllers

View on GitHub
api/middleware/authentication.go

Summary

Maintainability
A
0 mins
Test Coverage
package middleware

import (
    "context"
    "net/http"

    "code.cloudfoundry.org/korifi/api/authorization"
    apierrors "code.cloudfoundry.org/korifi/api/errors"
    "code.cloudfoundry.org/korifi/api/routing"

    "github.com/go-logr/logr"
)

//counterfeiter:generate -o fake -fake-name IdentityProvider . IdentityProvider

type IdentityProvider interface {
    GetIdentity(context.Context, authorization.Info) (authorization.Identity, error)
}

//counterfeiter:generate -o fake -fake-name AuthInfoParser . AuthInfoParser

type authentication struct {
    authInfoParser   AuthInfoParser
    identityProvider IdentityProvider
}

type AuthInfoParser interface {
    Parse(authHeader string) (authorization.Info, error)
}

func Authentication(
    authInfoParser AuthInfoParser,
    identityProvider IdentityProvider,
) func(http.Handler) http.Handler {
    return (&authentication{
        authInfoParser:   authInfoParser,
        identityProvider: identityProvider,
    }).middleware
}

func (a *authentication) middleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        logger := logr.FromContextOrDiscard(r.Context()).WithName("authentication-middleware")

        authInfo, err := a.authInfoParser.Parse(r.Header.Get("Authorization"))
        if err != nil {
            logger.Info("failed to parse auth info", "reason", err)
            routing.PresentError(logger, w, err)
            return
        }

        r = r.WithContext(authorization.NewContext(r.Context(), &authInfo))

        _, err = a.identityProvider.GetIdentity(r.Context(), authInfo)
        if err != nil {
            routing.PresentError(logger, w, apierrors.LogAndReturn(logger, err, "failed to get identity"))
            return
        }

        next.ServeHTTP(w, r)
    })
}