-
Notifications
You must be signed in to change notification settings - Fork 818
/
Copy pathSSOAuthHelper.cs
175 lines (153 loc) · 6.85 KB
/
SSOAuthHelper.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Primitives;
using Microsoft.Identity.Client;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace TeamsTabSSO.Helper
{
/// <summary>
/// Helper class for Authentication.
/// </summary>
public class SSOAuthHelper
{
/// <summary>
/// Azure Client Id.
/// </summary>
private static readonly string ClientIdConfigurationSettingsKey = "AzureAd:ClientId";
/// <summary>
/// Azure Tenant Id.
/// </summary>
private static readonly string TenantIdConfigurationSettingsKey = "AzureAd:TenantId";
/// <summary>
/// Azure Application Id URI.
/// </summary>
private static readonly string ApplicationIdURIConfigurationSettingsKey = "AzureAd:ApplicationIdURI";
/// <summary>
/// Azure Valid Issuers.
/// </summary>
private static readonly string ValidIssuersConfigurationSettingsKey = "AzureAd:ValidIssuers";
/// <summary>
/// Azure AppSecret .
/// </summary>
private static readonly string AppsecretConfigurationSettingsKey = "AzureAd:AppSecret";
/// <summary>
/// Azure Url .
/// </summary>
private static readonly string AzureInstanceConfigurationSettingsKey = "AzureAd:Instance";
/// <summary>
/// Azure Authorization Url .
/// </summary>
private static readonly string AzureAuthUrlConfigurationSettingsKey = "AzureAd:AuthUrl";
/// <summary>
/// Retrieve Valid Audiences.
/// </summary>
/// <param name="configuration">IConfiguration instance.</param>
/// <returns>Valid Audiences.</returns>
public static IEnumerable<string> GetValidAudiences(IConfiguration configuration)
{
var clientId = configuration[ClientIdConfigurationSettingsKey];
var applicationIdUri = configuration[ApplicationIdURIConfigurationSettingsKey];
var validAudiences = new List<string> { clientId, applicationIdUri.ToLower() };
return validAudiences;
}
/// <summary>
/// Retrieve Valid Issuers.
/// </summary>
/// <param name="configuration">IConfiguration instance.</param>
/// <returns>Valid Issuers.</returns>
public static IEnumerable<string> GetValidIssuers(IConfiguration configuration)
{
var tenantId = configuration[TenantIdConfigurationSettingsKey];
var validIssuers = GetSettings(configuration);
validIssuers = validIssuers.Select(validIssuer => validIssuer.Replace("TENANT_ID", tenantId));
return validIssuers;
}
/// <summary>
/// Audience Validator.
/// </summary>
/// <param name="tokenAudiences">Token audiences.</param>
/// <param name="securityToken">Security token.</param>
/// <param name="validationParameters">Validation parameters.</param>
/// <returns>Audience validator status.</returns>
public static bool AudienceValidator(
IEnumerable<string> tokenAudiences,
SecurityToken securityToken,
TokenValidationParameters validationParameters)
{
if (tokenAudiences == null || tokenAudiences.Count() == 0)
{
throw new ApplicationException("No audience defined in token!");
}
var validAudiences = validationParameters.ValidAudiences;
if (validAudiences == null || validAudiences.Count() == 0)
{
throw new ApplicationException("No valid audiences defined in validationParameters!");
}
foreach (var tokenAudience in tokenAudiences)
{
if (validAudiences.Any(validAudience => validAudience.Equals(tokenAudience, StringComparison.OrdinalIgnoreCase)))
{
return true;
}
}
return false;
}
/// <summary>
/// Get token using client credentials flow
/// </summary>
/// <param name="configuration">IConfiguration instance.</param>
/// <param name="httpClientFactory">IHttpClientFactory instance.</param>
/// <param name="httpContextAccessor">IHttpContextAccessor instance.</param>
/// <returns>App access token on behalf of user.</returns>
public static async Task<string> GetAccessTokenOnBehalfUserAsync(IConfiguration configuration, IHttpClientFactory httpClientFactory, IHttpContextAccessor httpContextAccessor)
{
var tenantId = configuration["AzureAd:TenantId"];
IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(configuration["AzureAd:ClientId"])
.WithClientSecret(configuration["AzureAd:AppSecret"])
.WithAuthority($"https://login.microsoftonline.com/{tenantId}")
.Build();
try
{
var httpContext = httpContextAccessor.HttpContext;
httpContext.Request.Headers.TryGetValue("Authorization", out StringValues assertion);
var idToken = assertion.ToString().Split(" ")[1];
UserAssertion assert = new UserAssertion(idToken);
List<string> scopes = new List<string>
{
"User.Read"
};
var responseToken = await app.AcquireTokenOnBehalfOf(scopes, assert).ExecuteAsync();
return responseToken.AccessToken.ToString();
}
catch (Exception ex)
{
return "invalid_grant";
}
}
/// <summary>
/// Retrieve Settings.
/// </summary>
/// <param name="configuration">IConfiguration instance.</param>
/// <returns>Configuration settings for valid issuers.</returns>
private static IEnumerable<string> GetSettings(IConfiguration configuration)
{
var configurationSettingsValue = configuration[ValidIssuersConfigurationSettingsKey];
var settings = configurationSettingsValue
?.Split(new char[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries)
?.Select(p => p.Trim());
if (settings == null)
{
throw new ApplicationException($"{ValidIssuersConfigurationSettingsKey} does not contain a valid value in the configuration file.");
}
return settings;
}
}
}