cosmocode / dokuwiki-plugin-oauth

Generic oAuth1 and oAuth2 plugin for DokuWiki
http://www.dokuwiki.org/plugin:oauth
30 stars 78 forks source link

"Your (re)login has failed." each a few pages #70

Closed fdcastel closed 2 years ago

fdcastel commented 5 years ago

I've installed this plugin and it works... For a while. 😢

It works for about 2 or 3 pageviews. Then it kicks me out to login page with the message "Your (re)login has failed."

image

Then I enter with my Google account again, it works, and the problem occurs again. I can see 2 or 3 pages (with some luck). But invariably I will get the login page again.

It is simply unusable for us at its current state. 😞 We are migrating all our services to use Google Auth and it is working perfectly with several other services.

I understand this is not enough information to debug the problem. Please advise if I can send more helpful information (logs?)

doubledgedboard commented 3 years ago

I get the same behavior and I'm trying to use a reverse proxy to serve the site.

doubledgedboard commented 3 years ago

I noticed that when the issue occurs, the session cookie appears to be missing

doubledgedboard commented 3 years ago

Is it possible that the REMOTE_ADDR is used to tie the session somehow? When using through cloudfront, the remote address changes from request to request.

AIDungeonWiXAnon commented 3 years ago

Is it possible that the REMOTE_ADDR is used to tie the session somehow? When using through cloudfront, the remote address changes from request to request.

It does indeed, I had the same issue. More specifically, the browser's UID is pulled using the auth_browseruid() function of Dokuwiki located here: https://github.com/splitbrain/dokuwiki/blob/8eb6b2dc77730355efb38eacb07ba0b50c7a8d1b/inc/auth.php#L286 Since this uses the first byte/network portion of the IP, it can end up getting changed by the remote address changing. It's used both by the helper.php to verify the UID (validBrowserID()) and by auth.php went setting the user session (setUserSession()).

Ideally, there'd be a config option in Dokuwiki that would allow for Cloudflare/CloudFront/etc. support that would remove this information from the UID, but in the meantime, I am using this fix that has been working: Inside of helper.php:

    /**
     * Generates a pseudo UID from browser data.
     * Removes IP component because each IP from
     * Cloudflare's redirects can be different.
     * 
     * Based on work by Andreas Gohr <andi@splitbrain.org>
     *
     * @return string an MD5 sum of various browser headers
     */
    public function cust_auth_browseruid () {
        /* @var Input $INPUT */
        global $INPUT;

        $ip  = clientIP(true);
        $uid = '';
        $uid .= $INPUT->server->str('HTTP_USER_AGENT');
        $uid .= $INPUT->server->str('HTTP_ACCEPT_CHARSET');
        $uid = \dokuwiki\Utf8\PhpString::strtolower($uid);
        return md5($uid);

    }

    /**
     * @param array $session cookie auth session
     *
     * @return bool
     */
    public function validBrowserID ($session) {
        return $session['buid'] == $this->cust_auth_browseruid();
    }

And inside of auth.php:

    /**
     * @param array  $data
     * @param string $service
     */
    protected function setUserSession($data, $service) {
        global $USERINFO;
        global $conf;

    $hlp = plugin_load('helper', 'oauth');

        // set up groups
        if(!is_array($data['grps'])) {
            $data['grps'] = array();
        }
        $data['grps'][] = $this->getGroup($data['user']);
        $data['grps']   = array_unique($data['grps']);

        $USERINFO                               = $data;
        $_SERVER['REMOTE_USER']                 = $data['user'];
        $_SESSION[DOKU_COOKIE]['auth']['user']  = $data['user'];
        $_SESSION[DOKU_COOKIE]['auth']['pass']  = $data['pass'];
        $_SESSION[DOKU_COOKIE]['auth']['info']  = $USERINFO;
        $_SESSION[DOKU_COOKIE]['auth']['buid']  = $hlp->cust_auth_browseruid();
        $_SESSION[DOKU_COOKIE]['auth']['time']  = time();
        $_SESSION[DOKU_COOKIE]['auth']['oauth'] = $service;
    }