public function getIdentity()
    {
        if ($this->identity) {
            return $this->identity;
        }

        if (!isset($_COOKIE[self::COOKIE_VERIFY_A], $_COOKIE[self::COOKIE_VERIFY_B], $_COOKIE[self::COOKIE_USER])) {
            return null;
        }

        $systemKey = new EncryptionKey($this->systemEncryptionKey);
        $verificationCookie = $_COOKIE[self::COOKIE_VERIFY_A];
        $hashPass = hash_equals(
            hash_hmac('sha256', $_COOKIE[self::COOKIE_USER], $systemKey),
            $verificationCookie
        );

        //
        // 1. Is the verify cookie still equivalent to the user cookie, if so, do not decrypt
        //
        if (!$hashPass) {
            return null;
        }

        //
        // 2. If the user cookie was not tampered with, decrypt its contents with the system key
        //
        try {

            $userTuple = Crypto::decrypt(base64_decode($_COOKIE[self::COOKIE_USER]), $systemKey);

            if (strpos($userTuple, ':') === false) {
                throw new \Exception();
            }

            // paranoid, make sure we have everything we need
            @list($cookieUserId, $hashCookieSuffix) = @explode(":", $userTuple, 2);
            if (!isset($cookieUserId, $hashCookieSuffix) || !is_numeric($cookieUserId) || !trim($hashCookieSuffix)) {
                throw new \Exception();
            }

            /** @var AuthenticationRecordInterface $auth */
            if (!($auth = $this->authenticationProvider->findByUserId($cookieUserId))) {
                throw new \Exception();
            }

            $hashCookieName = self::COOKIE_HASH_PREFIX . $hashCookieSuffix;

            //
            // 2. Check the hashCookie for corroborating data
            //
            if (!isset($_COOKIE[$hashCookieName])) {
                throw new \Exception();
            }

            $userKey = new EncryptionKey(new HiddenString($auth->getSessionKey()));
            $hashPass = hash_equals(
                hash_hmac('sha256', $_COOKIE[$hashCookieName], $userKey),
                $_COOKIE[self::COOKIE_VERIFY_B]
            );

            if (!$hashPass) {
                throw new \Exception();
            }

            //
            // 3. Decrypt the hash cookie with the user key
            //
            $hashedCookieContents = Crypto::decrypt(base64_decode($_COOKIE[$hashCookieName]), $userKey);
            if (!substr_count($hashedCookieContents, ':') === 2) {
                throw new \Exception();
            }

            list(, $hashedUserId, $hashedUsername) = explode(':', $hashedCookieContents);
            if ($hashedUserId !== $cookieUserId) {
                throw new \Exception();
            }

            if ($hashedUsername !== $auth->getUsername()) {
                throw new \Exception();
            }

            $this->purgeHashCookies($hashCookieName);

            //
            // 4. Cookies check out - it's up to the user provider now
            //
            $user = $this->userProvider->getUser($auth->getUserId());
            if ($user) {
                $this->setIdentity($user);

                return $this->identity;
            }

        } catch (\Exception $x) {
            $this->purgeHashCookies();
        }

        return null;
    }
public function getIdentity()
    {
        if ($this->identity) {
            return $this->identity;
        }

        if (!isset($_COOKIE[self::COOKIE_VERIFY_A], $_COOKIE[self::COOKIE_VERIFY_B], $_COOKIE[self::COOKIE_USER])) {
            return null;
        }

        $systemKey = new EncryptionKey($this->systemEncryptionKey);
        $verificationCookie = $_COOKIE[self::COOKIE_VERIFY_A];
        $hashPass = hash_equals(
            hash_hmac('sha256', $_COOKIE[self::COOKIE_USER], $systemKey),
            $verificationCookie
        );

        //
        // 1. Is the verify cookie still equivalent to the user cookie, if so, do not decrypt
        //
        if (!$hashPass) {
            return null;
        }

        //
        // 2. If the user cookie was not tampered with, decrypt its contents with the system key
        //
        try {

            $userTuple = Crypto::decrypt(base64_decode($_COOKIE[self::COOKIE_USER]), $systemKey);

            if (strpos($userTuple, ':') === false) {
                throw new \Exception();
            }

            // paranoid, make sure we have everything we need
            @list($cookieUserId, $hashCookieSuffix) = @explode(":", $userTuple, 2);
            if (!isset($cookieUserId, $hashCookieSuffix) || !is_numeric($cookieUserId) || !trim($hashCookieSuffix)) {
                throw new \Exception();
            }

            /** @var AuthenticationRecordInterface $auth */
            if (!($auth = $this->authenticationProvider->findByUserId($cookieUserId))) {
                throw new \Exception();
            }

            $hashCookieName = self::COOKIE_HASH_PREFIX . $hashCookieSuffix;

            //
            // 2. Check the hashCookie for corroborating data
            //
            if (!isset($_COOKIE[$hashCookieName])) {
                throw new \Exception();
            }

            $userKey = new EncryptionKey(new HiddenString($auth->getSessionKey()));
            $hashPass = hash_equals(
                hash_hmac('sha256', $_COOKIE[$hashCookieName], $userKey),
                $_COOKIE[self::COOKIE_VERIFY_B]
            );

            if (!$hashPass) {
                throw new \Exception();
            }

            //
            // 3. Decrypt the hash cookie with the user key
            //
            $hashedCookieContents = Crypto::decrypt(base64_decode($_COOKIE[$hashCookieName]), $userKey);
            if (!substr_count($hashedCookieContents, ':') === 2) {
                throw new \Exception();
            }

            list(, $hashedUserId, $hashedUsername) = explode(':', $hashedCookieContents);
            if ($hashedUserId !== $cookieUserId) {
                throw new \Exception();
            }

            if ($hashedUsername !== $auth->getUsername()) {
                throw new \Exception();
            }

            $this->purgeHashCookies($hashCookieName);

            //
            // 4. Cookies check out - it's up to the user provider now
            //
            $user = $this->userProvider->getUser($auth->getUserId());
            if ($user) {
                $this->setIdentity($user);

                return $this->identity;
            }

        } catch (\Exception $x) {
            $this->purgeHashCookies();
        }

        return null;
    }
