using System; using System.Collections.Generic; using System.Text; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using Microsoft.IdentityModel.Tokens; using Microsoft.Identity.Client; using System.ComponentModel; using System.Threading.Tasks; using Azure.Security.KeyVault.Secrets; using Azure.Core; using Azure.Identity; using System.Net.Http; using System.Collections.Concurrent; using System.Diagnostics; namespace TEAMModelOS.SDK.Extension { public static class CoreTokenExtensions { //var issuer = Configuration.GetValue("JwtSettings:Issuer"); //var signKey = Configuration.GetValue("JwtSettings:SignKey"); private const string issuer = "account.teammodel"; //Azure AD 租用戶識別碼(國際、大陸) private static List tenantids = new List { "73a2bcc5-fe99-4566-aa8a-07e7bb287df1", "4807e9cf-87b8-4174-aa5b-e76497d7392b" }; private static ConcurrentDictionary KeyVaultSecrets { get; } = new ConcurrentDictionary(); #region Access Token /// /// 產生AccessToken /// /// /// 服務位置,Global or China ... /// public static async ValueTask CreateAccessToken(string clientID, string clientSecret, string location) { //從金鑰庫取出秘密,此作法讓所有端直接刷新金鑰,無需傳送秘密,SPA更適用 var secret = clientSecret ?? (await GetClientIDSecret(clientID, location)).Value; var sts = Enum.Parse(location, true); IConfidentialClientApplication app; app = ConfidentialClientApplicationBuilder.Create(clientID) .WithClientSecret(secret) .WithAuthority(new Uri(sts.GetDescriptionText())) .Build(); var scope = ((STSScope)sts).GetDescriptionText(); var result = await app.AcquireTokenForClient(new[] { scope }).ExecuteAsync(); return result; } /// /// 驗證是否為公司Azure發行金鑰,支援大陸國際 /// /// /// public static bool ValidateAccessToken(JwtSecurityToken token) { try { if (token.Payload.TryGetValue("tid", out var value) && value is string tokenTenantId) { return tenantids.Contains(tokenTenantId); } return false; } catch (Exception) { return false; } } public static bool ValidateIdToken(string token, string salt) { try { var handler = new JwtSecurityTokenHandler(); var validationParameters = new TokenValidationParameters { RequireExpirationTime = true, ValidateIssuer = false, ValidateAudience = false, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt)), ValidateLifetime = false, //LifetimeValidator = LifetimeValidator, ClockSkew = TimeSpan.Zero }; ClaimsPrincipal principal = handler.ValidateToken(token, validationParameters, out SecurityToken securityToken); return true; } catch(Exception ex) { Trace.WriteLine(ex.Message); return false; } } #endregion private static async ValueTask GetClientIDSecret(string clientID, string location) { //Azure 金鑰庫處理 var s = await Task.Run(() => { var secret = KeyVaultSecrets.GetOrAdd(clientID, (x) => { try { var sts = Enum.Parse(location, true); var scrtetstring = sts.GetDescriptionText().Split(","); //TODO 之後驗證端點用KnownAuthorityHosts取代,此SDK版本無支援 var secret = new ClientSecretCredential(scrtetstring[0], scrtetstring[1], scrtetstring[2], new TokenCredentialOptions() { AuthorityHost = new Uri(scrtetstring[3]) }); var client = new SecretClient(new Uri(((KeyVaultEndpoint)sts).GetDescriptionText()), secret); var clientSecret = client.GetSecretAsync(clientID).ConfigureAwait(false); return clientSecret.GetAwaiter().GetResult(); } catch { return null; } }); return secret; }); return s; } public static bool LifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) { return true; //if (expires != null) //{ // if (DateTime.UtcNow < expires) // { // return true; // } //} //return false; } private enum STSEndpoint { [Description("https://login.chinacloudapi.cn/4807e9cf-87b8-4174-aa5b-e76497d7392b")] China, [Description("https://login.microsoftonline.com/73a2bcc5-fe99-4566-aa8a-07e7bb287df1")] Global } private enum STSScope { [Description("api://72643704-b2e7-4b26-b881-bd5865e7a7a5/.default")] China, [Description("api://8768b06f-c5c5-4b0c-abfb-d7ded354626d/.default")] Global } private enum KeyVaultEndpoint { [Description("https://corekeyvaultcn.vault.azure.cn/")] China, [Description("https://corekeyvaultjp.vault.azure.net/")] Global } private enum CoreServiceClient { [Description("4807e9cf-87b8-4174-aa5b-e76497d7392b,72643704-b2e7-4b26-b881-bd5865e7a7a5,tRYbDXtotEOe2Bbmo=[3h9Hbu_Trt:c6,https://login.partner.microsoftonline.cn")] China, [Description("73a2bcc5-fe99-4566-aa8a-07e7bb287df1,8768b06f-c5c5-4b0c-abfb-d7ded354626d,7=O./yws0L89WcEsece:9/4deJHP4E=F,https://login.microsoftonline.com/")] Global } } }