, чтобы сделать ваш вопрос проще.
Идея, лежащая в основе токена, состоит в том, чтобы проанализировать токен и получить 3 части из токена
-Header : contain information about in which algorithm the token haven been encrypted
-Payload : information about the user
-Signature: it's the calculation of encryption of ( Header + Payload) using the Azure certificate or( your identity provider).
Следующий шаг - пользователь отправляет запрос на ваш сервер вместе с JWT.
Ваш бэкэнд проанализирует токен и получит тип сертификата, а затем отправит HTTP-запрос вашему провайдеру идентификации для получения сертификата
Затем ваш бэкэнд создаст опцию сертификата и попытается выполнить шифрование для (заголовка + полезной нагрузки), полученной из вашего токена, выходная строка должна быть точно такой же подписи, которую вы получили в токене от вашего внешнего интерфейса.
Если все хорошо
теперь ваш бэкэнд начнет проверять другие атрибуты, такие как Аудитория, Эмитент
если вы настраиваете свой токен для проверки аудитории, это означает, что ваш интерфейс должен предоставить токену, содержащему аудиторию (идентификатор приложения), точно такую же, как для вашего сервера, так и для эмитента.
вопрос теперь, как мой сервер знает о сертификате?
Azure AD с использованием OpenID connect, Дополнительная информация здесь
так как вы настроили своего арендатора в бэкэнде, пакет auth позвонит по номеру https://login.microsoftonline.com/{tenant}/.well-known/openid-configuration
, чтобы узнать подробности о вашем провайдере идентификации
и одна важная ссылка - ("jwks_uri": "https://login.microsoftonline.com/common/discovery/keys")
, где размещена подпись.
Вы можете прочитать и узнать больше о том, как проверить сертификат JWT и проверить это
https://codereview.stackexchange.com/questions/70005/authentication-with-jwt
переход к части 2 проверки дополнительных атрибутов.
Так как вы используете OpenIdConnect, пакет имеет класс OpenIdConnectEvents
, который позволяет запускать события и делать все, что вы захотите, как это
.AddOpenIdConnect(o =>
{
//Additional config snipped
o.Events = new OpenIdConnectEvents
{
OnTokenValidated = async ctx =>
{
//Get user's immutable object id from claims that came from Azure AD
string oid = ctx.Principal.FindFirstValue("http://schemas.microsoft.com/identity/claims/objectidentifier");
//Get EF context
var db = ctx.HttpContext.RequestServices.GetRequiredService<AuthorizationDbContext>();
//Check is user a super admin
bool isSuperAdmin = await db.SuperAdmins.AnyAsync(a => a.ObjectId == oid);
if (isSuperAdmin)
{
//Add claim if they are
var claims = new List<Claim>
{
new Claim(ClaimTypes.Role, "superadmin")
};
var appIdentity = new ClaimsIdentity(claims);
ctx.Principal.AddIdentity(appIdentity);
}
}
};
});
переход к части 3
разбор токена в javascript
function parseJwt (token) {
var base64Url = token.split('.')[1];
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
return JSON.parse(window.atob(base64));
};
разбор токена в C #
используйте эту библиотеку https://www.jsonwebtoken.io/
try {
string jsonPayload = JWT.JsonWebToken.Decode(token, secretKey);
Console.WriteLine(jsonPayload);
} catch (JWT.SignatureVerificationException) {
Console.WriteLine("Invalid token!");
}
или руководство
var jwtHandler = new JwtSecurityTokenHandler();
var jwtInput = txtJwtIn.Text;
//Check if readable token (string is in a JWT format)
var readableToken = jwtHandler.CanReadToken(jwtInput);
if(readableToken != true)
{
txtJwtOut.Text = "The token doesn't seem to be in a proper JWT format.";
}
if(readableToken == true)
{
var token = jwtHandler.ReadJwtToken(jwtInput);
//Extract the headers of the JWT
var headers = token.Header;
var jwtHeader = "{";
foreach(var h in headers)
{
jwtHeader += '"' + h.Key + "\":\"" + h.Value + "\",";
}
jwtHeader += "}";
txtJwtOut.Text = "Header:\r\n" + JToken.Parse(jwtHeader).ToString(Formatting.Indented);
//Extract the payload of the JWT
var claims = token.Claims;
var jwtPayload = "{";
foreach(Claim c in claims)
{
jwtPayload += '"' + c.Type + "\":\"" + c.Value + "\",";
}
jwtPayload += "}";
txtJwtOut.Text += "\r\nPayload:\r\n" + JToken.Parse(jwtPayload).ToString(Formatting.Indented);
}
Я надеюсь, что ответить на ваши вопросы