SAMLMiddleware   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 24
c 1
b 0
f 0
dl 0
loc 94
rs 10
wmc 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A checkExcludedUrl() 0 13 3
A process() 0 28 5
A isEnabled() 0 3 1
A getExcludedUrls() 0 3 1
1
<?php
2
namespace SilverStripe\SAML\Middleware;
3
4
use SilverStripe\Control\Controller;
5
use SilverStripe\Control\Director;
6
use SilverStripe\Control\HTTPRequest;
7
use SilverStripe\Control\Middleware\HTTPMiddleware;
8
use SilverStripe\Core\Config\Configurable;
9
use SilverStripe\Core\Injector\Injector;
10
use SilverStripe\SAML\Helpers\SAMLHelper;
11
use SilverStripe\Security\Security;
12
13
class SAMLMiddleware implements HTTPMiddleware
14
{
15
    use Configurable;
16
17
    /**
18
     * @var bool Whether this middleware is enabled or not
19
     * @config
20
     */
21
    private static $enabled = false;
22
23
    /**
24
     * @var array A list of URLs to be excluded from processing via this middleware. These URLs are passed through
25
     * preg_match(), so regular expressions are acceptable. The default URLs include:
26
     * - Any URL under Security/
27
     * - Any URL under saml/
28
     */
29
    private static $excluded_urls = [
30
        '/^Security/i',
31
        '/^saml/i'
32
    ];
33
34
    /**
35
     * Processes the given request. If the middleware is enabled, the URL pattern does not match an exclusion pattern,
36
     * and the user is not logged in, then they are shipped off to the SAML Identity Provider (IdP) to authenticate.
37
     *
38
     * Note: This middleware is always included in all requests, but is not enabled by default.
39
     *
40
     * @param HTTPRequest $request
41
     * @param callable $delegate
42
     * @return \SilverStripe\Control\HTTPResponse|void
43
     */
44
    public function process(HTTPRequest $request, callable $delegate)
45
    {
46
        // If the middleware isn't enabled, immediately stop processing and pass on to other delegates
47
        if (!$this->isEnabled()) {
48
            return $delegate($request);
49
        }
50
51
        // Check the URL to see if it matches an exclusion rule - if so, stop processing and pass on to other delegates
52
        if ($this->checkExcludedUrl($request)) {
53
            return $delegate($request);
54
        }
55
56
        // Don't redirect on CLI
57
        if (Director::is_cli()) {
58
            return $delegate($request);
59
        }
60
61
        // If the user is already logged in, stop processing and pass on to other delegates
62
        if (Security::getCurrentUser()) {
63
            return $delegate($request);
64
        }
65
66
        // If we get this far, then the middleware is enabled, doensdoesn't match an exclusion rule, and the user is not
67
        // logged in. Therefore, we should redirect them to the identity provider to log in, and set the back URL to the
68
        // current URL for when they successfully return
69
        /** @var SAMLHelper $helper */
70
        $helper = Injector::inst()->get(SAMLHelper::class);
71
        $helper->redirect(null, $request, $request->getURL(true));
72
    }
73
74
    /**
75
     * @param HTTPRequest $request The current request
76
     * @return bool true if the current URL should be excluded from having this middleware run
77
     */
78
    protected function checkExcludedUrl(HTTPRequest $request)
79
    {
80
        $urls = $this->getExcludedUrls();
81
        $currentRelativeUrl = $request->getURL(true);
82
83
        foreach ($urls as $pattern) {
84
            if (preg_match($pattern, $currentRelativeUrl)) {
85
                return true;
86
            }
87
        }
88
89
        // If no URLs match, then the current URL isn't excluded and should be processed
90
        return false;
91
    }
92
93
    /**
94
     * @return array The list of all excluded URLs
95
     */
96
    protected function getExcludedUrls()
97
    {
98
        return $this->config()->excluded_urls;
99
    }
100
101
    /**
102
     * @return bool true if this middleware is enabled, false if it's not enabled
103
     */
104
    protected function isEnabled()
105
    {
106
        return $this->config()->enabled;
107
    }
108
}
109