_create_oauth_service_client()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
c 1
b 0
f 0
dl 0
loc 13
ccs 9
cts 9
cp 1
rs 10
cc 3
nc 3
nop 2
crap 3
1
<?php
2
/**
3
 * This file is part of the tiqr project.
4
 * 
5
 * The tiqr project aims to provide an open implementation for 
6
 * authentication using mobile devices. It was initiated by 
7
 * SURFnet and developed by Egeniq.
8
 *
9
 * More information: http://www.tiqr.org
10
 *
11
 * @author Ivo Jansch <[email protected]>
12
 * 
13
 * @package tiqr
14
 *
15
 * @license New BSD License - See LICENSE file for details.
16
 *
17
 * @copyright (C) 2010-2012 SURFnet BV
18
 */
19
20
use Psr\Log\LoggerInterface;
21
22
/**
23
 * Class implementing a factory to retrieve user secrets.
24
 *
25
 * @author lineke
26
 */
27
class Tiqr_UserSecretStorage
28
{
29
    /**
30
     * Get a secret storage of a certain type
31
     *
32
     * @param String $type The type of storage to create. Supported
33
     *                     types are 'file', 'pdo' or 'oathserviceclient'.
34
     * @param LoggerInterface $logger The logger to use.
35
     * @param array $options The options to pass to the storage instance.
36
     *                       This contains the configuration options for the UserSecretStorage
37
     *                       specified in the $type parameter.
38
     *                       See the documentation in the UserSecretStorage subdirectory for options
39
     *                       per type.
40
     *
41
     *                       For the file and pdo UserSecretStorage types the encryption and decryption options
42
     *                       are used to encrypt the secrets. These are ignored when the oathserviceclient
43
     *                       is used.
44
     *
45
     *                       encryption:
46
     *                       The $options array can contain an 'encryption' key that specifies
47
     *                       the encryption method and configuration to use for encrypting the secrets.
48
     *                       The encryption method is specified in the 'type' key. Available types are:
49
     *                       - 'plain' : (default) no encryption
50
     *                       - 'dummy' : alias for 'plain'
51
     *                       - 'openssl: Uses the openssl extension to encrypt the secrets.
52
     *                       - A custom encryption class can be used by specifying the class name. The custom encryption
53
     *                         class must implement the Tiqr_UserSecretStorage_Encryption_Interface
54
     *                       The encryption options are documented in the UserSecretStorage/Encryption/
55
     *                       subdirectory.
56
     *
57
     *                       decryption:
58
     *                       The $options array can contain a 'decryption' kay that lists additional
59
     *                       encryption methods and their configuration to use for decrypting the secrets only.
60
     *                       The format is slightly different from the encryption configuration to allow
61
     *                       multiple decryption methods to be specified.
62
     *                       The decryption configuration is optional. If not specified it defaults to the
63
     *                       'plain' encryption method.
64
     *                       Note that all decryption methods specified in the 'decryption' configuration
65
     *                       must have a unique type as returned by the encryption method's
66
     *                       Tiqr_UserSecretStorage_Encryption_Interface::get_type() implementation
67
     *
68
     * The $options array has the following structure:
69
     * array(
70
     *    // UserSecretStorage configuration
71
     *    '<option_1_for_usersecretstorage>' => '<value>',
72
     *    '<option_2_for_usersecretstorage>' => '<value>',
73
     *
74
     *     // Encryption configuration
75
     *     // This configuration is used for both encryption and decryption
76
     *     // If not provided in config, we fall back to dummy/plain (no) encryption
77
     *     // <encryption_type> is the type of encryption or a custom encryption class name
78
     *    'encryption' => array(
79
     *        'type' => '<encryption_type>',
80
     *        '<option_1_for_encryption>' => '<value>',
81
     *        '<option_2_for_encryption>' => '<value>',
82
     *     ),
83
     *
84
     *     // Additional decryption method configuration
85
     *     // This configuration is only used for decryption, the encryption
86
     *     // configuration is also used for decryption and does not need to be repeated here.
87
     *     // <encryption_type_1> and <encryption_type_2> is the type of encryption or a custom encryption
88
     *     // class name.
89
     *     'decryption' => array(
90
     *         '<encryption_type_1>' => array(
91
     *             '<option_1_for_encryption_1>' => '<value>',
92
     *             '<option_2_for_encryption_1>' => '<value>',
93
     *         ),
94
     *         '<encryption_type_2>' => array(
95
     *              '<option_1_for_encryption_2>' => '<value>',
96
     *              '<option_2_for_encryption_2>' => '<value>',
97
     *         ),
98
     *     )
99
     * );
100
 *
101
     *
102
     * @return Tiqr_UserSecretStorage_Interface
103
     * @throws RuntimeException If an unknown type is requested.
104
     * @throws RuntimeException When the options configuration array misses a required parameter
105
     */
106 16
    public static function getSecretStorage(string $type, LoggerInterface $logger, array $options): Tiqr_UserSecretStorage_Interface
107
    {
108 16
        if ($type == 'oathserviceclient') {
109 3
            return (new Tiqr_UserSecretStorage)->_create_oauth_service_client($logger, $options);
110
        }
111
112
        // Create encryption instance
113
        // If not provided in config, we fall back to dummy/plain (no) encryption
114 13
        $encryptionType = $options['encryption']['type'] ?? 'plain';
115
        // If the encryption configuration is not configured, we fall back to an empty encryption configuration
116 13
        $encryptionOptions = $options['encryption'] ?? [];
117 13
        $encryption = Tiqr_UserSecretStorage_Encryption::getEncryption($logger, $encryptionType, $encryptionOptions);
118
119
        // Create decryption instance(s)
120
        // If not provided in config, we fall back to dummy/plain (no) encryption
121 13
        $decryptionOptions = $options['decryption'] ?? ['plain' => []];
122 13
        $decryption = [];
123 13
        foreach ($decryptionOptions as $decryptionType => $decryptionConfig) {
124 13
            $decryption[$decryptionType] = Tiqr_UserSecretStorage_Encryption::getEncryption($logger, $decryptionType, $decryptionConfig);
125
        }
126
127
        switch ($type) {
128 13
            case "file":
129 5
                if (!array_key_exists('path', $options)) {
130 1
                    throw new RuntimeException('The path is missing in the UserSecretStorage configuration');
131
                }
132 4
                $path = $options['path'];
133 4
                return new Tiqr_UserSecretStorage_File($encryption, $path, $logger, $decryption);
134
135 8
            case "pdo":
136
                // Input validation on the required configuration options
137 7
                if (!array_key_exists('dsn', $options)) {
138 1
                    throw new RuntimeException('The dsn is missing in the UserSecretStorage configuration');
139
                }
140 6
                if (!array_key_exists('username', $options)) {
141 1
                    throw new RuntimeException('The username is missing in the UserSecretStorage configuration');
142
                }
143 5
                if (!array_key_exists('password', $options)) {
144 1
                    throw new RuntimeException('The password is missing in the UserSecretStorage configuration');
145
                }
146
147 4
                $tableName = $options['table'] ?? 'tiqrusersecret';
148 4
                $dsn = $options['dsn'];
149 4
                $userName = $options['username'];
150 4
                $password = $options['password'];
151
152
                try {
153 4
                    $handle = new PDO($dsn, $userName, $password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION) );
154
                } catch (PDOException $e) {
155
                    $logger->error(
156
                        sprintf('Unable to establish a PDO connection. Error message from PDO: %s', $e->getMessage())
157
                    );
158
                    throw ReadWriteException::fromOriginalException($e);
159
                }
160 4
                return new Tiqr_UserSecretStorage_Pdo($encryption, $logger, $handle, $tableName, $decryption);
161
        }
162 1
        throw new RuntimeException(sprintf('Unable to create a UserSecretStorage instance of type: %s', $type));
163
    }
164
165 3
    private function _create_oauth_service_client(LoggerInterface $logger, array $options) : Tiqr_UserSecretStorage_OathServiceClient
166
    {
167 3
        if (!array_key_exists('apiURL', $options)) {
168 1
            throw new RuntimeException('The apiURL is missing in the UserSecretStorage configuration');
169
        }
170 2
        if (!array_key_exists('consumerKey', $options)) {
171 1
            throw new RuntimeException('The consumerKey is missing in the UserSecretStorage configuration');
172
        }
173
174 1
        $apiClient = new Tiqr_API_Client();
175 1
        $apiClient->setBaseURL($options['apiURL']);
176 1
        $apiClient->setConsumerKey($options['consumerKey']);
177 1
        return new Tiqr_UserSecretStorage_OathServiceClient($apiClient, $logger);
178
    }
179
}
180