microsoft/teams.net

Public

mirrored fromhttps://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v2.0.0-preview.5

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

Libraries/Microsoft.Teams.Apps/Contexts/Context.SignIn.cs

132lines · modecode

1using System.Text.Json;
2
3using Microsoft.Teams.Api;
4using Microsoft.Teams.Api.Activities;
5
6namespace Microsoft.Teams.Apps;
7
8public partial interface IContext<TActivity>
9{
10 /// <summary>
11 /// is the activity sender signed in?
12 /// </summary>
13 public bool IsSignedIn { get; set; }
14
15 /// <summary>
16 /// trigger user signin flow for the activity sender
17 /// </summary>
18 /// <param name="options">option overrides</param>
19 /// <returns>the existing user token if found</returns>
20 public Task<string?> SignIn(SignInOptions? options = null);
21
22 /// <summary>
23 /// trigger user signin flow for the activity sender
24 /// </summary>
25 /// <param name="connectionName">the connection name</param>
26 public Task SignOut(string? connectionName = null);
27}
28
29public partial class Context<TActivity> : IContext<TActivity>
30{
31 public bool IsSignedIn { get; set; } = false;
32
33 public async Task<string?> SignIn(SignInOptions? options = null)
34 {
35 options ??= new SignInOptions();
36 var reference = Ref.Copy();
37
38 try
39 {
40 var tokenResponse = await Api.Users.Token.GetAsync(new()
41 {
42 UserId = Activity.From.Id,
43 ChannelId = Activity.ChannelId,
44 ConnectionName = options.ConnectionName,
45 });
46
47 return tokenResponse.Token;
48 }
49 catch { }
50
51 // create new 1:1 conversation with user to do SSO
52 // because groupchats don't support it.
53 if (Activity.Conversation.IsGroup == true)
54 {
55 var (id, _, _) = await Api.Conversations.CreateAsync(new()
56 {
57 TenantId = Ref.Conversation.TenantId,
58 IsGroup = false,
59 Bot = Ref.Bot,
60 Members = [Activity.From]
61 });
62
63 reference.Conversation.Id = id;
64 reference.Conversation.IsGroup = false;
65
66 var oauthCardActivity = await Sender.Send(new MessageActivity(options.OAuthCardText), reference, CancellationToken);
67 await OnActivitySent(oauthCardActivity, (IContext<IActivity>)this);
68 }
69
70 var tokenExchangeState = new Api.TokenExchange.State()
71 {
72 ConnectionName = options.ConnectionName,
73 Conversation = reference,
74 RelatesTo = Activity.RelatesTo,
75 MsAppId = AppId
76 };
77
78 var state = Convert.ToBase64String(JsonSerializer.SerializeToUtf8Bytes(tokenExchangeState));
79 var resource = await Api.Bots.SignIn.GetResourceAsync(new() { State = state });
80 var activity = new MessageActivity();
81
82 activity.InputHint = InputHint.AcceptingInput;
83 activity.Recipient = Activity.From;
84 activity.Conversation = reference.Conversation;
85 activity.AddAttachment(new Api.Cards.OAuthCard()
86 {
87 Text = options.OAuthCardText,
88 ConnectionName = options.ConnectionName,
89 TokenExchangeResource = resource.TokenExchangeResource,
90 TokenPostResource = resource.TokenPostResource,
91 Buttons = [
92 new(Teams.Api.Cards.ActionType.SignIn)
93 {
94 Title = options.SignInButtonText,
95 Value = resource.SignInLink
96 }
97 ]
98 });
99
100 var res = await Sender.Send(activity, reference, CancellationToken);
101 await OnActivitySent(res, (IContext<IActivity>)this);
102 return null;
103 }
104
105 public async Task SignOut(string? connectionName = null)
106 {
107 await Api.Users.Token.SignOutAsync(new()
108 {
109 ChannelId = Ref.ChannelId,
110 UserId = Activity.From.Id,
111 ConnectionName = connectionName ?? "graph",
112 });
113 }
114}
115
116public class SignInOptions
117{
118 /// <summary>
119 /// the connection name
120 /// </summary>
121 public string ConnectionName { get; set; } = "graph";
122
123 /// <summary>
124 /// the oauth card text
125 /// </summary>
126 public string OAuthCardText { get; set; } = "Please Sign In...";
127
128 /// <summary>
129 /// the sign in button text
130 /// </summary>
131 public string SignInButtonText { get; set; } = "Sign In";
132}