-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathMastodonOAuth.php
More file actions
154 lines (143 loc) · 4.64 KB
/
MastodonOAuth.php
File metadata and controls
154 lines (143 loc) · 4.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
namespace Colorfield\Mastodon;
use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\GuzzleException;
/**
* Class MastodonOAuth.
*
* Usage: see README.md
*/
class MastodonOAuth
{
public ConfigurationVO $config;
private readonly ClientInterface $client;
/**
* Creates the OAuth object from the configuration.
*/
public function __construct(
string $client_name = ConfigurationVO::DEFAULT_NAME,
string $mastodon_instance = ConfigurationVO::DEFAULT_INSTANCE,
string $redirectUris = ConfigurationVO::DEFAULT_REDIRECT_URIS,
string $api_version = ConfigurationVO::API_VERSION
) {
$this->config = new ConfigurationVO($client_name, $mastodon_instance, $redirectUris, $api_version);
$this->client = new Client();
}
/**
* Get response from the endpoint.
*
*
* @return mixed
* @throws GuzzleException|Exception
*/
private function getResponse(string $endpoint, array $json): mixed
{
// endpoint
$uri = $this->config->getBaseUrl() . $endpoint;
$response = $this->client->post(
$uri,
[
'json' => $json,
]
);
// @todo $request->getHeader('content-type')
if ($response->getStatusCode() === 200) {
$result = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR);
} else {
throw new Exception('ERROR ' . $response->getStatusCode() . ' : ' . $response->getReasonPhrase());
}
return $result;
}
/**
* Register the Mastodon application.
*
* Appends client_id and client_secret to the configuration value object.
*
* @return void
* @throws GuzzleException|Exception
*/
public function registerApplication(): void
{
$options = $this->config->getAppConfiguration();
$credentials = $this->getResponse(
'/api/' . ConfigurationVO::API_VERSION . '/apps',
$options
);
if (isset($credentials['client_id'])
&& isset($credentials['client_secret'])
) {
$this->config->setClientId($credentials['client_id']);
$this->config->setClientSecret($credentials['client_secret']);
} else {
throw new Exception('ERROR: no credentials in API response');
}
}
/**
* Returns the authorization URL that will provide the authorization code"
* after manual approval.
*
* @return string
* @throws GuzzleException|Exception
*/
public function getAuthorizationUrl(): string
{
if (!$this->config->hasCredentials()) {
$this->registerApplication();
}
return "https://{$this->config->getMastodonInstance()}/oauth/authorize/?".http_build_query(
[
'response_type' => 'code',
// @todo review usage of singular / plural in redirect_uri
// singular seems to be required here.
'redirect_uri' => $this->config->getRedirectUris(),
'scope' => $this->config->getScopes(),
'client_id' => $this->config->getClientId(),
]
);
}
/**
* Gets the access token.
*
* As a side effect, stores it into the Configuration as bearer.
*
* @return string
* @throws GuzzleException|Exception
*/
public function getAccessToken(): string
{
$options = $this->config->getAccessTokenConfiguration();
// @todo fix workaround for plural / singular.
$options['redirect_uri'] = $options['redirect_uris'];
$token = $this->getResponse('/oauth/token', $options);
if (isset($token['access_token'])) {
$this->config->setBearer($token['access_token']);
} else {
throw new Exception('ERROR: no access token in API response');
}
return $token['access_token'];
}
/**
* Authenticates a user.
*
*
* @return array
* @throws GuzzleException|Exception
*/
public function authenticateUser(string $email, string $password): array
{
if (empty($this->config->getBearer())) {
$this->getAccessToken();
}
// @todo validate email address and password
$options = $this->config->getUserAuthenticationConfiguration(
$email,
$password
);
// @todo test, returns the bearer if success
$token = $this->getResponse('/oauth/token', $options);
$this->config->setBearer($token['access_token']);
return $token;
}
}