xref: /plugin/oauthgeneric/action.php (revision ad7ba96d107a088eb9cfedef27a11192c4c72648)
1<?php
2
3use dokuwiki\plugin\oauth\Adapter;
4use dokuwiki\plugin\oauthgeneric\DotAccess;
5use dokuwiki\plugin\oauthgeneric\Generic;
6
7/**
8 * Service Implementation for oAuth Doorkeeper authentication
9 */
10class action_plugin_oauthgeneric extends Adapter
11{
12
13    /** @inheritdoc */
14    public function registerServiceClass()
15    {
16        return Generic::class;
17    }
18
19    /** * @inheritDoc */
20    public function getUser()
21    {
22        $oauth = $this->getOAuthService();
23        $data = array();
24
25        $url = $this->getConf('userurl');
26        $raw = $oauth->request($url);
27
28        if (!$raw) throw new OAuthException('Failed to fetch data from userurl');
29        $result = json_decode($raw, true);
30        if (!$result) throw new OAuthException('Failed to parse data from userurl');
31
32        $grpdots = sexplode('[]', $this->getConf('json-grps'), 2);
33        $user = DotAccess::get($result, $this->getConf('json-user'), '');
34        $name = DotAccess::get($result, $this->getConf('json-name'), '');
35        $mail = DotAccess::get($result, $this->getConf('json-mail'), '');
36        $grps = DotAccess::get($result, $grpdots[0], []);
37
38        // use dot notation on each group
39        if (is_array($grps) && $grpdots[1]) {
40            $grps = array_map(function ($grp) use ($grpdots) {
41                return DotAccess::get($grp, $grpdots[1], '');
42            }, $grps);
43        }
44
45        // type fixes
46        if (is_array($user)) $user = array_shift($user);
47        if (is_array($name)) $name = array_shift($name);
48        if (is_array($mail)) $mail = array_shift($mail);
49        if (!is_array($grps)) {
50            $grps = explode(',', $grps);
51            $grps = array_map('trim', $grps);
52        }
53
54        // fallbacks for user name
55        if (empty($user)) {
56            if (!empty($name)) {
57                $user = $name;
58            } elseif (!empty($mail)) {
59                list($user) = explode('@', $mail);
60            }
61        }
62
63        // fallback for full name
64        if (empty($name)) {
65            $name = $user;
66        }
67
68        return compact('user', 'name', 'mail', 'grps');
69    }
70
71    /** @inheritdoc */
72    public function logout()
73    {
74        $url = $this->getConf('logouturl');
75        if (!$url) {
76            parent::logout();
77            return;
78        }
79
80        // add ID token if available
81        $oauth = $this->getOAuthService();
82        $token = $oauth->getStorage()->retrieveAccessToken($oauth->service());
83        $params = $token->getExtraParams();
84        if (isset($params['id_token'])) {
85            $url .= (strpos($url, '?') === false ? '?' : '&') . 'id_token_hint=' . urlencode($params['id_token']);
86        }
87
88        // redirect back to dokuwiki after logout
89        /** @var helper_plugin_oauth $helper */
90        $helper = plugin_load('helper', 'oauth');
91        $redir = $helper->redirectURI();
92        $url .= (strpos($url, '?') === false ? '?' : '&') . 'post_logout_redirect_uri=' . urlencode($redir);
93
94        // add state if needed (we don't check it, but some providers require it)
95        if ($this->getConf('needs-state')) {
96            $state = bin2hex(random_bytes(16));
97            $url .= (strpos($url, '?') === false ? '?' : '&') . 'state=' . urlencode($state);
98        }
99
100        parent::logout();
101        send_redirect($url);
102        exit;
103    }
104
105
106    /** @inheritdoc */
107    public function getScopes()
108    {
109        return $this->getConf('scopes');
110    }
111
112    /** @inheritDoc */
113    public function getLabel()
114    {
115        return $this->getConf('label');
116    }
117
118    /** @inheritDoc */
119    public function getColor()
120    {
121        return $this->getConf('color');
122    }
123}
124