Skip to content

Commit b00eff5

Browse files
Chadchad
Chad
authored and
chad
committed
Add Slack authentication adapter
Summary: This adds an authentication adapter to libphutil for Slack. Diff 1 of 2. Test Plan: Create a new auth provider for Slack. Link Slack account to phacility.slack.com. Authenticate a new user, create an account with Slack reg provider. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D16495
1 parent 97f0526 commit b00eff5

File tree

3 files changed

+152
-0
lines changed

3 files changed

+152
-0
lines changed

src/__phutil_library_map__.php

+4
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,8 @@
363363
'PhutilSimpleOptionsLexerTestCase' => 'lexer/__tests__/PhutilSimpleOptionsLexerTestCase.php',
364364
'PhutilSimpleOptionsTestCase' => 'parser/__tests__/PhutilSimpleOptionsTestCase.php',
365365
'PhutilSimplifiedChineseLocale' => 'internationalization/locales/PhutilSimplifiedChineseLocale.php',
366+
'PhutilSlackAuthAdapter' => 'auth/PhutilSlackAuthAdapter.php',
367+
'PhutilSlackFuture' => 'future/slack/PhutilSlackFuture.php',
366368
'PhutilSocketChannel' => 'channel/PhutilSocketChannel.php',
367369
'PhutilSortVector' => 'utils/PhutilSortVector.php',
368370
'PhutilSpanishSpainLocale' => 'internationalization/locales/PhutilSpanishSpainLocale.php',
@@ -933,6 +935,8 @@
933935
'PhutilSimpleOptionsLexerTestCase' => 'PhutilTestCase',
934936
'PhutilSimpleOptionsTestCase' => 'PhutilTestCase',
935937
'PhutilSimplifiedChineseLocale' => 'PhutilLocale',
938+
'PhutilSlackAuthAdapter' => 'PhutilOAuthAuthAdapter',
939+
'PhutilSlackFuture' => 'FutureProxy',
936940
'PhutilSocketChannel' => 'PhutilChannel',
937941
'PhutilSortVector' => 'Phobject',
938942
'PhutilSpanishSpainLocale' => 'PhutilLocale',

src/auth/PhutilSlackAuthAdapter.php

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
/**
4+
* Authentication adapter for Slack OAuth2.
5+
*/
6+
final class PhutilSlackAuthAdapter extends PhutilOAuthAuthAdapter {
7+
8+
public function getAdapterType() {
9+
return 'Slack';
10+
}
11+
12+
public function getAdapterDomain() {
13+
return 'slack.com';
14+
}
15+
16+
public function getAccountID() {
17+
$user = $this->getOAuthAccountData('user');
18+
return idx($user, 'id');
19+
}
20+
21+
public function getAccountEmail() {
22+
$user = $this->getOAuthAccountData('user');
23+
return idx($user, 'email');
24+
}
25+
26+
public function getAccountImageURI() {
27+
$user = $this->getOAuthAccountData('user');
28+
return idx($user, 'image_512');
29+
}
30+
31+
public function getAccountRealName() {
32+
$user = $this->getOAuthAccountData('user');
33+
return idx($user, 'name');
34+
}
35+
36+
protected function getAuthenticateBaseURI() {
37+
return 'https://slack.com/oauth/authorize';
38+
}
39+
40+
protected function getTokenBaseURI() {
41+
return 'https://slack.com/api/oauth.access';
42+
}
43+
44+
public function getScope() {
45+
return 'identity.basic,identity.team,identity.avatar';
46+
}
47+
48+
public function getExtraAuthenticateParameters() {
49+
return array(
50+
'response_type' => 'code',
51+
);
52+
}
53+
54+
protected function loadOAuthAccountData() {
55+
return id(new PhutilSlackFuture())
56+
->setAccessToken($this->getAccessToken())
57+
->setRawSlackQuery('users.identity')
58+
->resolve();
59+
}
60+
61+
}
+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
final class PhutilSlackFuture extends FutureProxy {
4+
5+
private $future;
6+
private $clientID;
7+
private $accessToken;
8+
private $action;
9+
private $params;
10+
private $method = 'GET';
11+
12+
public function __construct() {
13+
parent::__construct(null);
14+
}
15+
16+
public function setAccessToken($token) {
17+
$this->accessToken = $token;
18+
return $this;
19+
}
20+
21+
public function setClientID($client_id) {
22+
$this->clientID = $client_id;
23+
return $this;
24+
}
25+
26+
public function setRawSlackQuery($action, array $params = array()) {
27+
$this->action = $action;
28+
$this->params = $params;
29+
return $this;
30+
}
31+
32+
public function setMethod($method) {
33+
$this->method = $method;
34+
return $this;
35+
}
36+
37+
protected function getProxiedFuture() {
38+
if (!$this->future) {
39+
$params = $this->params;
40+
41+
if (!$this->action) {
42+
throw new Exception(pht('You must %s!', 'setRawSlackQuery()'));
43+
}
44+
45+
if (!$this->accessToken) {
46+
throw new Exception(pht('You must %s!', 'setAccessToken()'));
47+
}
48+
49+
$uri = new PhutilURI('https://slack.com/');
50+
$uri->setPath('/api/'.$this->action);
51+
$uri->setQueryParam('token', $this->accessToken);
52+
53+
$future = new HTTPSFuture($uri);
54+
$future->setData($this->params);
55+
$future->setMethod($this->method);
56+
57+
$this->future = $future;
58+
}
59+
60+
return $this->future;
61+
}
62+
63+
protected function didReceiveResult($result) {
64+
list($status, $body, $headers) = $result;
65+
66+
if ($status->isError()) {
67+
throw $status;
68+
}
69+
70+
$data = null;
71+
try {
72+
$data = phutil_json_decode($body);
73+
} catch (PhutilJSONParserException $ex) {
74+
throw new PhutilProxyException(
75+
pht('Expected JSON response from Slack.'),
76+
$ex);
77+
}
78+
79+
if (idx($data, 'error')) {
80+
$error = $data['error'];
81+
throw new Exception(pht('Received error from Slack: %s', $error));
82+
}
83+
84+
return $data;
85+
}
86+
87+
}

0 commit comments

Comments
 (0)