public static function verifyCredentials(ObjectRetriever $retriever, $username, $password) {
        // Validate input
        $namespaceCoid = new IRI('coid://'.$username);
        if (COIDParser::getType($namespaceCoid) != COIDParser::COID_ROOT)
            return self::RESULT_INVALID_USERNAME;
        if (strlen($password) != 40)
            return self::RESULT_INVALID_PASSWORD;

        // Retrieve namespace
        $namespace = $retriever->getObject($namespaceCoid);
        if (!isset($namespace))
            return self::RESULT_NAMESPACE_NOT_FOUND;

        // Read and validate shared secret
        $reader = new NodeReader([
            'prefixes' => [
                'co' => 'coid://cloudobjects.io/'
            ]
        ]);
        $sharedSecret = $reader->getAllValuesNode($namespace, 'co:hasSharedSecret');
        if (count($sharedSecret) != 1)
            return self::RESULT_SHARED_SECRET_NOT_RETRIEVABLE;
        
        if ($reader->getFirstValueString($sharedSecret[0], 'co:hasTokenValue') == $password)
            return self::RESULT_OK;
        else
            return self::RESULT_SHARED_SECRET_INCORRECT;        
    }