index-functions.php ➔ getUserAndRespond()   B
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 123

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 123
rs 8
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file contains functions called by index.php. The index.php
5
 * file should include this file with the following statement at the top:
6
 *
7
 * require_once __DIR__ . '/index-functions.php';
8
 */
9
10
use CILogon\Service\Util;
11
use CILogon\Service\OAuth2Provider;
12
use League\OAuth2\Client\Token\AccessToken;
13
14
/**
15
 * getUserAndRespond
16
 *
17
 * This function specifically handles the redirect from OAuth2 providers.
18
 * The function reads client keys/secrets from a local configuration file,
19
 * and then uses the PHP League OAuth2 client library to extract user
20
 * parameters from the HTTP response.
21
 */
22
function getUserAndRespond()
23
{
24
    $providerId = '';
25
    $providerName = '';
26
    $first_name = '';
27
    $last_name = '';
28
    $display_name = '';
29
    $email = '';
30
    $open_id = '';
31
    $oidc = '';
32
    $amr = '';
33
34
    Util::unsetSessionVar('logonerror');
35
36
    $state = Util::getGetVar('state');  // 'state' must match last CSRF value
37
    $code = Util::getGetVar('code');    // 'code' must not be empty
38
    $lastcsrf = Util::getCsrf()->getTheCookie();
39
    if ($state != $lastcsrf) {
40
        // Verify that response's 'state' equals the last CSRF token
41
        Util::setSessionVar('logonerror', 'Invalid state parameter.');
42
    } elseif (strlen($code) == 0) {
43
        // Make sure the response has a non-empty 'code'
44
        $error = Util::getGetVar('error');
45
        $error_description = Util::getGetVar('error_description');
46
        if ((strlen($error) > 0) && (strlen($error_description) > 0)) {
47
            Util::setSessionVar('logonerror', $error_description . '. Please try again.');
48
        } else {
49
            Util::setSessionVar('logonerror', 'Empty code parameter. Please try again.');
50
        }
51
    } else {
52
        // When using OAuth or OIDC, check portalcookie for providerId
53
        $providerId = Util::getPortalOrCookieVar('providerId');
54
        $providerName = Util::getAuthzIdP($providerId);
55
        $prov = strtolower($providerName); // IdP name all lowercase
56
57
        // Get the client id/secret for the OAuth2 IdP
58
        $clientid     = constant(strtoupper($prov) . '_OAUTH2_CLIENT_ID');
59
        $clientsecret = constant(strtoupper($prov) . '_OAUTH2_CLIENT_SECRET');
60
        if ((strlen($clientid) > 0) && (strlen($clientsecret) > 0)) {
61
            $oauth2 = new OAuth2Provider($providerName);
62
            try {
63
                $token = $oauth2->provider->getAccessToken(
64
                    'authorization_code',
65
                    [ 'code' => $code ]
66
                );
67
                $user = $oauth2->provider->getResourceOwner($token);
68
                $oidc = $user->getId();
69
                $email = $user->getEmail();
70
                // GitHub email may require special handling
71
                if ((strlen($email) == 0) && ($prov == 'github')) {
72
                    $email = getGitHubEmail($oauth2, $token);
73
                }
74
                $display_name = $user->getName();
75
                if ($prov != 'github') { // No first/last for GitHub
76
                    $first_name = $user->getFirstName();
77
                    $last_name = $user->getLastName();
78
                }
79
                // CIL-799 Get the 'amr' claim from the ORCID id_token
80
                if ($prov == 'orcid') {
81
                    $amr = $user->getAmr();
82
                }
83
84
                // CIL-793 - Calculate missing first/last name for OAuth1
85
                $callbackuri = Util::getSessionVar('callbackuri'); // OAuth 1.0a
86
                if (
87
                    (strlen($callbackuri) > 0) &&
88
                    ((strlen($first_name) == 0) ||
89
                     (strlen($last_name) == 0))
90
                ) {
91
                    list($first, $last) = Util::getFirstAndLastName(
92
                        $display_name,
93
                        $first_name,
94
                        $last_name
95
                    );
96
                    $first_name = $first;
97
                    $last_name = $last;
98
                }
99
            } catch (Exception $e) {
100
                Util::setSessionVar('logonerror', $e->getMessage());
101
            }
102
        } else {
103
            Util::setSessionVar(
104
                'logonerror',
105
                'Missing OAuth2 client configuration values.'
106
            );
107
        }
108
    }
109
110
    // If no error reported, check for session var 'storeattributes'
111
    // which indicates to simply store the user attributes in the
112
    // PHP session. If not set, then by default save the user
113
    // attributes to the database (which also stores the user
114
    // attributes in the PHP session).
115
    if (strlen(Util::getSessionVar('logonerror')) == 0) {
116
        $func = 'CILogon\Service\Util::saveUserToDataStore';
117
        if (!empty(Util::getSessionVar('storeattributes'))) {
118
            $func = 'CILogon\Service\Util::setUserAttributeSessionVars';
119
        }
120
        $func(
121
            $open_id,
122
            $providerId,
123
            $providerName,
124
            $first_name,
125
            $last_name,
126
            $display_name,
127
            $email,
128
            'openid',
129
            '', // ePPN
130
            '', // ePTID
131
            $open_id,
132
            $oidc,
133
            '', // subject_id
134
            '', // pairwise_id
135
            '', // affiliation
136
            '', // ou
137
            '', // member_of
138
            '', // acr
139
            $amr
140
        );
141
    } else {
142
        Util::unsetSessionVar('submit');
143
    }
144
}
145
146
/**
147
 * getGitHubEmail
148
 *
149
 * This function gets a GitHub user email address from the special
150
 * user email API endpoint. It returns an email address that is marked
151
 * as 'primary' by GitHub.
152
 *
153
 * @param OAuth2Provider An exsiting OAuth2Provider object
154
 * @param League\OAuth2\Client\Token\AccessToken An oauth2 token
155
 * @return string A GitHub user's primary email address, or empty string
156
 *         if no such email address exists.
157
 */
158
function getGitHubEmail($oauth2, $token)
159
{
160
    $oauth2_email = '';
161
162
    $request = $oauth2->provider->getAuthenticatedRequest(
163
        'GET',
164
        'https://api.github.com/user/emails',
165
        $token
166
    );
167
    $github_emails = json_decode(
168
        $oauth2->provider->getResponse($request)->getBody()
169
    );
170
171
    foreach ($github_emails as $email) {
172
        if ($email->primary == 1) {
173
            $oauth2_email = $email->email;
174
            break;
175
        }
176
    }
177
178
    return $oauth2_email;
179
}
180