Вопрос аутентификации на основе токенов OAuth 2.0 о хранении значений токенов - PullRequest
0 голосов
/ 21 сентября 2019

Я реализовал аутентификацию на основе токенов OAuth в нашем приложении WebAPI и проверяю имя пользователя и пароль по базе данных.Но мы не синхронизируем токены доступа и не обновляем токены для базы данных любого типа.Вот код, однако у меня есть один вопрос, где хранятся значения токенов.

Ниже код для генерации токена

        /// <summary>  
        /// Grant resource owner credentials overload method.  
        /// </summary>  
        /// <param name="context">Context parameter</param>  
        /// <returns>Returns when task is completed</returns>  
        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            // Initialization.  
            var usernameVal = context.UserName;
            var passwordVal = context.Password;
            var user = _securityLogic.AuthenticateApiUser(usernameVal, passwordVal);

            // Verification.  
            if (!user)
            {
                // Settings.  
                context.SetError("invalid_grant", "The user name or password is incorrect.");

                // Return info.  
                return;
            }

            // Initialization.  
            var claims = new List<Claim>
            {
                //var userInfo = user.FirstOrDefault();

                // Setting  
                new Claim(ClaimTypes.Name, usernameVal)
            };

            // Setting Claim Identities for OAUTH 2 protocol.  
            ClaimsIdentity oAuthClaimIdentity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
            ClaimsIdentity cookiesClaimIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationType);

            // Setting user authentication.  
            AuthenticationProperties properties = CreateProperties(usernameVal);
            AuthenticationTicket ticket = new AuthenticationTicket(oAuthClaimIdentity, properties);

            // Grant access to authorize user.  
            context.Validated(ticket);
            context.Request.Context.Authentication.SignIn(cookiesClaimIdentity);
        }
        #endregion

        #region Token endpoint override method.  
        /// <summary>  
        /// Token endpoint override method  
        /// </summary>  
        /// <param name="context">Context parameter</param>  
        /// <returns>Returns when task is completed</returns>  
        public override Task TokenEndpoint(OAuthTokenEndpointContext context)
        {
            foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
            {
                // Adding.  
                context.AdditionalResponseParameters.Add(property.Key, property.Value);
            }

            // Return info.  
            return Task.FromResult<object>(null);
        }
        #endregion

Это код для генерации токена обновления

        #region GrantRefreshToken

        private static readonly ConcurrentDictionary<string, AuthenticationTicket> RefreshTokens =
        new ConcurrentDictionary<string, AuthenticationTicket>();

        /// <summary>
        /// Grants Refresh Token 
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override Task GrantRefreshToken(OAuthGrantRefreshTokenContext context)
        {
            // Change authentication ticket for refresh token requests  
            var newIdentity = new ClaimsIdentity(context.Ticket.Identity);
            // newIdentity.AddClaim(new Claim("newClaim", "newValue"));

            var newTicket = new AuthenticationTicket(newIdentity, context.Ticket.Properties);
            context.Validated(newTicket);

            return Task.FromResult<object>(null);
        }

        public async Task CreateAsync(AuthenticationTokenCreateContext context)
        {
            var guid = Guid.NewGuid().ToString();

            // Copy claims from the previous token
            var refreshTokenProperties = new AuthenticationProperties(context.Ticket.Properties.Dictionary)
            {
                IssuedUtc = context.Ticket.Properties.IssuedUtc,
                ExpiresUtc = DateTime.UtcNow.AddMinutes(30)
            };

            var refreshTokenTicket = await Task.Run(() =>
                new AuthenticationTicket(context.Ticket.Identity, refreshTokenProperties));

            RefreshTokens.TryAdd(guid, refreshTokenTicket);

            // Consider storing only the hash of the handle  
            context.SetToken(guid);
        }
        #endregion

Итак, мой вопрос .NET / Owin / IdentityServer3записать их в какую-нибудь базу данных в памяти?Если да, могут ли они быть доступны для таких вещей, как просмотр и удаление?И что произойдет, если сервер приложений будет перезапущен, все токены уничтожены?Или они постоянны?

И вы рекомендуете хранить их в базе данных и извлекать из базы данных?Любая помощь приветствуется, кстати, этот код работает отлично.

1 Ответ

1 голос
/ 22 сентября 2019

Из документации :

Если специально не настроено, мы всегда будем предоставлять хранилища версий в памяти для кодов авторизации, согласия, ссылки и токенов обновления.

Обратите внимание, что они говорят о эталонных токенах и токенах обновления .Токены доступа JWT и токены идентификации не сохраняются.

Чтобы использовать токен обновления в IdentityServer3 (а также IdentityServer4 ), он должен соответствовать сохраненному токену.

Основным преимуществом этого является то, что вы можете контролировать токен.Вы можете отозвать его (удалить из хранилища) и определить, как его использовать: OneTime или ReUse.

Я не знаком с IdentityServer3, но вы можете взглянуть на github и найти код, где RevocationEndpoint - место, где токен обновления удален из хранилища.Это может дать подсказку о том, как получить доступ и использовать хранилище.

При хранении в памяти токены теряются при перезапуске IdentityServer.Поэтому сохранение их в постоянном хранилище, например в базе данных, - хорошая вещь для производственных серверов.Для IdentityServer4 вы можете реализовать оперативное хранилище .

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

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

Говоря о IdentityServer4, так как (бесплатная) поддержка IdentityServer3 имеет закончилась Я бы порекомендовал переключиться на IdentityServer4, если вы находитесь вположение, чтобы сделать это.Поскольку обе версии реализуют oidc / auth2, вы сможете продолжать использовать клиенты с обновленным IdentityServer.На stackoverflow есть вопросы, которые могут помочь вам в этом.И взгляните на документацию IdentityServer4, она очень информативна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...