Completed
Push — master ( a51466...8daf75 )
by Raffael
02:47
created

Oidc   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 2

Importance

Changes 0
Metric Value
wmc 14
lcom 3
cbo 2
dl 0
loc 141
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A setOptions() 0 12 3
B authenticate() 0 27 3
A getDiscoveryUrl() 0 4 1
A getDiscoveryDocument() 0 19 4
A verifyToken() 0 16 2
A getAttributes() 0 4 1
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * Micro
6
 *
7
 * @copyright Copyright (c) 2017 gyselroth GmbH (https://gyselroth.com)
8
 * @license   MIT https://opensource.org/licenses/MIT
9
 */
10
11
namespace Micro\Auth\Adapter;
12
13
use \Psr\Log\LoggerInterface as Logger;
14
use \Micro\Auth\Exception;
15
16
class Oidc extends AbstractAdapter
17
{
18
    /**
19
     * OpenID-connect discovery path
20
     */
21
    CONST DISCOVERY_PATH = '/.well-known/openid-configuration';
22
23
24
    /**
25
     * OpenID-connect provider url
26
     *
27
     * @var string
28
     */
29
    protected $provider_url = 'https://oidc.example.org';
30
31
32
    /**
33
     * Set options
34
     *
35
     * @param   Iterable $config
36
     * @return  AdapterInterface
37
     */
38
    public function setOptions(?Iterable $config=null): AdapterInterface
39
    {
40
        if ($config === null) {
41
            return $this;
42
        }
43
44
        if(isset($config['provider_url'])) {
45
            $this->discovery_url = (string)$config['provider_url'];
0 ignored issues
show
Bug introduced by
The property discovery_url does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
46
        }
47
48
        return  parent::setOptions($config);        
49
    }
50
51
52
    /**
53
     * Authenticate
54
     *
55
     * @return bool
56
     */
57
    public function authenticate(): bool
58
    {
59
        if (!isset($_SERVER['HTTP_AUTHORIZATION'])) {
60
            $this->logger->debug('skip auth adapter ['.get_class($this).'], no http authorization header or access_token param found', [
0 ignored issues
show
Bug introduced by
The property logger does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
61
                'category' => get_class($this)
62
            ]);
63
        
64
            return false;
65
        } else {
66
            $header = $_SERVER['HTTP_AUTHORIZATION'];
67
            $parts  = explode(' ', $header);
68
            
69
            if ($parts[0] == 'Bearer') {
70
                $this->logger->debug('found http bearer authorization header', [
71
                    'category' => get_class($this)
72
                ]);
73
                
74
                return $this->tokenAuth($parts[1]);
0 ignored issues
show
Bug introduced by
The method tokenAuth() does not seem to exist on object<Micro\Auth\Adapter\Oidc>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
75
            } else {
76
                $this->logger->debug('http authorization header contains no bearer string or invalid authentication string', [
77
                    'category' => get_class($this)
78
                ]);
79
            
80
                return false;
81
            }
82
        }
83
    }
84
85
    
86
    /**
87
     * Get discovery url
88
     *
89
     * @return string 
90
     */
91
    protected function getDiscoveryUrl(): string
92
    {
93
        return $this->provider_url.self::DISCOVERY_URL;    
94
    }
95
96
97
    /**
98
     * Get discovery document
99
     *
100
     * @return array
101
     */    
102
    protected function getDiscoveryDocument(): array
103
    {
104
        if($apc = extension_loaded('apc') && apc_exists($this->provider_url)) {
0 ignored issues
show
Comprehensibility introduced by
Consider adding parentheses for clarity. Current Interpretation: $apc = (extension_loaded...s($this->provider_url)), Probably Intended Meaning: ($apc = extension_loaded...ts($this->provider_url)
Loading history...
105
            return apc_get($this->provider_url);
106
        } else {
107
            $ch = curl_init();
108
            curl_setopt($ch, CURLOPT_URL, $this->getDiscoveryUrl());
109
            $result = curl_exec($ch);
110
            curl_close($ch);
111
112
            $discovery = json_decode($result, true);
113
            
114
            if($apc === true) {
115
                apc_store($this->provider_url, $discovery);
116
            }
117
118
            return $discovery;
119
        }
120
    }
121
122
123
    /**
124
     * Token verification
125
     *
126
     * @param   string $token
127
     * @return  bool
128
     */
129
    protected function verifyToken(string $token): bool
130
    {
131
        $discovery = $this->getDiscoverDocument();
0 ignored issues
show
Bug introduced by
The method getDiscoverDocument() does not exist on Micro\Auth\Adapter\Oidc. Did you maybe mean getDiscoveryDocument()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
132
        if(!(isset($discovery['authorization_endpoint']))) {
133
            throw new Exception('authorization_endpoint could not be determained');
134
        }
135
136
        $ch = curl_init();
137
        curl_setopt($ch, CURLOPT_URL, $discovery['authorization_endpoint'].'?token='.$token);
138
        $result = curl_exec($ch);
139
        curl_close($ch);
140
        $response = json_decode($result, true);
141
142
        $this->identifier = $response['id'];
143
        return true;
144
    }
145
146
147
    /**
148
     * Get attributes
149
     * 
150
     * @return array
151
     */
152
    public function getAttributes(): array
153
    {
154
        return [];
155
    }
156
}
157