Passed
Push — master ( ddecf7...23d3c8 )
by Terrence
10:52
created

DBService::clearUserCode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 5
ccs 0
cts 0
cp 0
crap 2
rs 10
1
<?php
2
3
namespace CILogon\Service;
4
5
use CILogon\Service\Util;
6
7
/**
8
 * DBService
9
 *
10
 * This class is a wrapper for the dbService servlet.  The dbService
11
 * servlet acts as a frontend to the database that stores info on users,
12
 * portal parameters, and IdPs. This was created to allow for fast
13
 * access to the database by keeping a connection open.  This class is a
14
 * rework of the old store.php class.
15
 *
16
 * Example usage:
17
 *     // For authentication, we have a bunch of attributes from an
18
 *     // identity provider. Thus get the database uid for the user
19
 *     // by using the multi-parameter version of getUser().
20
 *     $uid = '';
21
 *     $dbservice = new DBService();
22
 *     $dbservice->getUser('[email protected]',
23
 *                         'urn:mace:incommon:uiuc.edu',
24
 *                         'University of Illinois at Urbana-Champaign',
25
 *                         'John','Smith','John Smith,
26
 *                          '[email protected]');
27
 *     if (!($dbservice->status & 1)) { // OK status codes are even
28
 *         $uid = $dbservice->user_uid;
29
 *     }
30
 *
31
 *     // Later in the code, re-fetch the user using this uid
32
 *     // and print out the stored attributes.
33
 *     if (strlen($uid) > 0) {
34
 *         $dbservice->getUser($uid);
35
 *         echo 'Name = ' . $dbservice->first_name . ' ' .
36
 *                          $dbservice->last_name  . "\n";
37
 *         echo 'DN = '   . $dbservice->distinguished_name . "\n";
38
 *     }
39
 *
40
 *     // For getting/setting the Shibboleth-based IdPs, use the
41
 *     // getIdps()/setIdps() methods.  These methods utilize the
42
 *     // class member array $idp_uids for reading/writing. Two
43
 *     // convenience methods (setIdpsFromKeys($array) and
44
 *     // setIdpsFromValues($array)) are provided to populate the
45
 *     // $idp_uids array from the passed-in $array.
46
 *     $dbservice->getIdps();
47
 *     foreach($dbservice->idp_uids as $value) {
48
 *         echo "$value\n";
49
 *     }
50
 *
51
 *     $idps = array('urn:mace:incommon:ucsd.edu',
52
 *                   'urn:mace:incommon:uiuc.edu');
53
 *     $dbservice->setIdpsFromValues($idps);
54
 *     //   --- OR ---
55
 *     $idps = array('urn:mace:incommon:ucsd.edu' => 1,
56
 *                   'urn:mace:incommon:uiuc.edu' => 1);
57
 *     $dbservice->setIdpsFromKeys($idps);
58
 */