public function getIdentity ( ) { if ( $ this -> identity ) { return $ this -> identity ; } if ( ! isset ( $ _COOKIE [ self :: COOKIE_VERIFY_A ] , $ _COOKIE [ self :: COOKIE_VERIFY_B ] , $ _COOKIE [ self :: COOKIE_USER ] ) ) { return null ; } $ systemKey = new EncryptionKey ( $ this -> systemEncryptionKey ) ; $ verificationCookie = $ _COOKIE [ self :: COOKIE_VERIFY_A ] ; $ hashPass = hash_equals ( hash_hmac ( 'sha256' , $ _COOKIE [ self :: COOKIE_USER ] , $ systemKey ) , $ verificationCookie ) ; // // 1. Is the verify cookie still equivalent to the user cookie, if so, do not decrypt // if ( ! $ hashPass ) { return null ; } // // 2. If the user cookie was not tampered with, decrypt its contents with the system key // try { $ userTuple = Crypto :: decrypt ( base64_decode ( $ _COOKIE [ self :: COOKIE_USER ] ) , $ systemKey ) ; if ( strpos ( $ userTuple , ':' ) === false ) { throw new \ Exception ( ) ; } // paranoid, make sure we have everything we need @ list ( $ cookieUserId , $ hashCookieSuffix ) = @ explode ( ":" , $ userTuple , 2 ) ; if ( ! isset ( $ cookieUserId , $ hashCookieSuffix ) || ! is_numeric ( $ cookieUserId ) || ! trim ( $ hashCookieSuffix ) ) { throw new \ Exception ( ) ; } /** @var AuthenticationRecordInterface $auth */ if ( ! ( $ auth = $ this -> authenticationProvider -> findByUserId ( $ cookieUserId ) ) ) { throw new \ Exception ( ) ; } $ hashCookieName = self :: COOKIE_HASH_PREFIX . $ hashCookieSuffix ; // // 2. Check the hashCookie for corroborating data // if ( ! isset ( $ _COOKIE [ $ hashCookieName ] ) ) { throw new \ Exception ( ) ; } $ userKey = new EncryptionKey ( new HiddenString ( $ auth -> getSessionKey ( ) ) ) ; $ hashPass = hash_equals ( hash_hmac ( 'sha256' , $ _COOKIE [ $ hashCookieName ] , $ userKey ) , $ _COOKIE [ self :: COOKIE_VERIFY_B ] ) ; if ( ! $ hashPass ) { throw new \ Exception ( ) ; } // // 3. Decrypt the hash cookie with the user key // $ hashedCookieContents = Crypto :: decrypt ( base64_decode ( $ _COOKIE [ $ hashCookieName ] ) , $ userKey ) ; if ( ! substr_count ( $ hashedCookieContents , ':' ) === 2 ) { throw new \ Exception ( ) ; } list ( , $ hashedUserId , $ hashedUsername ) = explode ( ':' , $ hashedCookieContents ) ; if ( $ hashedUserId !== $ cookieUserId ) { throw new \ Exception ( ) ; } if ( $ hashedUsername !== $ auth -> getUsername ( ) ) { throw new \ Exception ( ) ; } $ this -> purgeHashCookies ( $ hashCookieName ) ; // // 4. Cookies check out - it's up to the user provider now // $ user = $ this -> userProvider -> getUser ( $ auth -> getUserId ( ) ) ; if ( $ user ) { $ this -> setIdentity ( $ user ) ; return $ this -> identity ; } } catch ( \ Exception $ x ) { $ this -> purgeHashCookies ( ) ; } return null ; }
Rifle through 4 cookies, ensuring that all details line up.  If they do, we accept that the cookies authenticate
a specific user.

Some notes:

- COOKIE_VERIFY_A is a do-not-decrypt check of COOKIE_USER
- COOKIE_VERIFY_B is a do-not-decrypt check of the random-named-cookie specified by COOKIE_USER
- COOKIE_USER has its contents encrypted by the system key
- the random-named-cookie has its contents encrypted by the user key

@see self::setSessionCookies
@return User|null
Rifle through 4 cookies ensuring that all details line up . If they do we accept that the cookies authenticate a specific user .