Exemple #1
2
// Verify user's JWT.
func checkJWT(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	addCommonJwtRespHeaders(w, r)
	// Look for JWT in both headers and request value "access_token".
	token, err := request.ParseFromRequest(r, TokenExtractor{}, func(token *jwt.Token) (interface{}, error) {
		// Token was signed with RSA method when it was initially granted
		if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
			return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
		}
		return publicKey, nil
	})
	if err != nil || !token.Valid {
		http.Error(w, fmt.Sprintf("{\"error\": \"%s %s\"}", "JWT not valid,", err), http.StatusUnauthorized)
	} else {
		w.WriteHeader(http.StatusOK)
	}
}
Exemple #2
0
// Enable JWT authorization check on the HTTP handler function.
func jwtWrap(originalHandler http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		addCommonJwtRespHeaders(w, r)
		// Look for JWT in both headers and request value "access_token".
		token, err := request.ParseFromRequest(r, TokenExtractor{}, func(token *jwt.Token) (interface{}, error) {
			// Token was signed with RSA method when it was initially granted
			if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
				return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
			}
			return publicKey, nil
		})
		if err != nil || !token.Valid {
			http.Error(w, "", http.StatusUnauthorized)
			return
		}
		tokenClaims := token.Claims.(jwt.MapClaims)
		var url = strings.TrimPrefix(r.URL.Path, "/")
		var col = r.FormValue("col")
		// Call the API endpoint handler if authorization allows
		if tokenClaims[JWT_USER_ATTR] == JWT_USER_ADMIN {
			originalHandler(w, r)
			return
		}
		if !sliceContainsStr(tokenClaims[JWT_ENDPOINTS_ATTR], url) {
			http.Error(w, "", http.StatusUnauthorized)
			return
		} else if col != "" && !sliceContainsStr(tokenClaims[JWT_COLLECTIONS_ATTR], col) {
			http.Error(w, "", http.StatusUnauthorized)
			return
		}
		originalHandler(w, r)
	}
}
Exemple #3
0
// ParseFromRequest parses and validates the input token string in an http.Request. It's a wrapper of jwt.ParseFromRequest().
//
//   Params:
//       r: http.Request may contain jwt token.
//       extractor: Interface for extracting a token from an HTTP request.
//                  See https://godoc.org/github.com/dgrijalva/jwt-go/request#Extractor
//   Return:
//       kid: Key id.
//       claims: map[string]interface{} to fill the jwt.Token[Claims].
//       valid: token is valid or not.
//       err: error.
func ParseFromRequest(r *http.Request, e request.Extractor) (kid string, claims map[string]interface{}, valid bool, err error) {
	t, err := request.ParseFromRequest(r, e, keyFunc)
	if err != nil {
		return "", nil, false, err
	}

	return t.Header["kid"].(string), t.Claims.(jwt.MapClaims), t.Valid, nil
}
Exemple #4
0
// NewJWTHandler parse and validates JWT token if present and store it in the net/context
func NewJWTHandler(users *resource.Resource, jwtKeyFunc jwt.Keyfunc) func(next http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			token, err := request.ParseFromRequest(r, request.OAuth2Extractor, jwtKeyFunc)
			if err == request.ErrNoTokenInRequest {
				// If no token is found, let REST Layer hooks decide if the resource is public or not
				next.ServeHTTP(w, r)
				return
			}
			if err != nil || !token.Valid {
				// Here you may want to return JSON error
				http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
				return
			}
			claims := token.Claims.(jwt.MapClaims)
			userID, ok := claims["user_id"].(string)
			if !ok || userID == "" {
				// The provided token is malformed, user_id claim is missing
				http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
				return
			}
			// Lookup the user by its id
			ctx := r.Context()
			user, err := users.Get(ctx, userID)
			if user != nil && err == resource.ErrUnauthorized {
				// Ignore unauthorized errors set by ourselves (see AuthResourceHook)
				err = nil
			}
			if err != nil {
				// If user resource storage handler returned an error, respond with an error
				if err == resource.ErrNotFound {
					http.Error(w, "Invalid credential", http.StatusForbidden)
				} else {
					http.Error(w, err.Error(), http.StatusInternalServerError)
				}
				return
			}
			// Store it into the request's context
			ctx = NewContextWithUser(ctx, user)
			r = r.WithContext(ctx)
			// If xlog is setup, store the user as logger field
			xlog.FromContext(ctx).SetField("user_id", user.ID)
			next.ServeHTTP(w, r)
		})
	}
}
Exemple #5
0
func (h *jwtHandler) validateToken(req *http.Request) (*processor.TokenInfo, error) {
	start := time.Now()
	token, err := request.ParseFromRequest(req, request.OAuth2Extractor, jwtValidator(h.keyLoader))
	if err != nil {
		log.Println("Failed to validate token: ", err)
		return nil, err
	}

	measureRequest(start, fmt.Sprintf("planb.tokeninfo.jwt.validation.%s", token.Method.Alg()))
	if !token.Valid {
		log.Println("Failed to validate token: ", ErrInvalidJWT)
		return nil, ErrInvalidJWT
	}
	if h.crp.IsJWTRevoked(token) {
		log.Println("Failed to validate token: ", ErrRevokedToken)
		return nil, ErrRevokedToken
	}
	return NewTokenInfo(token, time.Now())
}
Exemple #6
0
// Handle takes the next handler as an argument and wraps it in this middleware.
func (m *Middle) Handle(next httpware.Handler) httpware.Handler {
	return httpware.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
		token, err := request.ParseFromRequest(
			r,
			request.AuthorizationHeaderExtractor,
			func(token *jwt.Token) (interface{}, error) {
				return m.conf.Secret, nil
			},
		)

		if err == nil && token.Valid {
			newCtx := context.WithValue(ctx, httpware.TokenKey, token)
			return next.ServeHTTPCtx(newCtx, w, r)
		}

		// No soup for you.
		return httpware.NewErr("invalid token", http.StatusUnauthorized)
	})
}
Exemple #7
0
// isJWTReqAuthenticated validates if any incoming request to be a
// valid JWT authenticated request.
func isJWTReqAuthenticated(req *http.Request) bool {
	jwt, err := newJWT(defaultJWTExpiry, serverConfig.GetCredential())
	if err != nil {
		errorIf(err, "unable to initialize a new JWT")
		return false
	}

	var reqCallback jwtgo.Keyfunc
	reqCallback = func(token *jwtgo.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwtgo.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
		}
		return []byte(jwt.SecretAccessKey), nil
	}
	token, err := jwtreq.ParseFromRequest(req, jwtreq.AuthorizationHeaderExtractor, reqCallback)
	if err != nil {
		errorIf(err, "token parsing failed")
		return false
	}
	return token.Valid
}