microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
docs/update-release-process

Branches

Tags

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

Clone

HTTPS

Download ZIP

Libraries/Microsoft.Teams.Api/Auth/JsonWebToken.cs

116lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT License.
3
4using System.IdentityModel.Tokens.Jwt;
5using System.Text.Json.Serialization;
6
7namespace Microsoft.Teams.Api.Auth;
8
9public class JsonWebToken : IToken
10{
11 [JsonPropertyName("appid")]
12 public string? AppId => Token.Payload.TryGetValue("appid", out var value) ? (string?)value : null;
13
14 [JsonPropertyName("app_displayname")]
15 public string? AppDisplayName => Token.Payload.TryGetValue("app_displayname", out var value) ? (string?)value : null;
16
17 [JsonPropertyName("tid")]
18 public string? TenantId => Token.Payload.TryGetValue("tid", out var value) ? (string?)value : null;
19
20 [JsonPropertyName("serviceurl")]
21 public string ServiceUrl
22 {
23 get
24 {
25 var serviceUrl = Token.Payload.TryGetValue("serviceurl", out var value) ? (string?)value : null;
26
27 if (serviceUrl is null)
28 {
29 serviceUrl = "https://smba.trafficmanager.net/teams";
30 }
31
32 if (!serviceUrl.EndsWith("/"))
33 {
34 serviceUrl += '/';
35 }
36
37 return serviceUrl;
38 }
39 }
40
41 [JsonPropertyName("from")]
42 public CallerType From
43 {
44 get => AppId is null ? CallerType.Azure : CallerType.Bot;
45 }
46
47 [JsonPropertyName("fromId")]
48 public string FromId
49 {
50 get => From.IsBot ? $"urn:botframework:aadappid:{AppId}" : "urn:botframework:azure";
51 }
52
53 [JsonPropertyName("expiration")]
54 public DateTime? Expiration
55 {
56 get => Token.ValidTo;
57 }
58
59 [JsonIgnore]
60 public bool IsExpired
61 {
62 get => Token.ValidTo <= DateTime.UtcNow.AddMilliseconds(1000 * 60 * 5);
63 }
64
65 [JsonPropertyName("scopes")]
66 public IEnumerable<string> Scopes
67 {
68 get
69 {
70 var claim = Token.Claims.FirstOrDefault(c => c.Type == "scope" || c.Type == "scp");
71 if (claim is null) return [];
72 return claim.Value.Split(' ');
73 }
74 }
75
76 public JwtSecurityToken Token { get; }
77 private readonly string _tokenAsString;
78
79 /// <summary>
80 /// Typed accessor over an already-validated JWT payload. These constructors
81 /// perform no signature verification, no issuer/audience checks, and no
82 /// expiry enforcement. Constructing this class from an untrusted token does
83 /// NOT establish trust in the contained claims.
84 /// </summary>
85 /// <remarks>
86 /// Signature verification happens at the HTTP trust boundary via the
87 /// ASP.NET Core JwtBearer middleware configured by
88 /// <c>TokenValidator.ConfigureValidation</c>
89 /// (<c>Libraries/Microsoft.Teams.Plugins/Microsoft.Teams.Plugins.AspNetCore/Extensions/TokenValidator.cs</c>),
90 /// applied to endpoints via <c>.RequireAuthorization(...)</c>. Internal
91 /// callers may also construct from tokens sourced from trusted identity
92 /// infrastructure (MSAL, Bot Framework API responses).
93 /// <para>
94 /// Callers must not construct this class from raw network input.
95 /// </para>
96 /// </remarks>
97 public JsonWebToken(string token)
98 {
99 var handler = new JwtSecurityTokenHandler();
100 Token = handler.ReadJwtToken(token);
101 _tokenAsString = token;
102 }
103
104 /// <summary>
105 /// Typed accessor over a token returned by Teams identity infrastructure.
106 /// Same trust-boundary contract as the string constructor; see its remarks.
107 /// </summary>
108 public JsonWebToken(Token.Response response)
109 {
110 var handler = new JwtSecurityTokenHandler();
111 Token = handler.ReadJwtToken(response.Token);
112 _tokenAsString = response.Token;
113 }
114
115 public override string ToString() => _tokenAsString;
116}