Passed
Pull Request — master (#2)
by Tim
02:29
created

Twitter::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 8
c 2
b 0
f 0
nc 1
nop 2
dl 0
loc 14
rs 10
1
<?php
2
3
namespace SimpleSAML\Module\authtwitter\Auth\Source;
4
5
use League\OAuth1\Client\Server\Twitter as TwitterServer;
6
use League\OAuth1\Client\Credentials\TemporaryCredentials;
7
use SimpleSAML\Assert\Assert;
8
use SimpleSAML\Auth;
9
use SimpleSAML\Configuration;
10
use SimpleSAML\Error;
11
use SimpleSAML\Logger;
12
use SimpleSAML\Module;
13
use SimpleSAML\Utils;
14
use Symfony\Component\HttpFoundation\Request;
15
16
/**
17
 * Authenticate using Twitter.
18
 *
19
 * @package simplesamlphp/simplesamlphp-module-authtwitter
20
 */
21
22
class Twitter extends Auth\Source
23
{
24
    /**
25
     * The string used to identify our states.
26
     */
27
    public const STAGE_TEMP = 'twitter:temp';
28
29
    /**
30
     * The key of the AuthId field in the state.
31
     */
32
    public const AUTHID = 'twitter:AuthId';
33
34
    /** @var string */
35
    private string $key;
36
37
    /** @var string */
38
    private string $secret;
39
40
    /** @var string */
41
    private string $scope;
42
43
    /** @var bool */
44
    private bool $force_login;
45
46
    /**
47
     * Constructor for this authentication source.
48
     *
49
     * @param array $info  Information about this authentication source.
50
     * @param array $config  Configuration.
51
     */
52
    public function __construct(array $info, array $config)
53
    {
54
        // Call the parent constructor first, as required by the interface
55
        parent::__construct($info, $config);
56
57
        $configObject = Configuration::loadFromArray(
58
            $config,
59
            'authsources[' . var_export($this->authId, true) . ']'
60
        );
61
62
        $this->key = $configObject->getString('key');
63
        $this->secret = $configObject->getString('secret');
64
        $this->scope = $configObject->getString('scope');
65
        $this->force_login = $configObject->getBoolean('force_login', false);
66
    }
67
68
69
    /**
70
     * Log-in using Twitter platform
71
     *
72
     * @param array &$state  Information about the current authentication.
73
     */
74
    public function authenticate(array &$state): void
75
    {
76
        $this->temporaryCredentials($state);
77
    }
78
79
80
    /**
81
     * Retrieve temporary credentials
82
     *
83
     * @param array &$state  Information about the current authentication.
84
     */
85
    private function temporaryCredentials(array &$state): void
86
    {
87
        // We are going to need the authId in order to retrieve this authentication source later
88
        $state[self::AUTHID] = $this->authId;
89
90
        $stateId = base64_encode(Auth\State::saveState($state, self::STAGE_TEMP));
91
92
        $server = new TwitterServer(
93
            [
94
                'identifier' => $this->key,
95
                'secret' => $this->secret,
96
                'callback_uri' => Module::getModuleURL('authtwitter/linkback.php')
97
                    . '?AuthState=' . $stateId . '&force_login=' . strval($this->force_login),
98
            ]
99
        );
100
101
        // First part of OAuth 1.0 authentication is retrieving temporary credentials.
102
        // These identify you as a client to the server.
103
        $temporaryCredentials = $server->getTemporaryCredentials();
104
105
        $state['authtwitter:authdata:requestToken'] = serialize($temporaryCredentials);
106
        Auth\State::saveState($state, self::STAGE_TEMP);
107
108
        $server->authorize($temporaryCredentials);
109
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
110
    }
111
112
113
    /**
114
     * @param array &$state
115
     */
116
    public function finalStep(TemporaryCredentials $requestToken, string $oauth_token, string $oauth_verifier): void
117
    {
118
        $server = new TwitterServer(
119
            [
120
                'identifier' => $this->key,
121
                'secret' => $this->secret,
122
            ]
123
        );
124
125
        $tokenCredentials = $server->getTokenCredentials(
126
            $requestToken,
127
            $oauth_token,
128
            $oauth_verifier
129
        );
130
131
        $state['token_credentials'] = serialize($tokenCredentials);
0 ignored issues
show
Comprehensibility Best Practice introduced by
$state was never initialized. Although not strictly required by PHP, it is generally a good practice to add $state = array(); before regardless.
Loading history...
132
        $userdata = $server->getUserDetails($tokenCredentials);
133
134
        $attributes = [];
135
136
        foreach ($userdata->getIterator() as $key => $value) {
137
            if (is_string($value)) {
138
                $attributes['twitter.' . $key] = [$value];
139
            }
140
        }
141
142
        $attributes['twitter_at_screen_name'] = ['@' . $userdata->nickname];
143
        $attributes['twitter_screen_n_realm'] = [$userdata->nickname . '@twitter.com'];
144
        $attributes['twitter_targetedID'] = ['http://twitter.com!' . $userdata->uid];
145
146
        $state['Attributes'] = $attributes;
147
    }
148
}
149