Использование JWT с секретным ключом для обработки единого входа

У меня есть работающий веб-сайт только для членов, который работает так, как должен, с входом в систему и т. д. Теперь мне нужно поддерживать единый вход, где я получу имя пользователя профиля в токене JWT, а затем войду в систему. Внешняя система, которая отправит этот запрос, НЕ знает никакой другой информации, кроме имени пользователя, поэтому пароль не передается в токен, и это невозможно.

JWT был выбран в качестве предпочтительного метода для обеспечения этого. Мы собираемся использовать секретный ключ для обмена информацией, секретный ключ, конечно же, известен только отправителю и получателю.

Я ищу простой пример того, как это может выглядеть с точки зрения кода, как на стороне отправителя, так и на стороне получателя. Концом получателя будет конечная точка WebAPI, которая будет обрабатывать вход в систему, а затем перенаправлять на главную страницу веб-сайта только для членов, если вход в систему выполнен успешно.

Он разработан на C#.

«Я ищу простой пример того, как это может выглядеть с точки зрения кода» — такой вещи не существует: просто слишком много движущихся частей. Кроме того, пожалуйста, уточните, что именно вы подразумеваете под «единым входом», потому что тот факт, что вы используете JWT, не означает, например, что вы используете свой собственный IdP OIDC.

Dai 20.11.2022 03:45

Ваши сети csr или ssr с C#? Сколько веб-сайтов и микросервисов в вашей инфраструктуре? Вы ищете стратегию предприятия или просто poc?

JRichardsz 20.11.2022 03:50

@JRichardsz это SSR с C# на приемном конце. Просто простой POC, чтобы помочь с моим собственным пониманием лучшего решения и способа справиться с задачей. У меня есть сам логин, поэтому у меня есть код, который может принимать только имя пользователя, а затем регистрировать пользователя. Шаг, который мне не хватает, — это шифрование и дешифрование данных JWT с использованием секретного ключа.

brother 20.11.2022 08:28
[JS за 1 час] - 9. Асинхронный
[JS за 1 час] - 9. Асинхронный
JavaScript является однопоточным, то есть он может обрабатывать только одну задачу за раз. Для обработки длительных задач, таких как сетевые запросы,...
Топ-10 компаний-разработчиков PHP
Топ-10 компаний-разработчиков PHP
Если вы ищете надежных разработчиков PHP рядом с вами, вот список лучших компаний по разработке PHP.
Скраппинг поиска Apple App Store с помощью Python
Скраппинг поиска Apple App Store с помощью Python
📌Примечание: В этой статье я покажу вам, как скрапировать поиск Apple App Store и получить точно такой же результат, как на Apple iMac, потому что...
Редкие достижения на Github ✨
Редкие достижения на Github ✨
Редкая коллекция доступна в профиле на GitHub ✨
Подъем в javascript
Подъем в javascript
Hoisting - это поведение в JavaScript, при котором переменные и объявления функций автоматически "перемещаются" в верхнюю часть соответствующих...
Улучшение генерации файлов Angular
Улучшение генерации файлов Angular
Angular - это фреймворк. Вы можете создать практически любое приложение без использования сторонних библиотек.
0
3
120
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Элементарные советы

  • Обычно и часто пользователь/пароль заменяются на новый JWT.

  • JWT не должен хранить ничего разумного, например, пароль. Но некоторые компании вроде Microsoft хранят не осмысленные значения, а много информации https://gist.github.com/jrichardsz/6512f9b2b4c38620bf00e24c71b6cf2d

  • Для предприятий процесс шифрования и дешифрования не должен выполняться на уровне микросервиса. Это должно выполняться другим сервером, например: Auth0, okta, Keycloack и т. д.

  • Ваш микросервис только получает токен и отправляет его на платформу безопасности. Лучший способ сделать это — использовать промежуточное ПО на любом языке. Это для c#

  • Платформа безопасности возвращает ответ с данными в синтаксисе, который клиент (С# в вашем случае) понимает, является ли токен законным, действительным, не просроченным, существует пользователь, пользователю разрешено выполнять операцию и т. д. Я использовал это в некоторой реализации в на что я сказал: «Пользователю разрешено выполнять эту операцию, и это его имя пользователя»

    Конечная точка: acme-security.com/v1/oauth2/token/validate

    Просьба: eyJ0eXAiOiJKV1Qi...

    Отклик:

    {
    "isAllowed": true,
    "subject": "jane@blindspot.com"
    }
    
  • Также вы можете сделать это с помощью API-шлюза.

  • В более реальном сценарии нам нужно больше, чем простая проверка jwt. Нам нужно убедиться, что пользователю admin/guest разрешено выполнять определенные конечные точки. Мы не хотим, чтобы сотрудник напрямую вызывал конечную точку платежа, устанавливающую свою зарплату :/

  • Следуйте спецификации oauth2, если вы будете внедрять собственную платформу безопасности.

  • Jwt должен быть отправлен как заголовок авторизации

  • ВАЖНО: если вы будете реализовывать собственную генерацию и проверку jwt, используйте переменные ENV, чтобы скрыть секрет и максимально защитить его для вашей производственной среды.

Обработка JWT с С# netcore 5

Если предыдущие шаги понятны, вам нужен только один из этих подходов:

  • Используйте некоторые платформы IAM или безопасности, такие как auth0, okta, keycloack и т. д.
  • Простой С# web/microservice/api (который также функционирует как платформа безопасности) для получения токена и возврата, если пользователю разрешено
  • Класс для проверки внутри целевого микросервиса

Генерация JWT

public string GenerateToken(User user)
{
    // generate token that is valid for 7 days
    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.ASCII.GetBytes(SUPER_SECRET_KEY);
    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(new[] { new Claim("id", user.Id.ToString()) }),
        Expires = DateTime.UtcNow.AddDays(7),
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    };
    var token = tokenHandler.CreateToken(tokenDescriptor);
    return tokenHandler.WriteToken(token);
}

JWT-декодирование или проверка

public int? ValidateToken(string token)
{
    if (token == null) 
        return null;

    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.ASCII.GetBytes(SUPER_SECRET_KEY);
    try
    {
        tokenHandler.ValidateToken(token, new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(key),
            ValidateIssuer = false,
            ValidateAudience = false,
            // set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
            ClockSkew = TimeSpan.Zero
        }, out SecurityToken validatedToken);

        var jwtToken = (JwtSecurityToken)validatedToken;
        var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value);

        // return user id from JWT token if validation successful
        return userId;
    }
    catch
    {
        // return null if validation fails
        return null;
    }
}

Источник: https://jasonwatmore.com/post/2021/06/02/net-5-create-and-validate-jwt-tokens-use-custom-jwt-middleware

Этот код выдает ошибки, когда срок действия токена истек или какой-то приятель пытается отправить jwt без вашего SUPER_SECRET_KEY.

Вы можете использовать эти фрагменты непосредственно при генерации токенов и внутри своих конечных точек.

[HttpGet]
public ActionResult<List<Dictionary<string, object>>> findAllEmployees()
{
    //get jwt from http received headers
    validationResponse = ValidateToken(jwt)
    //if you have a security platform, callhere instead
    //ValidateToken(jwt)
    //if validationResponse.isAllowed ....
    var list = this.employeeService.findAllEmployees();
    return Ok(list);
}

Или с промежуточным программным обеспечением, таким как профессионал, чтобы содержать в чистоте ваши окончательные контроллеры

Лекции

Другие вопросы по теме