Skip to content

Commit ce9024f

Browse files
authored
Merge pull request #90 from objmj-itminds/feature/openid-signin
Sign in with Slack support via Open ID api methods
2 parents db51f53 + 7fd3334 commit ce9024f

File tree

6 files changed

+166
-0
lines changed

6 files changed

+166
-0
lines changed

SlackNet.Tests/ApiLintTest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ public ISlackApiClient WithAccessToken(string accessToken)
204204
public IMigrationApi Migration { get; }
205205
public IOAuthApi OAuth { get; }
206206
public IOAuthV2Api OAuthV2 { get; }
207+
public IOpenIdApi OpenIdApi { get; }
207208
public IPinsApi Pins { get; }
208209
public IReactionsApi Reactions { get; }
209210
public IRemindersApi Reminders { get; }

SlackNet.Tests/Configuration/FactorySlackHandlerConfigurationTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,7 @@ protected class TestApiClient : ISlackApiClient
969969
public IMigrationApi Migration { get; }
970970
public IOAuthApi OAuth { get; }
971971
public IOAuthV2Api OAuthV2 { get; }
972+
public IOpenIdApi OpenIdApi { get; }
972973
public IPinsApi Pins { get; }
973974
public IReactionsApi Reactions { get; }
974975
public IRemindersApi Reminders { get; }

