1<?php
2
3namespace dokuwiki\plugin\oauthazure;
4
5use dokuwiki\HTTP\DokuHTTPClient;
6use dokuwiki\plugin\oauth\Service\AbstractOAuth2Base;
7use OAuth\Common\Http\Uri\Uri;
8
9/**
10 * Custom Service for Azure oAuth
11 */
12class Azure extends AbstractOAuth2Base
13{
14    /**
15     * Defined scopes are listed here:
16     * @link https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent
17     */
18    const SCOPE_OPENID = 'openid';
19    const SCOPE_EMAIL = 'email';
20    const SCOPE_PROFILE = 'profile';
21    const SCOPE_OFFLINE = 'offline_access';
22    const SCOPE_USERREAD = 'https://graph.microsoft.com/user.read';
23    const SCOPE_GROUPMEMBER = 'https://graph.microsoft.com/GroupMember.Read.All';
24
25    /**
26     * Endpoints are listed here:
27     * @link https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#authorization-server-metadata
28     */
29    const ENDPOINT_AUTH = 'authorization_endpoint';
30    const ENDPOINT_TOKEN = 'token_endpoint';
31    const ENDPOINT_USERINFO = 'userinfo_endpoint';
32    const ENDPOINT_LOGOUT = 'end_session_endpoint';
33
34    // graph API endpoint to read group memberships
35    const GRAPH_MEMBEROF = 'https://graph.microsoft.com/v1.0/me/memberof';
36
37    /** @var string[] discovery URL cache */
38    protected $discovery;
39
40    /**
41     * Return URI of discovered endpoint
42     *
43     * @return string
44     */
45    public function getEndpoint(string $endpoint)
46    {
47        if (!isset($this->discovery)) {
48            $plugin = plugin_load('action', 'oauthazure');
49            $discover = 'https://login.microsoftonline.com/%s/v2.0/.well-known/openid-configuration';
50            $discover = sprintf($discover, $plugin->getConf('tenant'));
51
52            $http = new DokuHTTPClient();
53            $json = $http->get($discover);
54            if (!$json) return '';
55            $this->discovery = json_decode($json, true);
56        }
57        if (!isset($this->discovery[$endpoint])) return '';
58        return $this->discovery[$endpoint];
59    }
60
61    /** @inheritdoc */
62    public function getAuthorizationEndpoint()
63    {
64        global $conf;
65        $uri = new Uri($this->getEndpoint(self::ENDPOINT_AUTH));
66        if (isset($conf['plugin']['oauth']['mailRestriction'])) {
67            $uri->addToQuery('domain_hint', substr($conf['plugin']['oauth']['mailRestriction'], 1));
68        }
69        return $uri;
70    }
71
72    /** @inheritdoc */
73    public function getAccessTokenEndpoint()
74    {
75        $uri = new Uri($this->getEndpoint(self::ENDPOINT_TOKEN));
76        //$uri->addToQuery('requested_token_use', 'on_behalf_of');
77        return $uri;
78    }
79
80    /** @inheritdoc */
81    protected function getAuthorizationMethod()
82    {
83        return static::AUTHORIZATION_METHOD_HEADER_BEARER;
84    }
85
86    /**
87     * Logout from Azure
88     *
89     * @return void
90     * @throws \OAuth\Common\Exception\Exception
91     */
92    public function logout()
93    {
94        send_redirect($this->getEndpoint(self::ENDPOINT_LOGOUT));
95    }
96}
97