jwt support, using seperate descriptor attributes(success) for jwt and apikey
diff --git a/adapter/apigeeKeyAttributes.go b/adapter/apigeeKeyAttributes.go
index 5c5047c..8cc3c5b 100644
--- a/adapter/apigeeKeyAttributes.go
+++ b/adapter/apigeeKeyAttributes.go
@@ -22,20 +22,23 @@
 	"strings"
 	"github.com/apid/istioApigeeAdapter/adapter/config"
 	"istio.io/mixer/pkg/adapter"
+	"github.com/apid/istioApigeeAdapter/common"
 )
 
 const (
 	keyAttrsName = "apigeeKeyAttributes"
 	keyAttrsDesc = "Set attributes based on an Apigee API key"
 
-	keyParam           = "apiKey"
-	jwtParam	   = "jwtToken"
-	pathParam          = "requestPath"
-	successParam       = "success"
-	successStringParam = "successString"
-	clientIDParam      = "clientID"
-	appNameParam       = "applicationName"
-	productNameParam   = "apiProduct"
+	keyParam           	 = "apiKey"
+	jwtParam	   	 = "jwtToken"
+	pathParam          	 = "requestPath"
+	apiKeySuccessParam       = "apiKeySuccess"
+	apiKeySuccessStringParam = "apiKeySuccessString"
+	jwtSuccessParam       	 = "jwtSuccess"
+	jwtSuccessStringParam 	 = "jwtSuccessString"
+	clientIDParam      	 = "clientID"
+	appNameParam       	 = "applicationName"
+	productNameParam   	 = "apiProduct"
 )
 
 var keyAttrsConf = &config.VerifyKeyParams{}
@@ -81,13 +84,15 @@
 func (g *keyAttrsGenerator) Generate(in map[string]interface{}) (map[string]interface{}, error) {
 
 	out := make(map[string]interface{})
-	out[successParam] = false
-	out[successStringParam] = "false"
+	out[apiKeySuccessParam] = false
+	out[apiKeySuccessStringParam] = "false"
+	out[jwtSuccessParam] = false
+	out[jwtSuccessStringParam] = "false"
 
-	key := getString(in, keyParam)
+	apiKey := getString(in, keyParam)
 	jwt_token := getString(in, jwtParam)
 
-	if key == "" && jwt_token == "" {
+	if apiKey == "" && jwt_token == "" {
 		return out, nil
 	}
 
@@ -97,63 +102,70 @@
 	}
 
 	if jwt_token != "" {
+		// TODO: throw appropriate error to user eg. token expired, token invalid
+
 		if strings.HasPrefix(jwt_token, "Bearer") {
 			token := strings.Split(jwt_token, " ")[1]
 			jwt_token = token
 		} else {
 			g.env.Logger().Errorf("Cannot verify jwt token, Bearer missing")
-			return out, nil
 		}
 
-		claims, err := g.jwtVerifier.Verify(jwt_token)
-
-		if err != nil {
-			g.env.Logger().Errorf("Cannot verify jwt token : %s", err)
-			return out, nil
-		}
-
+		claims, verificationErr := g.jwtVerifier.Verify(jwt_token)
 		// considers token as valid if exp, iat, iss is not present
-		err = claims.Valid()
 
-		// invalid token
-		if err != nil {
-			g.env.Logger().Errorf("jwt token invalid : %s", err)
-			return out, nil
+		if verificationErr != nil {
+			g.env.Logger().Errorf("Cannot verify jwt token : %s", verificationErr)
+		} else {
+			validationErr := claims.Valid()
+
+			if validationErr != nil {
+				g.env.Logger().Errorf("Validation error, jwt token : %s", validationErr)
+			} else {
+				// TODO: check scopes
+
+				key := claims.(*apigeeClaims).ClientId
+				success, app, products, err := g.checkKey(key)
+
+				g.env.Logger().Errorf("Key check failed : %s", err)
+
+				out[jwtSuccessParam] = success
+				out[jwtSuccessStringParam] = strconv.FormatBool(success)
+
+				if app.valid {
+					out[clientIDParam] = app.clientID
+					out[appNameParam] = app.name
+				}
+
+				if success {
+					out[productNameParam] = products[0].Name
+				}
+			}
+		}
+	}
+
+	if apiKey != "" {
+		success, app, products, err := g.checkKey(apiKey)
+
+		g.env.Logger().Errorf("key check failed : %s", err)
+
+		if len(products) == 0 {
+			success = false
 		}
 
-		// TODO: check scopes
+		// TODO match API products by path
 
-		// prioritizing jwt over apikey (if user passes both jwt and apikey)
-		key = claims.(*apigeeClaims).ClientId
-	}
+		out[apiKeySuccessParam] = success
+		out[apiKeySuccessStringParam] = strconv.FormatBool(success)
 
-	// Look up API key from cache, making HTTP request if necessary
-	app, err := g.applications.get(key)
-	if err != nil {
-		g.env.Logger().Errorf("Error verifying API key: %s", err)
-		return nil, err
-	}
+		if app.valid {
+			out[clientIDParam] = app.clientID
+			out[appNameParam] = app.name
+		}
 
-	success := app.valid
-
-	// Look up API products from cache, making HTTP request if necessary
-	products, err := g.products.getProducts(app.apiProducts)
-	if err != nil {
-		return nil, fmt.Errorf("Cannot fetch API product list: %s", err)
-	}
-	if len(products) == 0 {
-		success = false
-	}
-	// TODO match API products by path
-
-	out[successParam] = success
-	out[successStringParam] = strconv.FormatBool(success)
-	if app.valid {
-		out[clientIDParam] = app.clientID
-		out[appNameParam] = app.name
-	}
-	if success {
-		out[productNameParam] = products[0].Name
+		if success {
+			out[productNameParam] = products[0].Name
+		}
 	}
 
 	return out, nil
@@ -163,6 +175,31 @@
 	return nil
 }
 
+func (g *keyAttrsGenerator) checkKey(key string) (bool, *application, []common.APIProduct, error) {
+	// Look up API key from cache, making HTTP request if necessary
+	app, err := g.applications.get(key)
+	if err != nil {
+		g.env.Logger().Errorf("Error verifying API key: %s", err)
+		return false, nil, nil, err
+	}
+
+	success := app.valid
+
+	// Look up API products from cache, making HTTP request if necessary
+	products, err := g.products.getProducts(app.apiProducts)
+	if err != nil {
+		return false, nil, nil, fmt.Errorf("Cannot fetch API product list: %s", err)
+	}
+
+	if len(products) == 0 {
+		success = false
+	}
+
+	// TODO match API products by path
+
+	return success, app, products, err
+}
+
 func getPulicKeyUrl(cfg *config.VerifyKeyParams) (string) {
 	return fmt.Sprintf(defaultPublicKeyURL, cfg.Organization, cfg.Environment)
-}
\ No newline at end of file
+}