lundi 25 juillet 2022

Replacing Multiple If statements to reduce cognitive complexity

So I have a go application that is trying to authorize the user using two mechanisms:

  1. CSP (in which the app-key (ak) request header must be present in the request)
  2. OAuth (i will use the azp claim to set the name of service)

So I have to do the name-spacing in my service on the basis of type of authorization the user has used (User is free to choose any one of them).

So there is a design issue which I am not able to resolve:

func setServiceName(appKeys, oAuthUserMap map[string]string, logger log.Logger) func(inner http.Handler) http.Handler {
    return func(inner http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
            
            ak := req.Header.Get("ak")

            claims, _ := req.Context().Value(oauth.JWTContextKey("claims")).(jwt.MapClaims)
            
            authClaim, errorMessage, keyMap, middlewareError := checkAuthType(ak, claims, appKeys, oAuthUserMap)

            if authClaim == "" || authClaim == "<nil>" {
                // return error for "Invalid Authorization" as none of the request header is present
            }

            if val, ok := keyMap[authClaim]; ok {
                // if value is not empty, then there must be a mapping existing between authClaim and service name
                
                // serve the request
                
            }

            // return error according to the type of authorization used i.e. Invalid APP KEY in case of CSP or Invalid Credentials in case of Oauth
        })
    }
}


// this function checks the type of authorization used and returns the paramters respectively
func checkAuthType(ak string, claims jwt.MapClaims, appKeys, oAuthUserMap map[string]string) (authClaim,
    errorMessage string, keyMap map[string]string, middlewareError error) {
    
    if ak != "" {
        keyMap = appKeys
        errorMessage = "Invalid APP KEY provided"
        middlewareError = // i will return a custom error here
        authClaim = ak
    }

    azp := claims["azp"]
    oauthClaim := fmt.Sprint(azp)

    if oauthClaim != "<nil>" {
        keyMap = oAuthUserMap
        errorMessage = "Invalid Credentials"
        middlewareError = // i will return a custom error here
        authClaim = oauthClaim
    }

    return authClaim, errorMessage, keyMap, middlewareError
}

Things to keep in mind while seeing the code:

  1. This setServiceName is a middleware that i will be using in my application
  1. I have to return different errors on basis of type of authorization mechanism used
  1. The appKeys and oAuthUserMap are two maps that i will populate on the basis of environment variables set in configs and i have to use appKeys map for name-spacing in case of CSP and the later in case of OAuth
  1. authClaim will help me in finding the value from the key in map that will be used for namespacing

Problems I am facing:

  1. If I keep all the if statements inside the setServiceName middleware function the cognitive complexity will increase and that's not acceptable
  2. the function checkAuthType is not a very good function as it is performing simple if-else logic that can be shifted inside the middleware function only

Please help me in solving this design issue. The function checkAuthType doesn't seem to be much useful as it contains only if-else logic but at the same time i have to take care of cognitive complexity of setServiceName.

Aucun commentaire:

Enregistrer un commentaire