using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; using System; using System.Threading.Tasks; using System.Security.Claims; using System.IdentityModel.Tokens.Jwt; using System.Collections.Generic; using System.Text; namespace TEAMModelOS.SDK.Extension { public static class JwtAuthExtension { public static string CreateAuthToken(string issuer, string id,string name,string picture, string salt, string schoolID = "",string standard="", string[] roles = null, string[] permissions = null, int expire = 1) { // 設定要加入到 JWT Token 中的聲明資訊(Claims) var payload = new JwtPayload { { JwtRegisteredClaimNames.Iss, issuer }, //發行者 { JwtRegisteredClaimNames.Sub, id }, // 用戶ID { JwtRegisteredClaimNames.Azp,schoolID}, // 學校簡碼,如果有的話 { JwtRegisteredClaimNames.Exp,DateTimeOffset.UtcNow.AddHours(expire).ToUnixTimeSeconds().ToString()}, // 到期的時間,必須為數字 { "name",name}, // 用戶的顯示名稱 { "picture",picture}, // 用戶頭像 { "roles",roles}, // 登入者的角色,角色類型 (Admin、Teacher、Student) { "permissions",permissions}, //登入者的權限請求 { "standard",standard} //登入者的權限請求 }; // 建立一組對稱式加密的金鑰,主要用於 JWT 簽章之用 var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt)); // HmacSha256 有要求必須要大於 128 bits,所以 salt 不能太短,至少要 16 字元以上 // https://stackoverflow.com/questions/47279947/idx10603-the-algorithm-hs256-requires-the-securitykey-keysize-to-be-greater var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature); var header = new JwtHeader(signingCredentials); var secToken = new JwtSecurityToken(header, payload); // 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式) var tokenHandler = new JwtSecurityTokenHandler(); //var securityToken = tokenHandler.CreateToken(tokenDescriptor); var serializeToken = tokenHandler.WriteToken(secToken); return serializeToken; } public static string CreateApiToken(string issuer, string id, string salt,string name,List auth , string schoolID = "", int expire = 1) { // 設定要加入到 JWT Token 中的聲明資訊(Claims) var payload = new JwtPayload { { JwtRegisteredClaimNames.Iss, issuer }, //發行者 iss: jwt签发者 { JwtRegisteredClaimNames.Sub, id }, // APPID sub: jwt所面向的用户 { JwtRegisteredClaimNames.Aud, "" }, // aud: 接收jwt的一方 { JwtRegisteredClaimNames.Azp,schoolID}, // 學校簡碼,如果有的話 {JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString() }, { "name",name}, // 用戶的顯示名稱 //{ JwtRegisteredClaimNames.Exp,DateTimeOffset.UtcNow.AddHours(expire).ToUnixTimeSeconds().ToString()}, // 到期的時間,必須為數字 //{ "name",name}, // 用戶的顯示名稱 //{ "picture",picture}, // 用戶頭像 { "auth",auth}, // 登入者的角色,角色類型 (Admin、Teacher、Student) // { "permissions",permissions} //登入者的權限請求 }; // 建立一組對稱式加密的金鑰,主要用於 JWT 簽章之用 var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt)); // HmacSha256 有要求必須要大於 128 bits,所以 salt 不能太短,至少要 16 字元以上 // https://stackoverflow.com/questions/47279947/idx10603-the-algorithm-hs256-requires-the-securitykey-keysize-to-be-greater var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature); var header = new JwtHeader(signingCredentials); var secToken = new JwtSecurityToken(header, payload); // 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式) var tokenHandler = new JwtSecurityTokenHandler(); //var securityToken = tokenHandler.CreateToken(tokenDescriptor); var serializeToken = tokenHandler.WriteToken(secToken); return serializeToken; } public static bool ValidateApiToken(string token, string salt) { try { var handler = new JwtSecurityTokenHandler(); var validationParameters = new TokenValidationParameters { RequireExpirationTime = false, 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) { //Trace.WriteLine(ex.Message); return false; } } public static bool ValidateAuthToken(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) { //Trace.WriteLine(ex.Message); return false; } } } }