SlackNet/SlackApiClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public interface ISlackApiClient
2929
IMigrationApi Migration { get; }
3030
IOAuthApi OAuth { get; }
3131
IOAuthV2Api OAuthV2 { get; }
32+
IOpenIdApi OpenIdApi { get; }
3233
IPinsApi Pins { get; }
3334
IReactionsApi Reactions { get; }
3435
IRemindersApi Reminders { get; }
@@ -161,6 +162,7 @@ public SlackApiClient(IHttp http, ISlackUrlBuilder urlBuilder, SlackJsonSettings
161162
public IMigrationApi Migration => new MigrationApi(this);
162163
public IOAuthApi OAuth => new OAuthApi(this);
163164
public IOAuthV2Api OAuthV2 => new OAuthV2Api(this);
165+
public IOpenIdApi OpenIdApi => new OpenIdApi(this);
164166
public IPinsApi Pins => new PinsApi(this);
165167
public IReactionsApi Reactions => new ReactionsApi(this);
166168
public IRemindersApi Reminders => new RemindersApi(this);

SlackNet/WebApi/OpenIdApi.cs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
using Args = System.Collections.Generic.Dictionary<string, object>;
4+
5+
namespace SlackNet.WebApi
6+
{
7+
public interface IOpenIdApi
8+
{
9+
/// <summary>
10+
/// Exchanges a temporary OAuth verifier code for an access token for Sign in with Slack.
11+
/// See https://api.slack.com/methods/openid.connect.token for more information.
12+
/// </summary>
13+
/// <param name="clientId">Issued when you created your application.</param>
14+
/// <param name="clientSecret">Issued when you created your application.</param>
15+
/// <param name="code">The code param returned via the OAuth callback.</param>
16+
/// <param name="grantType">The grant_type param as described in the OAuth spec.</param>
17+
/// <param name="redirectUrl">This must match the originally submitted URI (if one was sent).</param>
18+
/// <param name="refreshToken">The refresh_token param as described in the OAuth spec.</param>
19+
/// <param name="cancellationToken"></param>
20+
Task<OpenIdTokenResponse> Token(
21+
string clientId,
22+
string clientSecret,
23+
#nullable enable
24+
string? code,
25+
string? grantType,
26+
string? redirectUrl,
27+
string? refreshToken,
28+
#nullable disable
29+
CancellationToken? cancellationToken
30+
);
31+
32+
/// <summary>
33+
/// Get the identity of a user who has authorized Sign in with Slack.
34+
/// See https://api.slack.com/methods/openid.connect.userInfo for more information.
35+
/// Note: that this method uses an Authentication token passed in the header.
36+
/// Use <c>SlackApiClient.WithAccessToken</c> to specify a token.
37+
/// </summary>
38+
/// <param name="token">Authentication token bearing required scopes. Tokens should be passed as an HTTP Authorization header or alternatively, as a POST parameter.</param>
39+
/// <param name="cancellationToken"></param>
40+
Task<OpenIdUserInfoResponse> UserInfo(CancellationToken? cancellationToken);
41+
42+
}
43+
44+
public class OpenIdApi : IOpenIdApi
45+
{
46+
private readonly ISlackApiClient _client;
47+
public OpenIdApi(ISlackApiClient client) => _client = client;
48+
49+
/// <summary>
50+
/// Exchanges a temporary OAuth verifier code for an access token for Sign in with Slack.
51+
/// See https://api.slack.com/methods/openid.connect.token for more information.
52+
/// </summary>
53+
/// <param name="clientId">Issued when you created your application.</param>
54+
/// <param name="clientSecret">Issued when you created your application.</param>
55+
/// <param name="code">The code param returned via the OAuth callback.</param>
56+
/// <param name="grantType">The grant_type param as described in the OAuth spec.</param>
57+
/// <param name="redirectUrl">This must match the originally submitted URI (if one was sent).</param>
58+
/// <param name="refreshToken">The refresh_token param as described in the OAuth spec.</param>
59+
/// <param name="cancellationToken"></param>
60+
public Task<OpenIdTokenResponse> Token(
61+
string clientId,
62+
string clientSecret,
63+
#nullable enable
64+
string? code,
65+
string? grantType,
66+
string? redirectUrl,
67+
string? refreshToken,
68+
#nullable disable
69+
CancellationToken? cancellationToken = null
70+
) => _client.Post<OpenIdTokenResponse>("openid.connect.token", new Args
71+
{
72+
{ "client_id", clientId },
73+
{ "client_secret", clientSecret },
74+
{ "code", code },
75+
{ "grant_type", grantType },
76+
{ "redirect_uri", redirectUrl },
77+
{ "refresh_token", refreshToken }
78+
}, cancellationToken);
79+
80+
81+
/// <summary>
82+
/// Get the identity of a user who has authorized Sign in with Slack.
83+
/// See https://api.slack.com/methods/openid.connect.userInfo for more information.
84+
/// Note: that this method uses an Authentication token passed in the header.
85+
/// Use <c>SlackApiClient.WithAccessToken</c> to specify a token.
86+
/// </summary>
87+
/// <param name="token">Authentication token bearing required scopes. Tokens should be passed as an HTTP Authorization header or alternatively, as a POST parameter.</param>
88+
/// <param name="cancellationToken"></param>
89+
public Task<OpenIdUserInfoResponse> UserInfo(CancellationToken? cancellationToken = null) =>
90+
_client.Post<OpenIdUserInfoResponse>("openid.connect.userInfo", new Args { }, cancellationToken);
91+
}
92+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace SlackNet.WebApi
2+
{
3+
public class OpenIdTokenResponse
4+
{
5+
public bool Ok { get; set; }
6+
public string AccessToken { get; set; }
7+
public string TokenType { get; set; }
8+
public string IdToken { get; set; }
9+
}
10+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using Newtonsoft.Json;
2+
3+
namespace SlackNet.WebApi
4+
{
5+
public class OpenIdUserInfoResponse
6+
{
7+
string Ok { get; set; }
8+
string Sub { get; set; }
9+
10+
[JsonProperty("https://slack.com/user_id")]
11+
string UserId { get; set; }
12+
13+
[JsonProperty("https://slack.com/team_id")]
14+
string TeamId { get; set; }
15+
16+
string Email { get; set; }
17+
string EmailVerified { get; set; }
18+
string DateEmailVerified { get; set; }
19+
string Name { get; set; }
20+
string Picture { get; set; }
21+
string GivenName { get; set; }
22+
string FamilyName { get; set; }
23+
string Locale { get; set; }
24+
25+
[JsonProperty("https://slack.com/team_name")]
26+
string TeamName { get; set; }
27+
[JsonProperty("https://slack.com/team_domain")]
28+
string TeamDomain { get; set; }
29+
30+
[JsonProperty("https://slack.com/user_image_24")]
31+
string UserImage24 { get; set; }
32+
[JsonProperty("https://slack.com/user_image_32")]
33+
string UserImage32 { get; set; }
34+
[JsonProperty("https://slack.com/user_image_48")]
35+
string UserImage48 { get; set; }
36+
[JsonProperty("https://slack.com/user_image_72")]
37+
string UserImage72 { get; set; }
38+
[JsonProperty("https://slack.com/user_image_192")]
39+
string UserImage192 { get; set; }
40+
[JsonProperty("https://slack.com/user_image_512")]
41+
string UserImage512 { get; set; }
42+
43+
[JsonProperty("https://slack.com/team_image_34")]
44+
string TeamImage34 { get; set; }
45+
[JsonProperty("https://slack.com/team_image_44")]
46+
string TeamImage44 { get; set; }
47+
[JsonProperty("https://slack.com/team_image_68")]
48+
string TeamImage68 { get; set; }
49+
[JsonProperty("https://slack.com/team_image_88")]
50+
string TeamImage88 { get; set; }
51+
[JsonProperty("https://slack.com/team_image_102")]
52+
string TeamImage102 { get; set; }
53+
[JsonProperty("https://slack.com/team_image_132")]
54+
string TeamImage132 { get; set; }
55+
[JsonProperty("https://slack.com/team_image_230")]
56+
string TeamImage230 { get; set; }
57+
[JsonProperty("https://slack.com/team_image_default")]
58+
string TeamImageDefault { get; set; }
59+
}
60+
}

0 commit comments

Comments
 (0)