LaravelSSOBroker::redirect()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
nc 3
nop 3
1
<?php
2
3
namespace Zefy\LaravelSSO;
4
5
use Illuminate\Support\Facades\Cookie;
6
use Zefy\LaravelSSO\Exceptions\MissingConfigurationException;
7
use Zefy\SimpleSSO\SSOBroker;
8
use GuzzleHttp;
9
10
/**
11
 * Class SSOBroker. This class is only a skeleton.
12
 * First of all, you need to implement abstract functions in your own class.
13
 * Secondly, you should create a page which will be your SSO server.
14
 *
15
 * @package Zefy\SimpleSSO
16
 */
17
class LaravelSSOBroker extends SSOBroker
18
{
19
    /**
20
     * Generate request url.
21
     *
22
     * @param string $command
23
     * @param array $parameters
24
     *
25
     * @return string
26
     */
27
    protected function generateCommandUrl(string $command, array $parameters = [])
28
    {
29
        $query = '';
30
        if (!empty($parameters)) {
31
            $query = '?' . http_build_query($parameters);
32
        }
33
34
        return $this->ssoServerUrl . '/api/sso/' . $command . $query;
35
    }
36
37
    /**
38
     * Set base class options (sso server url, broker name and secret, etc).
39
     *
40
     * @return void
41
     *
42
     * @throws MissingConfigurationException
43
     */
44
    protected function setOptions()
45
    {
46
        $this->ssoServerUrl = config('laravel-sso.serverUrl', null);
47
        $this->brokerName = config('laravel-sso.brokerName', null);
48
        $this->brokerSecret = config('laravel-sso.brokerSecret', null);
49
50
        if (!$this->ssoServerUrl || !$this->brokerName || !$this->brokerSecret) {
51
            throw new MissingConfigurationException('Missing configuration values.');
52
        }
53
    }
54
55
    /**
56
     * Save unique client token to cookie.
57
     *
58
     * @return void
59
     */
60
    protected function saveToken()
61
    {
62
        if (isset($this->token) && $this->token) {
63
            return;
64
        }
65
66
        if ($this->token = Cookie::get($this->getCookieName(), null)) {
67
            return;
68
        }
69
70
        // If cookie token doesn't exist, we need to create it with unique token...
71
        $this->token = str_random(40);
72
        Cookie::queue(Cookie::make($this->getCookieName(), $this->token, 60));
0 ignored issues
show
Bug introduced by
Illuminate\Support\Facad...me(), $this->token, 60) of type Symfony\Component\HttpFoundation\Cookie is incompatible with the type array expected by parameter $parameters of Illuminate\Cookie\CookieJar::queue(). ( Ignorable by Annotation )

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

72
        Cookie::queue(/** @scrutinizer ignore-type */ Cookie::make($this->getCookieName(), $this->token, 60));
Loading history...
73
74
        // ... and attach it to broker session in SSO server.
75
        $this->attach();
76
    }
77
78
    /**
79
     * Delete saved unique client token.
80
     *
81
     * @return void
82
     */
83
    protected function deleteToken()
84
    {
85
        $this->token = null;
86
        Cookie::forget($this->getCookieName());
87
    }
88
89
    /**
90
     * Make request to SSO server.
91
     *
92
     * @param string $method Request method 'post' or 'get'.
93
     * @param string $command Request command name.
94
     * @param array $parameters Parameters for URL query string if GET request and form parameters if it's POST request.
95
     *
96
     * @return array
97
     */
98
    protected function makeRequest(string $method, string $command, array $parameters = [])
99
    {
100
        $commandUrl = $this->generateCommandUrl($command);
101
102
        $headers = [
103
            'Accept' => 'application/json',
104
            'Authorization' => 'Bearer '. $this->getSessionId(),
105
        ];
106
107
        switch ($method) {
108
            case 'POST':
109
                $body = ['form_params' => $parameters];
110
                break;
111
            case 'GET':
112
                $body = ['query' => $parameters];
113
                break;
114
            default:
115
                $body = [];
116
                break;
117
        }
118
119
        $client = new GuzzleHttp\Client;
120
        $response = $client->request($method, $commandUrl, $body + ['headers' => $headers]);
121
122
        return json_decode($response->getBody(), true);
123
    }
124
125
    /**
126
     * Redirect client to specified url.
127
     *
128
     * @param string $url URL to be redirected.
129
     * @param array $parameters HTTP query string.
130
     * @param int $httpResponseCode HTTP response code for redirection.
131
     *
132
     * @return void
133
     */
134
    protected function redirect(string $url, array $parameters = [], int $httpResponseCode = 307)
135
    {
136
        $query = '';
137
        // Making URL query string if parameters given.
138
        if (!empty($parameters)) {
139
            $query = '?';
140
141
            if (parse_url($url, PHP_URL_QUERY)) {
142
                $query = '&';
143
            }
144
145
            $query .= http_build_query($parameters);
146
        }
147
148
        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

148
        app()->/** @scrutinizer ignore-call */ abort($httpResponseCode, '', ['Location' => $url . $query]);
Loading history...
149
    }
150
151
    /**
152
     * Getting current url which can be used as return to url.
153
     *
154
     * @return string
155
     */
156
    protected function getCurrentUrl()
157
    {
158
        return url()->full();
159
    }
160
161
    /**
162
     * Cookie name in which we save unique client token.
163
     *
164
     * @return string
165
     */
166
    protected function getCookieName()
167
    {
168
        // Cookie name based on broker's name because there can be some brokers on same domain
169
        // and we need to prevent duplications.
170
        return 'sso_token_' . preg_replace('/[_\W]+/', '_', strtolower($this->brokerName));
171
    }
172
}
173