1<?php
2
3// must be run within Dokuwiki
4if (!defined('DOKU_INC')) {
5    die();
6}
7
8class auth_plugin_authloginapi extends DokuWiki_Auth_Plugin
9{
10    protected $token;
11
12    /**
13     * Constructor.
14     */
15    public function __construct()
16    {
17        parent::__construct();
18
19        $this->cando['external'] = true;
20
21        $this->token = $this->getConf('token');
22
23        $this->success = true;
24    }
25
26    /**
27     * Do all authentication
28     *
29     * @param  string $user   Username
30     * @param  string $pass   Cleartext Password
31     * @param  bool   $sticky Cookie should not expire
32     * @return bool   true on successful auth
33     */
34    public function trustExternal($user, $pass, $sticky = false)
35    {
36        global $USERINFO;
37        global $ACT;
38
39        $session = $_SESSION[DOKU_COOKIE]['auth'];
40        if (isset($session['info'])) {
41            $_SERVER['REMOTE_USER'] = $session['user'];
42            $USERINFO = $session['info'];
43
44            return true;
45        }
46
47        if ($ACT == 'login' && isset($_GET['r']) && isset($_GET['s'])) { // parse response
48            $data = $this->parseResponse($_GET['r'], $_GET['s']);
49
50            if (!$data || $data['action'] != 'login' || !isset($data['success']) || !$data['success']) {
51                msg($this->getLang('login_failed'), -1);
52
53                return false;
54            }
55            if (!isset($data['user']['groups'])) {
56                $data['user']['groups'] = array();
57            }
58
59            $this->setUserSession($data['user']['id'], $data['user']['username'], $data['user']['groups']);
60
61            return true;
62        }
63
64        return false;
65    }
66
67    /**
68     * Parse and validate a backend response
69     *
70     * @param  string     $raw
71     * @param  string     $signature
72     * @return array|null
73     */
74    protected function parseResponse($raw, $signature)
75    {
76        $signatureInput = $raw.$this->token;
77        $signatureExpected = hash('sha256', $signatureInput);
78        if ($signatureExpected != $signature) {
79            return;
80        }
81
82        $data = json_decode(base64_decode(str_pad(strtr($raw, '-_', '+/'), strlen($raw) % 4, '=', STR_PAD_RIGHT)), true);
83        if (!$data || !isset($data['time']) || !isset($data['action'])) {
84            return;
85        }
86
87        if (abs($data['time'] - time()) > 600) {
88            return;
89        }
90
91        return $data;
92    }
93
94    /**
95     * Setup session to login a user
96     *
97     * @param string $id
98     * @param string $username
99     * @param array  $groups
100     */
101    protected function setUserSession($id, $username, $groups = array())
102    {
103        global $USERINFO;
104
105        $groups = array_unique($groups);
106
107        $USERINFO['name'] = $username;
108        $USERINFO['mail'] = '';
109        $USERINFO['grps'] = $groups;
110        $_SERVER['REMOTE_USER'] = $id;
111
112        $_SESSION[DOKU_COOKIE]['auth']['user'] = $id;
113        $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO;
114    }
115}
116