forked from pnp/powershell
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTokenHandling.cs
154 lines (148 loc) · 7.01 KB
/
TokenHandling.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
using Microsoft.SharePoint.Client;
using Newtonsoft.Json.Linq;
using PnP.PowerShell.Commands.Attributes;
using PnP.PowerShell.Commands.Model;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Management.Automation;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using System.Web;
namespace PnP.PowerShell.Commands.Base
{
internal static class TokenHandler
{
internal static void ValidateTokenForPermissions(Type cmdletType, string token)
{
string[] requiredScopes = null;
var requiredScopesAttribute = (RequiredMinimalApiPermissions)Attribute.GetCustomAttribute(cmdletType, typeof(RequiredMinimalApiPermissions));
if (requiredScopesAttribute != null)
{
requiredScopes = requiredScopesAttribute.PermissionScopes;
}
if (requiredScopes.Length > 0)
{
var decodedToken = new JwtSecurityToken(token);
var roles = decodedToken.Claims.FirstOrDefault(c => c.Type == "roles");
if (roles != null)
{
foreach (var permission in requiredScopes)
{
if (!roles.Value.ToLower().Contains(permission.ToLower()))
{
throw new PSArgumentException($"Authorization Denied: Token used does not contain permission scope '{permission}'");
}
}
}
roles = decodedToken.Claims.FirstOrDefault(c => c.Type == "scp");
if (roles != null)
{
foreach (var permission in requiredScopes)
{
if (!roles.Value.ToLower().Contains(permission.ToLower()))
{
throw new PSArgumentException($"Authorization Denied: Token used does not contain permission scope '{permission}'");
}
}
}
}
}
internal static string GetAccessToken(Type cmdletType, string appOnlyDefaultScope)
{
var contextSettings = PnPConnection.Current.Context.GetContextSettings();
var authManager = contextSettings.AuthenticationManager;
if (authManager != null)
{
if (contextSettings.Type == Framework.Utilities.Context.ClientContextType.SharePointACSAppOnly)
{
// When connected using ACS, we cannot get a token for another endpoint
throw new PSInvalidOperationException("Trying to get a token for a different endpoint while being connected through an ACS token is not possible. Please connect differently.");
}
string[] requiredScopes = null;
//RequiredMinimalApiPermissions requiredScopesAttribute = (RequiredMinimalApiPermissions)Attribute.GetCustomAttribute(cmdletType, typeof(RequiredMinimalApiPermissions));
RequiredMinimalApiPermissions requiredScopesAttribute = null;
if (cmdletType != null)
{
requiredScopesAttribute = (RequiredMinimalApiPermissions)Attribute.GetCustomAttribute(cmdletType, typeof(RequiredMinimalApiPermissions));
}
if (requiredScopesAttribute != null)
{
requiredScopes = requiredScopesAttribute.PermissionScopes;
}
if (contextSettings.Type == Framework.Utilities.Context.ClientContextType.AzureADCertificate)
{
requiredScopes = new[] { appOnlyDefaultScope }; // override for app only
}
if (requiredScopes == null && !string.IsNullOrEmpty(appOnlyDefaultScope))
{
requiredScopes = new[] { appOnlyDefaultScope };
}
var accessToken = authManager.GetAccessTokenAsync(requiredScopes).GetAwaiter().GetResult();
return accessToken;
}
return null;
}
internal static async Task<string> GetManagedIdentityTokenAsync(Cmdlet cmdlet, HttpClient httpClient, string defaultResource)
{
string requiredScope = null;
var requiredScopesAttribute = (RequiredMinimalApiPermissions)Attribute.GetCustomAttribute(cmdlet.GetType(), typeof(RequiredMinimalApiPermissions));
if (requiredScopesAttribute != null)
{
requiredScope = requiredScopesAttribute.PermissionScopes.First();
if (requiredScope.ToLower().StartsWith("https://"))
{
var uri = new Uri(requiredScope);
requiredScope = $"https://{uri.Host}/";
}
else
{
requiredScope = defaultResource;
}
}
else
{
requiredScope = defaultResource;
}
var endPoint = Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT");
var identityHeader = Environment.GetEnvironmentVariable("IDENTITY_HEADER");
if (string.IsNullOrEmpty(endPoint))
{
endPoint = Environment.GetEnvironmentVariable("MSI_ENDPOINT");
identityHeader = Environment.GetEnvironmentVariable("MSI_SECRET");
}
if (!string.IsNullOrEmpty(endPoint))
{
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, $"{endPoint}?resource={requiredScope}&api-version=2019-08-01"))
{
requestMessage.Headers.Add("Metadata", "true");
if (!string.IsNullOrEmpty(identityHeader))
{
requestMessage.Headers.Add("X-IDENTITY-HEADER", identityHeader);
}
var response = await httpClient.SendAsync(requestMessage).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
var responseElement = JsonSerializer.Deserialize<JsonElement>(responseContent);
if (responseElement.TryGetProperty("access_token", out JsonElement accessTokenElement))
{
return accessTokenElement.GetString();
}
}
else
{
var errorMessage = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new PSInvalidOperationException(errorMessage);
}
}
}
else
{
throw new PSInvalidOperationException("Cannot determine Managed Identity Endpoint URL to acquire token.");
}
return null;
}
}
}