Как передать / проверить токен Open ID между основным веб-приложением. net и веб-интерфейсом? - PullRequest
0 голосов
/ 10 января 2020

У нас есть следующая архитектура:

  • . NET веб-приложение core 3.1 с использованием бритвенных страниц, jQuery, et c в качестве пользовательского интерфейса (не приложение angular)
  • . NET core 3.1 веб-API-приложение, выступающее в качестве нашего API-слоя
  • Okta в качестве нашего поставщика удостоверений

Я реализовал виджет и промежуточное ПО Okta в сети применение. Пользователи могут войти в систему, и после этого я могу получить ClaimsPrincipal, получить доступ ко всем их областям действия и получить любые пользовательские данные профиля, которые я сохранил через открытый идентификатор. Я могу обеспечить просмотр через украшение [Авторизация]. Все, что работает отлично.

Теперь мне нужно выполнить проверки безопасности на стороне API. Я часами смотрел на примеры и нашел много, но я либо упускаю что-то очевидное, либо то, что я делаю, уникально (и я не могу представить, что то, что я делаю, уникально). В основном мне нужно сделать следующее:

  • Попросить веб-приложение передать токены auth и id в api
  • Пусть api сможет проверить токен и затем расшифровать информацию о пользователе. из идентификатора токена

Это позволило бы мне реализовать необходимые логи безопасности c на стороне API. Допустим, это API, который возвращает заказы клиентов - ну, мне нужно убедиться, что пользователь, который его называет, является либо администратором, либо фактическим клиентом (поэтому я не возвращаю данные клиента кому-то, кто не должен его видеть). У меня есть все ролевые вещи, я просто не могу, на всю жизнь, понять, как определить, кто является кем-то через токен?

Передача токенов довольно проста, но как бы я получить токен из объекта ClaimsPrincipal? Или мне нужно вызвать API Okta после того, как пользователь войдет в систему, чтобы конкретно получить токены доступа и идентификатора?

Тогда, конечно, мне придется выяснить, как заставить сторону API правильно проверять и анализировать токен, который отправляется.

Если бы кто-нибудь мог помочь мне начать с этим или указать мне правильное направление для примера, я был бы очень признателен. На данный момент я прочитал каждую статью о Owin, OpenID, Okta, авторизации в. net ядре, которое смог найти.

Ответы [ 2 ]

1 голос
/ 13 января 2020

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

Если вы используете Okta, вы можете сделать все это через пакет промежуточного программного обеспечения Okta. Вы можете сделать это, просто используя библиотеку c# OpenID, но библиотека Okta.AspNetCore поможет вам в этом.

Сначала вы зарегистрируете промежуточное ПО в веб-приложении. Okta имеет множество примеров этого на своем сайте, и это довольно просто.

В вашем веб-приложении вы можете использовать это для получения токена (после того, как пользователь, конечно, прошел аутентификацию)

await context.HttpContext?.GetTokenAsync("id_token")

Отправьте это вместе с вашими вызовами API как часть заголовка, используя стандартный механизм:

"Authorization" : "Bearer [token]"

На стороне веб-API вы используете тот же пакет промежуточного программного обеспечения Okta.AspNetCore и можете затем украсить свои контроллеры с помощью [Авторизировать], чтобы обеспечить аутентификацию на них. Вот где я споткнулся. Если вы не используете сервер аутентификации по умолчанию в Okta и настроили пользовательский сервер для своего приложения, вам нужно указать c it и аудиторию в вашей конфигурации:

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = OktaDefaults.ApiAuthenticationScheme;
                options.DefaultChallengeScheme = OktaDefaults.ApiAuthenticationScheme;
                options.DefaultSignInScheme = OktaDefaults.ApiAuthenticationScheme;
            })
            .AddOktaWebApi(new OktaWebApiOptions()
            {
                OktaDomain = oktaDomain,
                AuthorizationServerId = authServerId,
                Audience = clientId
            });

            services.AddAuthorization();

Я полностью забыл об аудитории - и с тем, как работает проверка токена, эта часть обязательна.

Оттуда промежуточное программное обеспечение позаботится о заполнении ClaimsPrincipal для вас, чтобы вы могли получить доступ к пользовательской информации через ClaimsPrincipal (HttpContext.User). Я закончил тем, что создал «CurrentUserService» и вытащил его в свою собственную библиотеку, чтобы я мог консолидировать там все свои обработчики аутентификации; тем самым позволяя моему веб-приложению и коду веб-API проверять разрешения и таким же образом получать информацию о текущем пользователе. Этот код здесь, если вы заинтересованы:

    public interface ICurrentUserService
    {
        public ClaimsPrincipal GetCurrentUser();

        public string GetCurrentUserDisplayName();

        public string GetCurrentUserFullName();

        public string GetCurrentUserId();

        public DateTime? GetCurrentUserDob();

        public string GetCurrentUserGender();

        public AddressFromClaimsDTO GetCurentUserAddress();

        public bool IsAuthenticated();
    }

    public class CurrentUserService : ICurrentUserService
    {

        private const string FULL_ADDRESS_CLAIM_TYPE = "address";

        private readonly IHttpContextAccessor _context;

        public CurrentUserService(IHttpContextAccessor context)
        {
            _context = context;
        }

        /// <summary>
        /// Gets whether or not the current user context is authenticated.
        /// </summary>
        /// <returns></returns>
        public bool IsAuthenticated()
        {
            return GetCurrentUser().Identity.IsAuthenticated;
        }

        /// <summary>
        /// Gets the current user's address.
        /// TODO: tie this into our address data model... but if addresses live in Okta what does that mean?
        /// </summary>
        /// <returns></returns>
        public AddressFromClaimsDTO GetCurentUserAddress()
        {
            var addressClaim = GetClaim(FULL_ADDRESS_CLAIM_TYPE);

            if (addressClaim != null)
            {
                //var parseValue = addressClaim.Value.ToString().Replace("{address:", "{\"address\":");
                var address = JsonSerializer.Deserialize<AddressFromClaimsDTO>(addressClaim.Value.ToString());
                return address;
            }
            else
            {
                return new AddressFromClaimsDTO();
            }
        }

        public ClaimsPrincipal GetCurrentUser()
        {
            return _context.HttpContext.User;
        }

        public string GetCurrentUserDisplayName()
        {
            return GetCurrentUser().Identity.Name;
        }

        public string GetCurrentUserFullName()
        {
            throw new NotImplementedException();
        }

        public string GetCurrentUserId()
        {
            throw new NotImplementedException();
        }

        public DateTime? GetCurrentUserDob()
        {
            var claim = GetClaim("birthdate");

            if (claim != null && !string.IsNullOrEmpty(claim.Value))
            {
                return DateTime.Parse(claim.Value);
            }
            else
            {
                return null;
            }
        }

        public string GetCurrentUserGender()
        {
            return GetClaim("gender")?.Value.ToString();
        }


        public Claim GetClaim(string claimType)
        {
            return _context.HttpContext.User.FindFirst(x => x.Type == claimType);
        }

    }
0 голосов
/ 10 января 2020

Ваш провайдер идентификаторов, в данном случае Okta, выдаст токен-носитель авторизации OpenID Connect, который вам нужно будет передать любому приложению, которое вы хотите защитить.

На стороне Web Api вашего приложения вам необходимо зарегистрировать свое промежуточное программное обеспечение для обработки обработки токенов OpenID Connect Okta. Затем вы можете украсить свои контроллеры / действия с помощью [Authorize] и проверить утверждения личности.

...