Passed
Pull Request — 2.2 (#20357)
by Wilmer
13:33 queued 05:55
created

CompositeAuth::challenge()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @link https://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license https://www.yiiframework.com/license/
6
 */
7
8
namespace yii\filters\auth;
9
10
use Yii;
11
use yii\base\ActionFilter;
12
use yii\base\Controller;
13
use yii\base\InvalidConfigException;
14
15
/**
16
 * CompositeAuth is an action filter that supports multiple authentication methods at the same time.
17
 *
18
 * The authentication methods contained by CompositeAuth are configured via [[authMethods]],
19
 * which is a list of supported authentication class configurations.
20
 *
21
 * The following example shows how to support three authentication methods:
22
 *
23
 * ```php
24
 * public function behaviors()
25
 * {
26
 *     return [
27
 *         'compositeAuth' => [
28
 *             'class' => \yii\filters\auth\CompositeAuth::class,
29
 *             'authMethods' => [
30
 *                 \yii\filters\auth\HttpBasicAuth::class,
31
 *                 \yii\filters\auth\QueryParamAuth::class,
32
 *             ],
33
 *         ],
34
 *     ];
35
 * }
36
 * ```
37
 *
38
 * @author Qiang Xue <[email protected]>
39
 * @since 2.0
40
 */
41
class CompositeAuth extends AuthMethod
42
{
43
    /**
44
     * @var array the supported authentication methods. This property should take a list of supported
45
     * authentication methods, each represented by an authentication class or configuration.
46
     *
47
     * If this property is empty, no authentication will be performed.
48
     *
49
     * Note that an auth method class must implement the [[\yii\filters\auth\AuthInterface]] interface.
50
     */
51
    public $authMethods = [];
52
53
54
    /**
55
     * {@inheritdoc}
56
     */
57 13
    public function beforeAction($action)
58
    {
59 13
        return empty($this->authMethods) ? true : parent::beforeAction($action);
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65 12
    public function authenticate($user, $request, $response)
66
    {
67 12
        foreach ($this->authMethods as $i => $auth) {
68 12
            if (!$auth instanceof AuthInterface) {
69 12
                $this->authMethods[$i] = $auth = Yii::createObject($auth);
70 12
                if (!$auth instanceof AuthInterface) {
71
                    throw new InvalidConfigException(get_class($auth) . ' must implement yii\filters\auth\AuthInterface');
72
                }
73
            }
74
75
            if (
76 12
                $this->owner instanceof Controller
77
                && (
78 12
                    !isset($this->owner->action)
79 12
                    || (
80 12
                        $auth instanceof ActionFilter
81 12
                        && !$auth->isActive($this->owner->action)
82 12
                    )
83
                )
84
            ) {
85 2
                continue;
86
            }
87
88 12
            $authUser = $auth->user;
0 ignored issues
show
Bug introduced by
Accessing user on the interface yii\filters\auth\AuthInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
89 12
            if ($authUser != null && !$authUser instanceof \yii\web\User) {
90
                throw new InvalidConfigException(get_class($authUser) . ' must implement yii\web\User');
91 12
            } elseif ($authUser != null) {
92
                $user = $authUser;
93
            }
94
95 12
            $authRequest = $auth->request;
0 ignored issues
show
Bug introduced by
Accessing request on the interface yii\filters\auth\AuthInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
96 12
            if ($authRequest != null && !$authRequest instanceof \yii\web\Request) {
97
                throw new InvalidConfigException(get_class($authRequest) . ' must implement yii\web\Request');
98 12
            } elseif ($authRequest != null) {
99
                $request = $authRequest;
100
            }
101
102 12
            $authResponse = $auth->response;
0 ignored issues
show
Bug introduced by
Accessing response on the interface yii\filters\auth\AuthInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
103 12
            if ($authResponse != null && !$authResponse instanceof \yii\web\Response) {
104
                throw new InvalidConfigException(get_class($authResponse) . ' must implement yii\web\Response');
105 12
            } elseif ($authResponse != null) {
106
                $response = $authResponse;
107
            }
108
109 12
            $identity = $auth->authenticate($user, $request, $response);
110 11
            if ($identity !== null) {
111 7
                return $identity;
112
            }
113
        }
114
115 4
        return null;
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121 3
    public function challenge($response)
122
    {
123 3
        foreach ($this->authMethods as $method) {
124
            /** @var AuthInterface $method */
125 3
            $method->challenge($response);
126
        }
127
    }
128
}
129