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;
using System.ComponentModel;
namespace TEAMModelOS.SDK.Extension
{
public static class JwtAuthExtension
{
public static string CreateAuthToken(string issuer, string id, string name, string picture, string salt, string scope, string Website,int timezone, string areaId = "", string schoolID = "", string standard = "", string[] roles = null, string[] permissions = null, int expire = 1,int year=-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()}, // 到期的時間,必須為數字
{ "name",name}, // 用戶的顯示名稱
{ "picture",picture}, // 用戶頭像
{ "roles",roles}, // 登入者的角色,角色類型 (Admin、Teacher、Student)
{ "permissions",permissions}, //登入者的權限請求
{ "standard",standard} ,//登入者的能力点标准
{ "scope",scope}, //登入者的入口类型。 (teacher 教师端登录的醍摩豆ID、tmduser学生端登录的醍摩豆ID、student学生端登录校内账号的学生ID)
{ "area",areaId==null?"":areaId},
{ "timezone",timezone},
{ JwtRegisteredClaimNames.Website,Website},
};
//学生入学年
if (year!=-1) {
payload.Add("year", year);
}
// 建立一組對稱式加密的金鑰,主要用於 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 signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
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;
}
///
///
///
/// 颁发者
/// 第三方合作uuid
///
///
///
public static (string jwt , string jti) CreateBusinessApiToken(string location, string id, string salt,int customize = 0 )
{
string scope = "business";
if (customize != 0)
scope = "customize";
var keys = OpenApiJtwIssuer.OpenApiJtw签发者.GetDescriptionText().Split(',');
string issuer = "";
if (location.Equals("China-Dep"))
{
issuer = keys[0];
}
else if (location.Equals("China-Test"))
{
issuer = keys[0];
}
else if (location.Equals("China"))
{
issuer = keys[1];
}
else if (location.Equals("Global-Dep"))
{
issuer = keys[2];
}
else if (location.Equals("Global-Test"))
{
issuer = keys[2];
}
else if (location.Equals("Global"))
{
issuer = keys[3];
}
string jti = Guid.NewGuid().ToString();
// 設定要加入到 JWT Token 中的聲明資訊(Claims)
var payload = new JwtPayload {
{ JwtRegisteredClaimNames.Iss, issuer }, //發行者 iss: jwt签发者
{ JwtRegisteredClaimNames.Sub, id }, // APPID sub: jwt所面向的用户
{JwtRegisteredClaimNames.Jti, jti},
{ "scope",scope}
};
// 建立一組對稱式加密的金鑰,主要用於 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 signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
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,jti);
}
///
///
///
/// 颁发者
/// 第三方合作uuid
///
///
///
public static (string jwt, string jti) CreateSchoolApiToken(string location, string id, string salt,List auth, string schoolID = "")
{
string scope = "school";
var keys = OpenApiJtwIssuer.OpenApiJtw签发者.GetDescriptionText().Split(',');
string issuer = "";
if (location.Equals("China-Dep"))
{
issuer = keys[0];
}
else if (location.Equals("China-Test"))
{
issuer = keys[0];
}
else if (location.Equals("China"))
{
issuer = keys[1];
}
else if (location.Equals("Global-Dep"))
{
issuer = keys[2];
}
else if (location.Equals("Global-Test"))
{
issuer = keys[2];
}
else if (location.Equals("Global"))
{
issuer = keys[3];
}
string jti = Guid.NewGuid().ToString();
// 設定要加入到 JWT Token 中的聲明資訊(Claims)
var payload = new JwtPayload {
{ JwtRegisteredClaimNames.Iss, issuer }, //發行者 iss: jwt签发者
{ JwtRegisteredClaimNames.Sub, id }, // APPID sub: jwt所面向的用户
{JwtRegisteredClaimNames.Jti, jti},
{ "scope",scope},
{ "auth",auth},
{ JwtRegisteredClaimNames.Azp,schoolID}, // 學校簡碼,如果有的話
};
// 建立一組對稱式加密的金鑰,主要用於 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 signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
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, jti);
}
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()}, // 到期的時間,必須為數字
//{ "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 signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
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;
}
}
///
/// 刷新token,不验证过期时间
///
///
///
///
public static bool ValidateAuthTokenRefresh(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 = true,
ClockSkew = TimeSpan.Zero
};
ClaimsPrincipal principal = handler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
return true;
}
catch (Exception)
{
//Trace.WriteLine(ex.Message);
return false;
}
}
///
/// 第三方登录后的id_token
///
///
///
///
///
///
///
///
///
///
///
public static string CreateBizLoginAuthToken(string issuser, string id, string name, string picture, string webSite, string salt, string[] roles = null, string[] permissions = null, int expire = 1)
{
var payload = new JwtPayload
{
{ JwtRegisteredClaimNames.Iss,issuser}, //发行者
{ JwtRegisteredClaimNames.Sub,id}, //用户ID
{ JwtRegisteredClaimNames.Exp,DateTimeOffset.UtcNow.AddHours(expire).ToUnixTimeSeconds()},//到期时间
{ "name",name},//用户显示名称
{ "picture",picture}, // 用户头像
{ "roles",roles}, //登陆者的角色, (admin、dea)
{ "permissions",permissions}, //登陆者的权限
{ JwtRegisteredClaimNames.Website,webSite}, // 平台站点
};
// 建立加密的秘钥
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 signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
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 enum OpenApiJtwIssuer
{
[Description("open-test.teammodel.cn,open.teammodel.cn,open-test.teammodel.net,open.teammodel.net")]
OpenApiJtw签发者,
}
}