Passed
Pull Request — master (#18)
by
unknown
03:06
created

LaravelSSOServer::getBrokerDetail()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Zefy\LaravelSSO;
4
5
use Illuminate\Database\Eloquent\ModelNotFoundException;
6
use Illuminate\Support\Facades\Auth;
7
use Illuminate\Support\Facades\Cache;
8
use Illuminate\Support\Facades\Session;
9
use Zefy\SimpleSSO\SSOServer;
10
use Zefy\LaravelSSO\Resources\UserResource;
11
12
class LaravelSSOServer extends SSOServer
13
{
14
    /**
15
     * Redirect to provided URL with query string.
16
     *
17
     * If $url is null, redirect to url which given in 'return_url'.
18
     *
19
     * @param string|null $url URL to be redirected.
20
     * @param array $parameters HTTP query string.
21
     * @param int $httpResponseCode HTTP response code for redirection.
22
     *
23
     * @return void
24
     */
25
    protected function redirect(?string $url = null, array $parameters = [], int $httpResponseCode = 307)
26
    {
27
        if (!$url) {
28
            $url = urldecode(request()->get('return_url', null));
29
        }
30
31
        $query = '';
32
        // Making URL query string if parameters given.
33
        if (!empty($parameters)) {
34
            $query = '?';
35
36
            if (parse_url($url, PHP_URL_QUERY)) {
37
                $query = '&';
38
            }
39
40
            $query .= http_build_query($parameters);
41
        }
42
43
        app()->abort($httpResponseCode, '', ['Location' => $url . $query]);
0 ignored issues
show
introduced by
The method abort() does not exist on Illuminate\Container\Container. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

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

43
        app()->/** @scrutinizer ignore-call */ abort($httpResponseCode, '', ['Location' => $url . $query]);
Loading history...
44
    }
45
46
    /**
47
     * Returning json response for the broker.
48
     *
49
     * @param null|array $response Response array which will be encoded to json.
50
     * @param int $httpResponseCode HTTP response code.
51
     *
52
     * @return string
53
     */
54
    protected function returnJson(?array $response = null, int $httpResponseCode = 200)
55
    {
56
        return response()->json($response, $httpResponseCode);
57
    }
58
59
    /**
60
     * Authenticate using user credentials
61
     *
62
     * @param string $username
63
     * @param string $password
64
     *
65
     * @return bool
66
     */
67
    protected function authenticate(string $username, string $password)
68
    {
69
        if (!Auth::attempt(['email' => $username, 'password' => $password])) {
70
            return false;
71
        }
72
73
        // After authentication Laravel will change session id, but we need to keep
74
        // this the same because this session id can be already attached to other brokers.
75
        $sessionId = $this->getBrokerSessionId();
76
        $savedSessionId = $this->getBrokerSessionData($sessionId);
0 ignored issues
show
Bug introduced by
It seems like $sessionId can also be of type null; however, parameter $brokerSessionId of Zefy\LaravelSSO\LaravelS...:getBrokerSessionData() 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

76
        $savedSessionId = $this->getBrokerSessionData(/** @scrutinizer ignore-type */ $sessionId);
Loading history...
77
        $this->startSession($savedSessionId);
0 ignored issues
show
Bug introduced by
It seems like $savedSessionId can also be of type null; however, parameter $sessionId of Zefy\LaravelSSO\LaravelSSOServer::startSession() 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

77
        $this->startSession(/** @scrutinizer ignore-type */ $savedSessionId);
Loading history...
78
79
        return true;
80
    }
81
82
    /**
83
     * Get the secret key and other info of a broker
84
     *
85
     * @param string $brokerId
86
     *
87
     * @return null|array
88
     */
89
    protected function getBrokerInfo(string $brokerId)
90
    {
91
        try {
92
            $broker = config('laravel-sso.brokersModel')::where('name', $brokerId)->firstOrFail();
93
        } catch (ModelNotFoundException $e) {
94
            return null;
95
        }
96
97
        return $broker;
98
    }
99
100
    /**
101
     * Check for User Auth with Broker Application.
102
     *
103
     * @return boolean
104
     */
105
    protected function checkBrokerUserAuthentication()
106
    {
107
        $userInfo = $this->userInfo();
108
        $broker = $this->getBrokerDetail();
109
        if(!empty($userInfo->id) && !empty($broker)) {
0 ignored issues
show
Bug introduced by
The property id does not exist on string.
Loading history...
110
            $brokerUser = config('laravel-sso.brokersUserModel')::where('user_id', $userInfo->id)->where('broker_id', $broker->id)->first();
111
            if(empty($brokerUser)) {
112
                return false;
113
            }
114
        }
115
        return true;
116
    }
117
118
    /**
119
     * Check for the User authorization with application and return error or userinfo
120
     *
121
     * @return string
122
     */
123
    public function checkUserApplicationAuth()
124
    {
125
        try {
126
            if(empty($this->checkBrokerUserAuthentication())) {
127
                $this->fail('User authorization failed with application.');
128
            }
129
        } catch (SSOServerException $e) {
0 ignored issues
show
Bug introduced by
The type Zefy\LaravelSSO\SSOServerException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
130
            return $this->returnJson(['error' => $e->getMessage()]);
131
        }
132
        return $this->userInfo();
133
    }
134
135
    /**
136
     * Returning the broker details
137
     *
138
     * @return string
139
     */
140
    public function getBrokerDetail()
141
    {
142
        return $this->getBrokerInfo($this->brokerId);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getBrokerInfo($this->brokerId) also could return the type array which is incompatible with the documented return type string.
Loading history...
143
    }
144
145
    /**
146
     * Get the information about a user
147
     *
148
     * @param string $username
149
     *
150
     * @return array|object|null
151
     */
152
    protected function getUserInfo(string $username)
153
    {
154
        try {
155
            $user = config('laravel-sso.usersModel')::where('email', $username)->firstOrFail();
156
        } catch (ModelNotFoundException $e) {
157
            return null;
158
        }
159
160
        return $user;
161
    }
162
163
    /**
164
     * Returning user info for broker. Should return json or something like that.
165
     *
166
     * @param array|object $user Can be user object or array.
167
     *
168
     * @return array|object|UserResource
169
     */
170
    protected function returnUserInfo($user)
171
    {
172
        return new UserResource($user);
173
    }
174
175
    /**
176
     * Return session id sent from broker.
177
     *
178
     * @return null|string
179
     */
180
    protected function getBrokerSessionId()
181
    {
182
        $authorization = request()->header('Authorization', null);
183
        if ($authorization &&  strpos($authorization, 'Bearer') === 0) {
0 ignored issues
show
Bug introduced by
It seems like $authorization can also be of type array; however, parameter $haystack of strpos() 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

183
        if ($authorization &&  strpos(/** @scrutinizer ignore-type */ $authorization, 'Bearer') === 0) {
Loading history...
184
            return substr($authorization, 7);
0 ignored issues
show
Bug introduced by
It seems like $authorization can also be of type array; however, parameter $string of substr() 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

184
            return substr(/** @scrutinizer ignore-type */ $authorization, 7);
Loading history...
185
        }
186
187
        return null;
188
    }
189
190
    /**
191
     * Start new session when user visits server.
192
     *
193
     * @return void
194
     */
195
    protected function startUserSession()
196
    {
197
        // Session must be started by middleware.
198
    }
199
200
    /**
201
     * Set session data
202
     *
203
     * @param string $key
204
     * @param null|string $value
205
     *
206
     * @return void
207
     */
208
    protected function setSessionData(string $key, ?string $value = null)
209
    {
210
        if (!$value) {
211
            Session::forget($key);
212
            return;
213
        }
214
215
        Session::put($key, $value);
216
    }
217
218
    /**
219
     * Get data saved in session.
220
     *
221
     * @param string $key
222
     *
223
     * @return string
224
     */
225
    protected function getSessionData(string $key)
226
    {
227
        if ($key === 'id') {
228
            return Session::getId();
229
        }
230
231
        return Session::get($key, null);
232
    }
233
234
    /**
235
     * Start new session with specific session id.
236
     *
237
     * @param $sessionId
238
     *
239
     * @return void
240
     */
241
    protected function startSession(string $sessionId)
242
    {
243
        Session::setId($sessionId);
244
        Session::start();
245
    }
246
247
    /**
248
     * Save broker session data to cache.
249
     *
250
     * @param string $brokerSessionId
251
     * @param string $sessionData
252
     *
253
     * @return void
254
     */
255
    protected function saveBrokerSessionData(string $brokerSessionId, string $sessionData)
256
    {
257
        Cache::put('broker_session:' . $brokerSessionId, $sessionData, now()->addHour());
258
    }
259
260
    /**
261
     * Get broker session data from cache.
262
     *
263
     * @param string $brokerSessionId
264
     *
265
     * @return null|string
266
     */
267
    protected function getBrokerSessionData(string $brokerSessionId)
268
    {
269
        return Cache::get('broker_session:' . $brokerSessionId);
270
    }
271
}
272