friendship ended with social-app. php is my new best friend
1<?php
2/**
3 * Class Slack
4 *
5 * @created 26.10.2017
6 * @author Smiley <smiley@chillerlan.net>
7 * @copyright 2017 Smiley
8 * @license MIT
9 *
10 * @noinspection PhpUnused
11 */
12declare(strict_types=1);
13
14namespace chillerlan\OAuth\Providers;
15
16use chillerlan\OAuth\Core\{AuthenticatedUser, CSRFToken, InvalidAccessTokenException, OAuth2Provider, UserInfo};
17use function sprintf;
18
19/**
20 * Slack v2 OAuth2
21 *
22 * @link https://api.slack.com/authentication/oauth-v2
23 * @link https://api.slack.com/authentication/sign-in-with-slack
24 * @link https://api.slack.com/authentication/token-types
25 */
26class Slack extends OAuth2Provider implements CSRFToken, UserInfo{
27
28 public const IDENTIFIER = 'SLACK';
29
30 // bot token
31 public const SCOPE_BOT = 'bot';
32
33 // user token
34 public const SCOPE_ADMIN = 'admin';
35 public const SCOPE_CHAT_WRITE_BOT = 'chat:write:bot';
36 public const SCOPE_CLIENT = 'client';
37 public const SCOPE_DND_READ = 'dnd:read';
38 public const SCOPE_DND_WRITE = 'dnd:write';
39 public const SCOPE_FILES_READ = 'files:read';
40 public const SCOPE_FILES_WRITE_USER = 'files:write:user';
41 public const SCOPE_IDENTIFY = 'identify';
42 public const SCOPE_IDENTITY_AVATAR = 'identity.avatar';
43 public const SCOPE_IDENTITY_BASIC = 'identity.basic';
44 public const SCOPE_IDENTITY_EMAIL = 'identity.email';
45 public const SCOPE_IDENTITY_TEAM = 'identity.team';
46 public const SCOPE_INCOMING_WEBHOOK = 'incoming-webhook';
47 public const SCOPE_POST = 'post';
48 public const SCOPE_READ = 'read';
49 public const SCOPE_REMINDERS_READ = 'reminders:read';
50 public const SCOPE_REMINDERS_WRITE = 'reminders:write';
51 public const SCOPE_SEARCH_READ = 'search:read';
52 public const SCOPE_STARS_READ = 'stars:read';
53 public const SCOPE_STARS_WRITE = 'stars:write';
54
55 // user & workspace tokens
56 public const SCOPE_CHANNELS_HISTORY = 'channels:history';
57 public const SCOPE_CHANNELS_READ = 'channels:read';
58 public const SCOPE_CHANNELS_WRITE = 'channels:write';
59 public const SCOPE_CHAT_WRITE_USER = 'chat:write:user';
60 public const SCOPE_COMMANDS = 'commands';
61 public const SCOPE_EMOJI_READ = 'emoji:read';
62 public const SCOPE_GROUPS_HISTORY = 'groups:history';
63 public const SCOPE_GROUPS_READ = 'groups:read';
64 public const SCOPE_GROUPS_WRITE = 'groups:write';
65 public const SCOPE_IM_HISTORY = 'im:history';
66 public const SCOPE_IM_READ = 'im:read';
67 public const SCOPE_IM_WRITE = 'im:write';
68 public const SCOPE_LINKS_READ = 'links:read';
69 public const SCOPE_LINKS_WRITE = 'links:write';
70 public const SCOPE_MPIM_HISTORY = 'mpim:history';
71 public const SCOPE_MPIM_READ = 'mpim:read';
72 public const SCOPE_MPIM_WRITE = 'mpim:write';
73 public const SCOPE_PINS_READ = 'pins:read';
74 public const SCOPE_PINS_WRITE = 'pins:write';
75 public const SCOPE_REACTIONS_READ = 'reactions:read';
76 public const SCOPE_REACTIONS_WRITE = 'reactions:write';
77 public const SCOPE_TEAM_READ = 'team:read';
78 public const SCOPE_USERGROUPS_READ = 'usergroups:read';
79 public const SCOPE_USERGROUPS_WRITE = 'usergroups:write';
80 public const SCOPE_USERS_PROFILE_READ = 'users.profile:read';
81 public const SCOPE_USERS_PROFILE_WRITE = 'users.profile:write';
82 public const SCOPE_USERS_READ = 'users:read';
83 public const SCOPE_USERS_READ_EMAIL = 'users:read.email';
84 public const SCOPE_USERS_WRITE = 'users:write';
85
86 public const DEFAULT_SCOPES = [
87 self::SCOPE_IDENTITY_AVATAR,
88 self::SCOPE_IDENTITY_BASIC,
89 self::SCOPE_IDENTITY_EMAIL,
90 self::SCOPE_IDENTITY_TEAM,
91 ];
92
93 protected string $authorizationURL = 'https://slack.com/oauth/v2/authorize';
94 protected string $accessTokenURL = 'https://slack.com/api/oauth.v2.access';
95 protected string $apiURL = 'https://slack.com/api';
96 protected string|null $userRevokeURL = 'https://slack.com/apps/manage';
97 protected string|null $apiDocs = 'https://api.slack.com';
98 protected string|null $applicationURL = 'https://api.slack.com/apps';
99
100 /**
101 * HTTP/200 OK on errors? you're fired.
102 *
103 * @inheritDoc
104 * @codeCoverageIgnore
105 */
106 public function me():AuthenticatedUser{
107 $json = $this->getMeResponseData('/users.identity');
108
109 if(!empty($json['ok'])){
110
111 $userdata = [
112 'data' => $json,
113 'avatar' => $json['user']['image_512'],
114 'displayName' => $json['user']['name'],
115 'email' => $json['user']['email'],
116 'id' => $json['user']['id'],
117 ];
118
119 return new AuthenticatedUser($userdata);
120 }
121
122 if(isset($json['error'])){
123
124 if($json['error'] === 'invalid_auth'){
125 throw new InvalidAccessTokenException;
126 }
127
128 throw new ProviderException($json['error']);
129 }
130
131 throw new ProviderException(sprintf('user info error'));
132 }
133
134}