59
60
class DBService
61
{
62
    /**
63
     * @var array $STATUS The various STATUS_* constants, originally from
64
     *      Store.pm. See cilogon2-server-loader-oauth2/src/main/java/org/cilogon/oauth2/servlet/impl/DBService2.java
65
     *      in the https://github.com/cilogon/cilogon-java/ repo for the
66
     *      definitive list of oauth2 return status codes.
67
     *      The keys of the array are strings corresponding to the
68
     *      constant names. The values of the array are the integer (hex)
69
     *      values. For example, DBService::$STATUS['STATUS_OK'] = 0;
70
     *      Use 'array_search($this->status,DBService::$STATUS)' to look
71
     *      up the STATUS_* name given the status integer value.
72
     */
73
    public static $STATUS = array(
74
        'STATUS_OK'                        => 0x0,
75
        'STATUS_ACTION_NOT_FOUND'          => 0x1,
76
        'STATUS_NEW_USER'                  => 0x2,
77
        'STATUS_USER_UPDATED'              => 0x4,
78
        'STATUS_USER_NOT_FOUND'            => 0x6,
79
        'STATUS_USER_EXISTS'               => 0x8,
80
        'STATUS_USER_EXISTS_ERROR'         => 0xFFFA1, // 1048481
81
        'STATUS_USER_NOT_FOUND_ERROR'      => 0xFFFA3, // 1048483
82
        'STATUS_TRANSACTION_NOT_FOUND'     => 0xFFFA5, // 1048485
83
        'STATUS_IDP_SAVE_FAILED'           => 0xFFFA7, // 1048487
84
        'STATUS_DUPLICATE_PARAMETER_FOUND' => 0xFFFF1, // 1048561
85
        'STATUS_INTERNAL_ERROR'            => 0xFFFF3, // 1048563
86
        'STATUS_SAVE_IDP_FAILED'           => 0xFFFF5, // 1048565
87
        'STATUS_MALFORMED_INPUT_ERROR'     => 0xFFFF7, // 1048567
88
        'STATUS_MISSING_PARAMETER_ERROR'   => 0xFFFF9, // 1048569
89
        'STATUS_NO_REMOTE_USER'            => 0xFFFFB, // 1048571
90
        'STATUS_NO_IDENTITY_PROVIDER'      => 0xFFFFD, // 1048573
91
        'STATUS_CLIENT_NOT_FOUND'          => 0xFFFFF, // 1048575
92
        'STATUS_TRANSACTION_NOT_FOUND'     => 0x10001, //   65537
93
        'STATUS_EPTID_MISMATCH'            => 0x100001,// 1048577
94
        'STATUS_PAIRWISE_ID_MISMATCH'      => 0x100003,// 1048579
95
        'STATUS_SUBJECT_ID_MISMATCH'       => 0x100005,// 1048581
96
        'STATUS_EXPIRED_TOKEN'             => 0x10003, //   65539
97
        'STATUS_CREATE_TRANSACTION_FAILED' => 0x10005, //   65541
98
        'STATUS_UNKNOWN_CALLBACK'          => 0x10007, //   65543
99
        'STATUS_MISSING_CLIENT_ID'         => 0x10009, //   65545
100
        'STATUS_NO_REGISTERED_CALLBACKS'   => 0x1000B, //   65547
101
        'STATUS_UNKNOWN_CLIENT'            => 0x1000D, //   65549
102
        'STATUS_UNAPPROVED_CLIENT'         => 0x1000F, //   65551
103
        'STATUS_NO_SCOPES'                 => 0x10011, //   65553
104
        'STATUS_MALFORMED_SCOPE'           => 0x10013, //   65555
105
    );
106
107
    public static $STATUS_TEXT = array(
108
        'STATUS_OK'                        => 'Status OK.',
109
        'STATUS_ACTION_NOT_FOUND'          => 'Action not found.',
110
        'STATUS_NEW_USER'                  => 'New user created.',
111
        'STATUS_USER_UPDATED'              => 'User data updated.',
112
        'STATUS_USER_NOT_FOUND'            => 'User not found.',
113
        'STATUS_USER_EXISTS'               => 'User exists.',
114
        'STATUS_USER_EXISTS_ERROR'         => 'User already exists.',
115
        'STATUS_USER_NOT_FOUND_ERROR'      => 'User not found.',
116
        'STATUS_TRANSACTION_NOT_FOUND'     => 'Transaction not found.',
117
        'STATUS_IDP_SAVE_FAILED'           => 'Could not save IdPs.',
118
        'STATUS_DUPLICATE_PARAMETER_FOUND' => 'Duplicate parameter.',
119
        'STATUS_INTERNAL_ERROR'            => 'Internal error.',
120
        'STATUS_SAVE_IDP_FAILED'           => 'Could not save IdP.',
121
        'STATUS_MALFORMED_INPUT_ERROR'     => 'Malformed input.',
122
        'STATUS_MISSING_PARAMETER_ERROR'   => 'Missing parameter.',
123
        'STATUS_NO_REMOTE_USER'            => 'Missing Remote User.',
124
        'STATUS_NO_IDENTITY_PROVIDER'      => 'Missing IdP.',
125
        'STATUS_CLIENT_NOT_FOUND'          => 'Missing client.',
126
        'STATUS_TRANSACTION_NOT_FOUND'     => 'Transaction not found.',
127
        'STATUS_EPTID_MISMATCH'            => 'EPTID mismatch.',
128
        'STATUS_PAIRWISE_ID_MISMATCH'      => 'Pairwise ID mismatch.',
129
        'STATUS_SUBJECT_ID_MISMATCH'       => 'Subject ID mismatch.',
130
        'STATUS_EXPIRED_TOKEN'             => 'Expired token.',
131
        'STATUS_CREATE_TRANSACTION_FAILED' => 'Failed to initialize OIDC flow.',
132
        'STATUS_UNKNOWN_CALLBACK'          => 'The redirect_uri does not match a registered callback URI.',
133
        'STATUS_MISSING_CLIENT_ID'         => 'Missing client_id parameter.',
134
        'STATUS_NO_REGISTERED_CALLBACKS'   => 'No registered callback URIs.',
135
        'STATUS_UNKNOWN_CLIENT'            => 'Unknown client_id.',
136
        'STATUS_UNAPPROVED_CLIENT'         => 'Client has not been approved.',
137
        'STATUS_NO_SCOPES'                 => 'Missing or empty scope parameter.',
138
        'STATUS_MALFORMED_SCOPE'           => 'Malformed scope parameter.',
139
    );
140
141
    /**
142
     * @var array $user_attrs An array of all the user attributes that
143
     *      get passed to the getUser function. This is available to other
144
     *      function since these user attributes are set frequently
145
     *      throughout the code.
146
     */
147
    public static $user_attrs = [
148
        'remote_user',
149
        'idp',
150
        'idp_display_name',
151
        'first_name',
152
        'last_name',
153
        'display_name',
154
        'email',
155
        'loa',
156
        'eppn',
157
        'eptid',
158
        'open_id',
159
        'oidc',
160
        'subject_id',
161
        'pairwise_id',
162
        'affiliation',
163
        'ou',
164
        'member_of',
165
        'acr',
166
        'amr',
167
        'entitlement',
168
        'itrustuin',
169
    ];
170
171
    /**
172
     * @var int|null $status The returned status code from dbService calls
173
     */
174
    public $status;
175
176
    /**
177
     * @var string|null $user_uid The CILogon UID
178
     */
179
    public $user_uid;
180
181
    /**
182
     * @var string|null $remote_user The HTTP session REMOTE_USER
183
     */
184
    public $remote_user;
185
186
    /**
187
     * @var string|null $idp The Identity Provider's entityId
188
     */
189
    public $idp;
190
191
    /**
192
     * @var string|null $idp_display_name The Identity Provider's name
193
     */
194
    public $idp_display_name;
195
196
    /**
197
     * @var string|null $first_name User's given name
198
     */
199
    public $first_name;
200
201
    /**
202
     * @var string|null $last_name User's family name
203
     */
204
    public $last_name;
205
206
    /**
207
     * @var string|null $display_name User's full name
208
     */
209
    public $display_name;
210
211
    /**
212
     * @var string|null $email User's email address
213
     */
214
    public $email;
215
216
    /**
217
     * @var string|null $loa Level of Assurance (Note: not saved in database)
218
     */
219
    public $loa;
220
221
    /**
222
     * @var string|null $distinguished_name X.509 DN + email address
223
     */
224
    public $distinguished_name;
225
226
    /**
227
     * @var string|null $eppn eduPersonPrincipalName
228
     */
229
    public $eppn;
230
231
    /**
232
     * @var string|null $eptid eduPersonTargetedID
233
     */
234
    public $eptid;
235
236
    /**
237
     * @var string|null $open_id Old Google OpenID 2.0 identifier
238
     */
239
    public $open_id;
240
241
    /**
242
     * @var string|null $oidc OpenID Connect identifier
243
     */
244
    public $oidc;
245
246
    /**
247
     * @var string|null $affiliation eduPersonScopedAffiliation
248
     */
249
    public $affiliation;
250
251
    /**
252
     * @var string|null $ou Organizational Unit
253
     */
254
    public $ou;
255
256
    /**
257
     * @var string|null $member_of isMemberOf group information
258
     */
259
    public $member_of;
260
261
    /**
262
     * @var string|null $acr Authentication Context Class Ref
263
     */
264
    public $acr;
265
266
    /**
267
     * @var string|null $amr Authentication Method Reference from ORCID
268
     */
269
    public $amr;
270
271
    /**
272
     * @var string|null $entitlement eduPersonEntitlement
273
     */
274
    public $entitlement;
275
276
    /**
277
     * @var string|null $itrustuin Person's univeristy ID number
278
     */
279
    public $itrustuin;
280
281
    /**
282
     * @var string|null $subject_id Person's univeristy subject identifier
283
     */
284
    public $subject_id;
285
286
    /**
287
     * @var string|null $pairwise_id Person's univeristy pairwise identifier
288
     */
289
    public $pairwise_id;
290
291
    /**
292
     * @var string|null $serial_string CILogon serial string (e.g., A34201)
293
     */
294
    public $serial_string;
295
296
    /**
297
     * @var string|null $create_time Time user entry was created
298
     */
299
    public $create_time;
300
301
    /**
302
     * @var string|null $oauth_token OAuth 2.0 token
303
     */
304
    public $oauth_token;
305
306
    /**
307
     * @var string|null $cilogon_callback OAuth 1.0a callback URL
308
     */
309
    public $cilogon_callback;
310
311
    /**
312
     * @var string|null $cilogon_success OAuth 1.0a success URL
313
     */
314
    public $cilogon_success;
315
316
    /**
317
     * @var string|null $cilogon_failure OAuth 1.0a failure URL
318
     */
319
    public $cilogon_failure;
320
321
    /**
322
     * @var string|null $cilogon_portal_name OAuth client name
323
     */
324
    public $cilogon_portal_name;
325
326
    /**
327
     * @var string|null $client_id OAuth 2.0 client_id
328
     */
329
    public $client_id;
330
331
    /**
332
     * @var string|null $user_code OAuth 2.0 Device Authz Grant flow user_code
333
     */
334
    public $user_code;
335
336
    /**
337
     * @var array $idp_uids IdPs stored in the 'values' of the array
338
     */
339
    public $idp_uids;
340
341
    /**
342
     * @var string|null $dbservice URL The URL to use for the dbService
343
     */
344
    private $dbserviceurl;
345
346
    /**
347
     * __construct
348
     *
349
     * Default constructor.  All of the various class members are
350
     * initialized to 'null' or empty arrays.
351
     *
352
     * @param string $serviceurl (Optional) The URL of the database service
353
     *        servlet
354
     */
355
    public function __construct($serviceurl = DEFAULT_DBSERVICE_URL)
0 ignored issues
show
Bug introduced by
The constant CILogon\Service\DEFAULT_DBSERVICE_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
356
    {
357
        $this->clear();
358
        $this->setDBServiceURL($serviceurl);
359
    }
360
361
    /**
362
     * getDBServiceURL
363
     *
364
     * Returns the full URL of the database servlet used by the call()
365
     * function.
366
     *
367
     * @return string The URL of the database service servlet
368
     */
369
    public function getDBServiceURL()
370
    {
371
        return $this->dbserviceurl;
372
    }
373
374
    /**
375
     * setDBServiceURL
376
     *
377
     * Set the private variable $dbserviceurl to the full URL of the
378
     * database servlet, which is used by the call() function.
379
     *
380
     * @param string $serviceurl The URL of the database service servlet.
381
     */
382
    public function setDBServiceURL($serviceurl)
383
    {
384
        $this->dbserviceurl = $serviceurl;
385
    }
386
387
    /**
388
     * clear
389
     *
390
     * Set all of the class members to 'null' or empty arrays.
391
     */
392
    public function clear()
393
    {
394
        $this->clearUser();
395
        $this->clearPortal();
396
        $this->clearUserCode();
397
        $this->clearIdps();
398
    }
399
400
    /**
401
     * clearUser
402
     *
403
     * Set all of the class member variables associated with getUser()
404
     * to 'null'.
405
     */
406
    public function clearUser()
407
    {
408
        foreach (static::$user_attrs as $value) {
409
            $this->$value = null;
410
        }
411
        $this->status = null;
412
        $this->user_uid = null;
413
        $this->distinguished_name = null;
414
        $this->serial_string = null;
415
        $this->create_time = null;
416
    }
417
418
    /**
419
     * clearPortal
420
     *
421
     * Set all of the class member variables associated with
422
     * getPortalParameters() to 'null'.
423
     */
424
    public function clearPortal()
425
    {
426
        $this->status = null;
427
        $this->oauth_token = null;
428
        $this->cilogon_callback = null;
429
        $this->cilogon_success = null;
430
        $this->cilogon_failure = null;
431
        $this->cilogon_portal_name = null;
432
    }
433
434
    /**
435
     * clearUserCode
436
     *
437
     * Set the class member variables associated with
438
     * checkUserCode() to 'null'
439
     */
440
    public function clearUserCode()
441
    {
442
        $this->status = null;
443
        $this->user_code = null;
444
        $this->client_id = null;
445
    }
446
447
    /**
448
     * clearIdps
449
     *
450
     * Set the class member variable $idp_uids to an empty array.
451
     */
452
    public function clearIdps()
453
    {
454
        $this->status = null;
455
        $this->idp_uids = array();
456
    }
457
458
    /**
459
     * getUser
460
     *
461
     * This method calls the 'getUser' action of the servlet and sets
462
     * the class member variables associated with user info
463
     * appropriately.  If the servlet returns correctly (i.e. an HTTP
464
     * status code of 200), this method returns true.
465
     *
466
     * @param mixed $args Variable number of parameters: 1, or more.
467
     *        For 1 parameter : $uid (database user identifier)
468
     *        For more than 1 parameter, parameters can include:
469
     *            $remote_user, $idp, $idp_display_name,
470
     *            $first_name, $last_name, $display_name, $email,
471
     *            $eppn, $eptid, $openid, $oidc,
472
     *            $subject_id, $pairwise_id, $affiliation,
473
     *            $ou, $member_of, $acr, $amr, $entitlement,
474
     *            $itrustuin
475
     *
476
     * @return bool True if the servlet returned correctly. Else false.
477
     */
478
    public function getUser(...$args)
479
    {
480
        $retval = false;
481
        $this->clearUser();
482
        $this->setDBServiceURL(DEFAULT_DBSERVICE_URL);
0 ignored issues
show
Bug introduced by
The constant CILogon\Service\DEFAULT_DBSERVICE_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
483
        $numargs = count($args);
484
        if ($numargs == 1) {
485
            $retval = $this->call('action=getUser&user_uid=' .
486
                urlencode($args[0]));
487
        } elseif ($numargs > 1) {
488
            $cmd = 'action=getUser';
489
            $attr_arr = array();
490
            $ou_pos = array_search('ou', static::$user_attrs);
491
            for ($i = 0; $i < $numargs; $i++) {
492
                $arg = $args[$i];
493
                if (strlen($arg) > 0) {
494
                    if ($i > $ou_pos) {
495
                        // Put params after $ou into JSON object
496
                        $attr_arr[static::$user_attrs[$i]] = $arg;
497
                    } else {
498
                        $cmd .= '&' . static::$user_attrs[$i] . '=' . urlencode($arg);
499
                    }
500
                }
501
            }
502
            // If any elements in $attr_arr, append converted JSON object
503
            if (count($attr_arr) > 0) {
504
                if (
505
                    ($attr_json = json_encode(
506
                        $attr_arr,
507
                        JSON_FORCE_OBJECT | JSON_UNESCAPED_SLASHES
508
                    )
509
                    ) !== false
510
                ) {
511
                    $cmd .= '&attr_json=' . urlencode($attr_json);
512
                }
513
            }
514
            // Add 'us_idp' parameter for InCommon/Google (1) or eduGAIN (0)
515
            $us_idp = 0;
516
            $idp = $args[1];
517
            $idp_display_name = $args[2];
518
            if (
519
                (Util::getIdpList()->isRegisteredByInCommon($idp)) ||
520
                (in_array($idp_display_name, Util::$oauth2idps))
521
            ) {
522
                $us_idp = 1;
523
            }
524
            $cmd .= "&us_idp=$us_idp";
525
526
            $retval = $this->call($cmd);
527
        }
528
        return $retval;
529
    }
530
531
    /**
532
     * removeUser
533
     *
534
     * This method calls the 'removeUser' action of the servlet and
535
     * sets the class member variable $status appropriately.  If the
536
     * servlet returns correctly (i.e. an HTTP status code of 200),
537
     * this method returns true.
538
     *
539
     * @param string $uid The database user identifier
540
     * @return bool True if the servlet returned correctly. Else false.
541
     */
542
    public function removeUser($uid)
543
    {
544
        $this->clearUser();
545
        $this->setDBServiceURL(DEFAULT_DBSERVICE_URL);
0 ignored issues
show
Bug introduced by
The constant CILogon\Service\DEFAULT_DBSERVICE_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
546
        return $this->call('action=removeUser&user_uid=' .
547
            urlencode($uid));
548
    }
549
550
    /**
551
     * getPortalParameters
552
     *
553
     * This method calls the 'getPortalParameter' action of the servlet
554
     * and sets the class member variables associated with the portal
555
     * parameters appropriately. If the servlet returns correctly (i.e.
556
     * an HTTP status code of 200), this method returns true.
557
     *
558
     * @param string $oauth_token The database OAuth identifier token
559
     * @return bool True if the servlet returned correctly. Else false.
560
     */
561
    public function getPortalParameters($oauth_token)
562
    {
563
        $this->clearPortal();
564
        $this->setDBServiceURL(OAUTH1_DBSERVICE_URL);
0 ignored issues
show
Bug introduced by
The constant CILogon\Service\OAUTH1_DBSERVICE_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
565
        return $this->call('action=getPortalParameter&oauth_token=' .
566
            urlencode($oauth_token));
567
    }
568
569
    /**
570
     * getIdps
571
     *
572
     * This method calls the 'getAllIdps' action of the servlet and
573
     * sets the class member array $idp_uris to contain all of the
574
     * Idps in the database, stored in the 'values' of the array.  If
575
     * the servlet returns correctly (i.e. an HTTP status code of 200),
576
     * this method returns true.
577
     *
578
     * @return bool True if the servlet returned correctly. Else false.
579
     */
580
    public function getIdps()
581
    {
582
        $this->clearIdps();
583
        $this->setDBServiceURL(DEFAULT_DBSERVICE_URL);
0 ignored issues
show
Bug introduced by
The constant CILogon\Service\DEFAULT_DBSERVICE_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
584
        return $this->call('action=getAllIdps');
585
    }
586
587
    /**
588
     * setIdps
589
     *
590
     * This method calls the 'setAllIdps' action of the servlet using
591
     * the class memeber array $idp_uris as the source for the Idps to
592
     * be stored to the database.  Note that if this array is empty,
593
     * an error code will be returned in the status since at least one
594
     * IdP should be saved to the database.  If you want to pass an
595
     * array of Idps to be saved, see the setIdpsFromKeys($array) and
596
     * setIdpsFromValues($array) methods.  If the servlet returns
597
     * correctly (i.e. an HTTP status code of 200), this method
598
     * returns true.
599
     *
600
     * @return bool True if the servlet returned correctly. Else false.
601
     */
602
    public function setIdps()
603
    {
604
        $retval = false;
605
        $this->setDBServiceURL(DEFAULT_DBSERVICE_URL);
0 ignored issues
show
Bug introduced by
The constant CILogon\Service\DEFAULT_DBSERVICE_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
606
        $idpcount = count($this->idp_uids);
607
        $idpidx = 0;
608
        if ($idpcount > 0) {
609
            // Loop through the idp_uids in chunks of 50 to deal
610
            // with query parameter limit of http browsers/servers.
611
            while ($idpidx < $idpcount) { // Loop through all IdPs
612
                $fiftyidx = 0;
613
                $idplist = '';
614
                while (
615
                    ($fiftyidx < 50) && // Send 50 IdPs at a time
616
                       ($idpidx < $idpcount)
617
                ) {
618
                    $idplist .=  '&idp_uid=' .
619
                                 urlencode($this->idp_uids[$idpidx]);
620
                    $fiftyidx++;
621
                    $idpidx++;
622
                }
623
                $cmd = 'action=setAllIdps' . $idplist;
624
                $retval = $this->call($cmd);
625
            }
626
        }
627
        return $retval;
628
    }
629
630
    /**
631
     * setIdpsFromKeys
632
     *
633
     * This is a convenience method which calls setIdps using a
634
     * passed-in array of IdPs stored as the keys of the array.  It
635
     * first sets the class member array $idp_uids appropriately and
636
     * then calls the setIdps() method. If the servlet returns
637
     * correctly (i.e. an HTTP status code of 200), this method
638
     * returns true.  See also setIdpsFromValues().
639
     *
640
     * @param array $idps An array of IdPs to be saved, stored in the
641
     *       'keys' of the array.
642
     * @return bool True if the servlet returned correctly. Else false.
643
     */
644
    public function setIdpsFromKeys($idps)
645
    {
646
        $this->clearIdps();
647
        foreach ($idps as $key => $value) {
648
            $this->idp_uids[] = $key;
649
        }
650
        return $this->setIdps();
651
    }
652
653
    /**
654
     * setIdpsFromValues
655
     *
656
     * This is a convenience method which calls setIdps using a
657
     * passed-in array of IdPs stored as the values of the array.  It
658
     * first sets the class member array $idp_uids appropriately and
659
     * then calls the setIdps() method. If the servlet returns
660
     * correctly (i.e. an HTTP status code of 200), this method
661
     * returns true.  See also setIdpsFromKeys().
662
     *
663
     * @param array $idps An array of IdPs to be saved, stored in the
664
     *        'values' of the array.
665
     * @return bool True if the servlet returned correctly. Else false.
666
     */
667
    public function setIdpsFromValues($idps)
668
    {
669
        $this->clearIdps();
670
        foreach ($idps as $value) {
671
            $this->idp_uids[] = $value;
672
        }
673
        return $this->setIdps();
674
    }
675
676
    /**
677
     * setTransactionState
678
     *
679
     * This method calls the 'setTransactionState' action of the OAuth
680
     * 2.0 servlet to associate the OAuth 2.0 'code' with the database
681
     * user UID. This is necessary for the OAuth 2.0 server to be able
682
     * to return information about the user (name, email address) as
683
     * well as return a certificate for the user. If the servlet
684
     * returns correctly (i.e., an HTTP status code of 200), this method
685
     * returns true. Check the 'status' return value to verify that
686
     * the transaction state was set successfully.
687
     *
688
     * @param string $code The 'code' as returned by the OAuth 2.0 server.
689
     * @param string $uid The database user UID.
690
     * @param int $authntime The Unix timestamp of the user authentication.
691
     * @param string $loa (Optional) The Level of Assurance: '' = basic,
692
     *        'openid' =  OpenID Connect (e.g., Google),
693
     *        'http://incommonfederation.org/assurance/silver' = silver
694
     * @param string $myproxyinfo (Optional) the 'info:...' string to be
695
     *        passed to MyProxy.
696
     * @return bool True if the servlet returned correctly. Else false.
697
     */
698
    public function setTransactionState(
699
        $code,
700
        $uid,
701
        $authntime,
702
        $loa = '',
703
        $myproxyinfo = ''
704
    ) {
705
        $this->setDBServiceURL(OAUTH2_DBSERVICE_URL);
0 ignored issues
show
Bug introduced by
The constant CILogon\Service\OAUTH2_DBSERVICE_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
706
        return $this->call(
707
            'action=setTransactionState' .
708
            '&code=' . urlencode($code) .
709
            '&user_uid=' . urlencode($uid) .
710
            '&auth_time=' . urlencode($authntime) .
711
            '&loa=' . urlencode($loa) .
712
            ((strlen($myproxyinfo) > 0) ?
713
                ('&cilogon_info=' . urlencode($myproxyinfo)) : '')
714
        );
715
    }
716
717
    /**
718
     * checkUserCode
719
     *
720
     * This method calls the 'checkUserCode' action of the OAuth 2.0 servlet
721
     * to fetch a client_id associated with a user_code entered by the end
722
     * user as part of an OAuth2 Device Authorization Grant flow. If the
723
     * servlet returns correctly (i.e., an HTTP status code of 200), this
724
     * method returns true. Check the 'status' return value to verify that
725
     * the user_code is correct. The client_id and 'original' user_code
726
     * will be available if the input user_code was valid.
727
     *
728
     * @param string $user_code The OAuth 2.0 Device Authorization Grant
729
     *        flow code entered by the user.
730
     * @return bool True if the servlet returned correctly. client_id and
731
     *         originally generated user_code will be available.
732
     *        Return false if user_code was expired or not found.
733
     */
734
    public function checkUserCode($user_code)
0 ignored issues
show
Unused Code introduced by
The parameter $user_code is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

734
    public function checkUserCode(/** @scrutinizer ignore-unused */ $user_code)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
735
    {
736
        $this->setDBServiceURL(OAUTH2_DBSERVICE_URL);
0 ignored issues
show
Bug introduced by
The constant CILogon\Service\OAUTH2_DBSERVICE_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
737
        /*
738
        return $this->call(
739
            'action=userCodeApproved' .
740
            '&user_code=' . urlencode($user_code)
741
        );
742
        */
743
        // DEBUG PLACEHOLDER - return some dummy values
744
        $this->status = 0;
745
        $this->user_code = 'ABCD-JKLM';
746
        $this->client_id = 'cilogon:/client_id/100c74e105fb9652d80817d4106b5696';
747
        return true;
748
    }
749
750
    /**
751
     * userCodeApproved
752
     *
753
     * This method calls the 'userCodeApproved' action of the OAuth 2.0
754
     * servlet to let the OA4MP code know that a user has approved a
755
     * user_code associated with a Device Authorization Grant transaction.
756
     * If the servlet returns correctly (i.e.,  an HTTP status code of 200),
757
     * this method returns true. Check the 'status' return value to verify
758
     * that the user_code is correct and is not expired.
759
     *
760
     * @param string $user_code The OAuth 2.0 Device Authorization Grant
761
     *        flow code entered by the user.
762
     * @param int $approved (Optional) =1 if the user_code has been approved
763
     *        by the user (default). =0 if the user clicks 'Cancel' to
764
     *        deny the user_code approval.
765
     * @return bool True if the servlet returned correctly. Else false.
766
     */
767
    public function userCodeApproved($user_code, $approved = 1)
0 ignored issues
show
Unused Code introduced by
The parameter $approved is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

767
    public function userCodeApproved($user_code, /** @scrutinizer ignore-unused */ $approved = 1)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $user_code is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

767
    public function userCodeApproved(/** @scrutinizer ignore-unused */ $user_code, $approved = 1)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
768
    {
769
        $this->setDBServiceURL(OAUTH2_DBSERVICE_URL);
0 ignored issues
show
Bug introduced by
The constant CILogon\Service\OAUTH2_DBSERVICE_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
770
        /*
771
        return $this->call(
772
            'action=userCodeApproved' .
773
            '&user_code=' . urlencode($user_code) .
774
            '&approved=' . $approved
775
        );
776
        */
777
        // DEBUG PLACEHOLDER - return some dummy values
778
        $this->status = 0;
779
        return true;
780
    }
781
782
    /**
783
     * call
784
     *
785
     * This method does the brunt of the work for calling the
786
     * dbService servlet.  The single parameter is a string of
787
     * 'key1=value1&key2=value2&...' containing all of the parameters
788
     * for the dbService.  If the servlet returns an HTTP status code
789
     * of 200, then this method will return true.  It parses the return
790
     * output for various 'key=value' lines and stores then in the
791
     * appropriate member variables, urldecoded of course.
792
     *
793
     * @param string $params A string containing 'key=value' pairs,
794
     *        separated by ampersands ('&') as appropriate for passing to a
795
     *        URL for a GET query.
796
     * @return bool True if the servlet returned correctly. Else false.
797
     */
798
    public function call($params)
799
    {
800
        $success = false;
801
802
        $attr_json = '';
803
        $ch = curl_init();
804
        if ($ch !== false) {
805
            $url = $this->getDBServiceURL() . '?' . $params;
806
            curl_setopt($ch, CURLOPT_URL, $url);
807
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
808
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
809
            $output = curl_exec($ch);
810
            if (curl_errno($ch)) { // Send alert on curl errors
811
                Util::sendErrorAlert(
812
                    'cUrl Error',
813
                    'cUrl Error    = ' . curl_error($ch) . "\n" .
814
                    "URL Accessed  = $url"
815
                );
816
            }
817
            if (!empty($output)) {
818
                $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
819
                if ($httpcode == 200) {
820
                    $success = true;
821
                    if (preg_match('/status=([^\r\n]+)/', $output, $match)) {
0 ignored issues
show
Bug introduced by
It seems like $output can also be of type true; however, parameter $subject of preg_match() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

821
                    if (preg_match('/status=([^\r\n]+)/', /** @scrutinizer ignore-type */ $output, $match)) {
Loading history...
822
                        $this->status = (int)(urldecode($match[1]));
823
                    }
824
                    if (preg_match('/user_uid=([^\r\n]+)/', $output, $match)) {
825
                        $this->user_uid = urldecode($match[1]);
826
                    }
827
                    if (preg_match('/remote_user=([^\r\n]+)/', $output, $match)) {
828
                        $this->remote_user = urldecode($match[1]);
829
                    }
830
                    if (preg_match('/idp=([^\r\n]+)/', $output, $match)) {
831
                        $this->idp = urldecode($match[1]);
832
                    }
833
                    if (preg_match('/idp_display_name=([^\r\n]+)/', $output, $match)) {
834
                        $this->idp_display_name = urldecode($match[1]);
835
                    }
836
                    if (preg_match('/first_name=([^\r\n]+)/', $output, $match)) {
837
                        $this->first_name = urldecode($match[1]);
838
                    }
839
                    if (preg_match('/last_name=([^\r\n]+)/', $output, $match)) {
840
                        $this->last_name = urldecode($match[1]);
841
                    }
842
                    if (preg_match('/[^_]display_name=([^\r\n]+)/', $output, $match)) {
843
                        $this->display_name = urldecode($match[1]);
844
                    }
845
                    if (preg_match('/email=([^\r\n]+)/', $output, $match)) {
846
                        $this->email = urldecode($match[1]);
847
                    }
848
                    if (preg_match('/distinguished_name=([^\r\n]+)/', $output, $match)) {
849
                        $this->distinguished_name = urldecode($match[1]);
850
                    }
851
                    if (preg_match('/eppn=([^\r\n]+)/', $output, $match)) {
852
                        $this->eppn = urldecode($match[1]);
853
                    }
854
                    if (preg_match('/eptid=([^\r\n]+)/', $output, $match)) {
855
                        $this->eptid = urldecode($match[1]);
856
                    }
857
                    if (preg_match('/open_id=([^\r\n]+)/', $output, $match)) {
858
                        $this->open_id = urldecode($match[1]);
859
                    }
860
                    if (preg_match('/oidc=([^\r\n]+)/', $output, $match)) {
861
                        $this->oidc = urldecode($match[1]);
862
                    }
863
                    if (preg_match('/subject_id=([^\r\n]+)/', $output, $match)) {
864
                        $this->subject_id = urldecode($match[1]);
865
                    }
866
                    if (preg_match('/pairwise_id=([^\r\n]+)/', $output, $match)) {
867
                        $this->pairwise_id = urldecode($match[1]);
868
                    }
869
                    if (preg_match('/affiliation=([^\r\n]+)/', $output, $match)) {
870
                        $this->affiliation = urldecode($match[1]);
871
                    }
872
                    if (preg_match('/ou=([^\r\n]+)/', $output, $match)) {
873
                        $this->ou = urldecode($match[1]);
874
                    }
875
                    if (preg_match('/attr_json=([^\r\n]+)/', $output, $match)) {
876
                        // Decode $attr_json into class members later
877
                        $attr_json = urldecode($match[1]);
878
                    }
879
                    if (preg_match('/serial_string=([^\r\n]+)/', $output, $match)) {
880
                        $this->serial_string = urldecode($match[1]);
881
                    }
882
                    if (preg_match('/create_time=([^\r\n]+)/', $output, $match)) {
883
                        $this->create_time = urldecode($match[1]);
884
                    }
885
                    if (preg_match('/oauth_token=([^\r\n]+)/', $output, $match)) {
886
                        $this->oauth_token = urldecode($match[1]);
887
                    }
888
                    if (preg_match('/cilogon_callback=([^\r\n]+)/', $output, $match)) {
889
                        $this->cilogon_callback = urldecode($match[1]);
890
                    }
891
                    if (preg_match('/cilogon_success=([^\r\n]+)/', $output, $match)) {
892
                        $this->cilogon_success = urldecode($match[1]);
893
                    }
894
                    if (preg_match('/cilogon_failure=([^\r\n]+)/', $output, $match)) {
895
                        $this->cilogon_failure = urldecode($match[1]);
896
                    }
897
                    if (preg_match('/cilogon_portal_name=([^\r\n]+)/', $output, $match)) {
898
                        $this->cilogon_portal_name = urldecode($match[1]);
899
                    }
900
                    if (preg_match('/user_code=([^\r\n]+)/', $output, $match)) {
901
                        $this->user_code = urldecode($match[1]);
902
                    }
903
                    if (preg_match('/client_id=([^\r\n]+)/', $output, $match)) {
904
                        $this->client_id = urldecode($match[1]);
905
                    }
906
                    if (preg_match_all('/idp_uid=([^\r\n]+)/', $output, $match)) {
907
                        foreach ($match[1] as $value) {
908
                            $this->idp_uids[] = urldecode($value);
909
                        }
910
                    }
911
                }
912
            }
913
            curl_close($ch);
914
        }
915
916
        // Convert $attr_json into array and extract elements into class members
917
        if (strlen($attr_json) > 0) {
918
            $attr_arr = json_decode($attr_json, true);
919
            if (!is_null($attr_arr)) {
920
                if (isset($attr_arr['member_of'])) {
921
                    $this->member_of = $attr_arr['member_of'];
922
                }
923
                if (isset($attr_arr['acr'])) {
924
                    $this->acr = $attr_arr['acr'];
925
                }
926
                if (isset($attr_arr['amr'])) {
927
                    $this->amr = $attr_arr['amr'];
928
                }
929
                if (isset($attr_arr['entitlement'])) {
930
                    $this->entitlement = $attr_arr['entitlement'];
931
                }
932
                if (isset($attr_arr['itrustuin'])) {
933
                    $this->itrustuin = $attr_arr['itrustuin'];
934
                }
935
            }
936
        }
937
938
        return $success;
939
    }
940
941
    /**
942
     * dump
943
     *
944
     * This is a convenience method which prints out all of the
945
     * non-null / non-empty member variables to stdout.
946
     */
947
    public function dump()
948
    {
949
        if (!is_null($this->status)) {
950
            echo "status=$this->status (" .
951
            (string)(array_search($this->status, static::$STATUS)) . ")\n";
952
        }
953
        if (!is_null($this->user_uid)) {
954
            echo "user_uid=$this->user_uid\n";
955
        }
956
        if (!is_null($this->remote_user)) {
957
            echo "remote_user=$this->remote_user\n";
958
        }
959
        if (!is_null($this->idp)) {
960
            echo "idp=$this->idp\n";
961
        }
962
        if (!is_null($this->idp_display_name)) {
963
            echo "idp_display_name=$this->idp_display_name\n";
964
        }
965
        if (!is_null($this->first_name)) {
966
            echo "first_name=$this->first_name\n";
967
        }
968
        if (!is_null($this->last_name)) {
969
            echo "last_name=$this->last_name\n";
970
        }
971
        if (!is_null($this->display_name)) {
972
            echo "display_name=$this->display_name\n";
973
        }
974
        if (!is_null($this->email)) {
975
            echo "email=$this->email\n";
976
        }
977
        if (!is_null($this->distinguished_name)) {
978
            echo "distinguished_name=$this->distinguished_name\n";
979
        }
980
        if (!is_null($this->eppn)) {
981
            echo "eppn=$this->eppn\n";
982
        }
983
        if (!is_null($this->eptid)) {
984
            echo "eptid=$this->eptid\n";
985
        }
986
        if (!is_null($this->open_id)) {
987
            echo "open_id=$this->open_id\n";
988
        }
989
        if (!is_null($this->oidc)) {
990
            echo "oidc=$this->oidc\n";
991
        }
992
        if (!is_null($this->affiliation)) {
993
            echo "affiliation=$this->affiliation\n";
994
        }
995
        if (!is_null($this->ou)) {
996
            echo "ou=$this->ou\n";
997
        }
998
        if (!is_null($this->member_of)) {
999
            echo "member_of=$this->member_of\n";
1000
        }
1001
        if (!is_null($this->acr)) {
1002
            echo "acr=$this->acr\n";
1003
        }
1004
        if (!is_null($this->amr)) {
1005
            echo "amr=$this->amr\n";
1006
        }
1007
        if (!is_null($this->entitlement)) {
1008
            echo "entitlement=$this->entitlement\n";
1009
        }
1010
        if (!is_null($this->itrustuin)) {
1011
            echo "itrustuin=$this->itrustuin\n";
1012
        }
1013
        if (!is_null($this->subject_id)) {
1014
            echo "subject_id=$this->subject_id\n";
1015
        }
1016
        if (!is_null($this->pairwise_id)) {
1017
            echo "pairwise_id=$this->pairwise_id\n";
1018
        }
1019
        if (!is_null($this->serial_string)) {
1020
            echo "serial_string=$this->serial_string\n";
1021
        }
1022
        if (!is_null($this->create_time)) {
1023
            echo "create_time=$this->create_time\n";
1024
        }
1025
        if (!is_null($this->oauth_token)) {
1026
            echo "oauth_token=$this->oauth_token\n";
1027
        }
1028
        if (!is_null($this->cilogon_callback)) {
1029
            echo "cilogon_callback=$this->cilogon_callback\n";
1030
        }
1031
        if (!is_null($this->cilogon_success)) {
1032
            echo "cilogon_success=$this->cilogon_success\n";
1033
        }
1034
        if (!is_null($this->cilogon_failure)) {
1035
            echo "cilogon_failure=$this->cilogon_failure\n";
1036
        }
1037
        if (!is_null($this->cilogon_portal_name)) {
1038
            echo "cilogon_portal_name=$this->cilogon_portal_name\n";
1039
        }
1040
        if (!is_null($this->user_code)) {
1041
            echo "user_code=$this->user_code\n";
1042
        }
1043
        if (!is_null($this->client_id)) {
1044
            echo "client_id=$this->client_id\n";
1045
        }
1046
        if (count($this->idp_uids) > 0) {
1047
            uasort($this->idp_uids, 'strcasecmp');
1048
            echo "idp_uids={\n";
1049
            foreach ($this->idp_uids as $value) {
1050
                echo "    $value\n";
1051
            }
1052
            echo "}\n";
1053
        }
1054
    }
1055
}
1056