Passed
Push — master ( 4c69e1...93a00e )
by Stefan
10:14
created

Authentication::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
/*
3
 * *****************************************************************************
4
 * Contributions to this work were made on behalf of the GÉANT project, a 
5
 * project that has received funding from the European Union’s Framework 
6
 * Programme 7 under Grant Agreements No. 238875 (GN3) and No. 605243 (GN3plus),
7
 * Horizon 2020 research and innovation programme under Grant Agreements No. 
8
 * 691567 (GN4-1) and No. 731122 (GN4-2).
9
 * On behalf of the aforementioned projects, GEANT Association is the sole owner
10
 * of the copyright in all material which was developed by a member of the GÉANT
11
 * project. GÉANT Vereniging (Association) is registered with the Chamber of 
12
 * Commerce in Amsterdam with registration number 40535155 and operates in the 
13
 * UK as a branch of GÉANT Vereniging.
14
 * 
15
 * Registered office: Hoekenrode 3, 1102BR Amsterdam, The Netherlands. 
16
 * UK branch address: City House, 126-130 Hills Road, Cambridge CB2 1PQ, UK
17
 *
18
 * License: see the web/copyright.inc.php file in the file structure or
19
 *          <base_url>/copyright.php after deploying the software
20
 */
21
22
namespace web\lib\admin;
23
24
use Exception;
25
26
/**
27
 * This class handles admin user authentication.
28
 * 
29
 * @author Stefan Winter <[email protected]>
30
 */
31
class Authentication extends \core\common\Entity {
32
33
    public function __construct() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
34
        parent::__construct();
35
        include_once \config\Master::AUTHENTICATION['ssp-path-to-autoloader'];
36
    }
37
    /**
38
     * finds out whether the user is already authenticated. Does not trigger an authentication if not.
39
     *
40
     * @return boolean auth state
41
     */
42
    public function isAuthenticated() {
43
        $authSimple = new \SimpleSAML\Auth\Simple(\config\Master::AUTHENTICATION['ssp-authsource']);
44
        $session = \SimpleSAML\Session::getSessionFromRequest();
45
        $status = $authSimple->isAuthenticated();
46
        $session->cleanup();
47
        return $status;
48
    }
49
50
    /**
51
     * authenticates a user.
52
     * 
53
     * @return void
54
     * @throws Exception
55
     */
56
    public function authenticate() {
57
        \core\common\Entity::intoThePotatoes();
58
        $loggerInstance = new \core\common\Logging();
59
        $authSimple = new \SimpleSAML\Auth\Simple(\config\Master::AUTHENTICATION['ssp-authsource']);
60
        $authSimple->requireAuth();
61
        $admininfo = $authSimple->getAttributes();
62
        $session = \SimpleSAML\Session::getSessionFromRequest();
63
        $session->cleanup();
64
65
        if (!isset($admininfo[\config\Master::AUTHENTICATION['ssp-attrib-identifier']][0])) {
66
            $failtext = "FATAL ERROR: we did not receive a unique user identifier from the authentication source!";
67
            echo $failtext;
68
            throw new Exception($failtext);
69
        }
70
71
        $user = $admininfo[\config\Master::AUTHENTICATION['ssp-attrib-identifier']][0];
72
73
        $_SESSION['user'] = $user;
74
        $_SESSION['name'] = $admininfo[\config\Master::AUTHENTICATION['ssp-attrib-name']][0] ?? _("Unnamed User");
75
        /*
76
         * This is a nice pathological test case for a user ID.
77
         *
78
         * */
79
        //$_SESSION['user'] = "<saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" NameQualifier=\"https://idp.jisc.ac.uk/idp/shibboleth\" SPNameQualifier=\"https://cat-beta.govroam.uk/simplesaml/module.php/saml/sp/metadata.php/default-sp\" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent\">XXXXXXXXXXXXXXXX</saml:NameID>";
80
81
82
        $newNameReceived = FALSE;
83
84
        $userObject = new \core\User($user);
85
86
        $attribMapping = [
87
            "ssp-attrib-name" => "user:realname",
88
            "ssp-attrib-email" => "user:email"];
89
90
        foreach ($attribMapping as $SSPside => $CATside) {
91
            if (isset($admininfo[\config\Master::AUTHENTICATION[$SSPside]][0]) && (count($userObject->getAttributes($CATside)) == 0) && \config\Master::DB['USER']['readonly'] === FALSE) {
92
                $name = $admininfo[\config\Master::AUTHENTICATION[$SSPside]][0];
93
                $userObject->addAttribute($CATside, NULL, $name);
94
                $loggerInstance->writeAudit($_SESSION['user'], "NEW", "User - added $CATside from external auth source");
95
                if ($CATside == "user:realname") {
96
                    $newNameReceived = TRUE;
97
                }
98
            }
99
        }
100
101
        if (count($userObject->getAttributes('user:realname')) > 0 || $newNameReceived) { // we have a real name in the DB. We trust this more than a session one, so set it
102
            $nameArray = $userObject->getAttributes("user:realname");
103
            if (!empty($nameArray[0])) {
104
                $_SESSION['name'] = $nameArray[0]['value'];
105
            }
106
        }
107
        \core\common\Entity::outOfThePotatoes();
108
    }
109
110
    /**
111
     * deauthenticates the user.
112
     * Sends a SAML LogoutRequest to the IdP, which will kill the SSO session and return us to our own logout_check page.
113
     * 
114
     * @return void
115
     */
116
    public function deauthenticate() {
117
118
        $as = new \SimpleSAML\Auth\Simple(\config\Master::AUTHENTICATION['ssp-authsource']);
119
        $servername = filter_input(INPUT_SERVER, 'SERVER_NAME', FILTER_SANITIZE_STRING);
120
        $scriptself = filter_input(INPUT_SERVER, 'PHP_SELF', FILTER_SANITIZE_STRING);
121
        $url = "https://www.eduroam.org"; // fallback if something goes wrong during URL construction below
122
        $trailerPosition = strrpos($scriptself, "/inc/logout.php");
123
        if ($trailerPosition !== FALSE) {
124
            $base = substr($scriptself, 0, $trailerPosition);
125
            if ($base !== FALSE) {
126
                $url = "//$servername" . $base . "/logout_check.php";
127
            }
128
        }
129
130
        $as->logout([
131
            'ReturnTo' => $url,
132
            'ReturnStateParam' => 'LogoutState',
133
            'ReturnStateStage' => 'MyLogoutState',
134
        ]);
135
    }
136
137
}
138