public function verifyAndDecode($jwt)
    {
        $tks = explode('.', $jwt);

        if (count($tks) !== 3) {
            throw new InvalidTokenException('Wrong number of segments');
        }

        try {
            $head_decoded = $this->decodeTokenSegment($tks[0]);
            $body_decoded = $this->decodeTokenSegment($tks[1]);
        } catch (\DomainException $e) {
            throw new InvalidTokenException('Malformed token.');
        }

        if (! is_object($head_decoded) || ! is_object($body_decoded)) {
            throw new InvalidTokenException('Malformed token.');
        }

        if (empty($head_decoded->alg)) {
            throw new InvalidTokenException('Token algorithm not found');
        }

        if (! $this->supportsAlg($head_decoded->alg)) {
            throw new InvalidTokenException('Token algorithm not supported');
        }

        // Validate the token audience, if present.
        if (! empty($body_decoded->aud)) {
            $audience = is_array($body_decoded->aud) ? $body_decoded->aud : [$body_decoded->aud];
            if (! count(array_intersect($audience, $this->valid_audiences))) {
                $message  = 'Invalid token audience '.implode( ', ', $audience );
                $message .= '; expected '.implode( ', ', $this->valid_audiences );
                throw new InvalidTokenException($message);
            }
        }

        if ('HS256' === $head_decoded->alg) {
            $secret = $this->client_secret;
        } else {
            if (empty($head_decoded->kid)) {
                throw new CoreException('Token key ID is missing for RS256 token');
            }

            if (empty($body_decoded->iss) || ! in_array($body_decoded->iss, $this->authorized_iss)) {
                throw new CoreException('We cannot trust on a token issued by `'.$body_decoded->iss.'`');
            }

            $jwks_url                   = $body_decoded->iss.$this->jwks_path;
            $secret[$head_decoded->kid] = $this->JWKFetcher->requestJwkX5c($jwks_url, $head_decoded->kid);
        }

        try {
            return $this->decodeToken($jwt, $secret);
        } catch (\Exception $e) {
            throw new CoreException($e->getMessage());
        }
    }