Несколько токенов доступа Oauth2

13

У меня есть API, который использует oAuth2, и мои собственные мобильные приложения, которые используют этот API в качестве своего бэкэнда. Поскольку пользователи могут входить в систему одновременно с нескольких устройств (например, iPhone, iPad, планшета Android или телефона Android), мне нужен API, чтобы различать каждое соединение. Я хотел бы сделать это через отдельные токены доступа: каждый клиент получает отдельный токен доступа.

Проблема в том, что текущая реализация, которую мы используем (spring-security-oauth2), генерирует уникальный ключ на основе client_id, username и scope. Таким образом, при получении токена доступа все клиенты получают одинаковый токен доступа для одного и того же пользователя. Это делается с помощью DefaultAuthenticationKeyGenerator.

Безопасно ли игнорировать генератор ключей аутентификации и просто создавать новый токен доступа при каждом запросе от клиента?

контрольный список
источник
2
Вы можете использовать область, чтобы дифференцировать каждого клиента? т.е. дать ios область «ios», android область «android», планшет - область «tablet» и т. д. Но в итоге я написал свою собственную реализацию TokenServices (на самом деле я думаю, что сделал ее оберткой по умолчанию), что генерирует новый токен каждый раз.
Роб
В целом, хотя реализация Spring Security OAuth2 для меня работала хорошо (как только я прошел через конфигурацию XML), но управление токеном и объектами аутентификации было постоянной проблемой.
Роб
2
Поиск в Google «DefaultAuthenticationKeyGenerator» привел меня к файлу .java в библиотеке spring-security-oauth на GitHub. Этот класс реализует AuthenticationKeyGeneratorинтерфейс. Не могли бы вы создать свою собственную реализацию и использовать ее вместо этого?
Грег Бургхардт
URL-адрес файла .java, который я нашел: github.com/spring-projects/spring-security-oauth/blob/master/…
Грег Бургхардт
2
Я согласен с @Rob, вы можете использовать devicetype в запросе типа "android", "ios", "web" и т. Д.
Викаш Раджпурохит

Ответы:

1

Весеннее облако обеспечивает уже такое поведение. Просто добавьте разных клиентов. Как и iosAppClient, androidAppClient в вашем классе AuthorizationServerConfiguration.

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
                clients.inMemory().withClient("androidAppclient")
                    .secret("clientsecret")
                    .autoApprove(true)
                    .accessTokenValiditySeconds(120)
                    .authorizedGrantTypes("password")
                    .resourceIds("accountservice")
                    .scopes("read", "write")
                    .and()
                    .withClient("iosappclient")
                    ........

        }

В бэкэнде вы можете получить clientID, как показано ниже

clientId = ((OAuth2Authentication) authentication).getOAuth2Request().getClientId();

и реализовать другое поведение на основе clientId.

Rocks360
источник
0

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

Что касается различия между iPad и iPhone, я бы предложил не полагаться на систему OAuth для этого.

RibaldEddie
источник
0

Я столкнулся с той же проблемой при разработке моего бэкенда с Spring Boot и OAuth2. Проблема, с которой я столкнулся, заключалась в том, что если несколько устройств совместно использовали одни и те же токены, то, как только одно устройство обновляло токен, другое устройство было бы невежественным, и, короче говоря, оба устройства входили в безумие обновления токена. Мое решение состояло в том, чтобы заменить стандартную AuthenticationKeyGeneratorреализацию пользовательской реализацией, которая переопределяет DefaultAuthenticationKeyGeneratorи добавляет новый параметр client_instance_idв смесь генератора ключей. Мои мобильные клиенты затем отправляют этот параметр, который должен быть уникальным при установке приложений (iOS или Android). Это не специальное требование, так как большинство мобильных приложений уже отслеживают экземпляр приложения в той или иной форме.

public class EnhancedAuthenticationKeyGenerator extends DefaultAuthenticationKeyGenerator {

    public static final String PARAM_CLIENT_INSTANCE_ID = "client_instance_id";

    private static final String KEY_SUPER_KEY = "super_key";
    private static final String KEY_CLIENT_INSTANCE_ID = PARAM_CLIENT_INSTANCE_ID;

    @Override
    public String extractKey(final OAuth2Authentication authentication) {
        final String superKey = super.extractKey(authentication);

        final OAuth2Request authorizationRequest = authentication.getOAuth2Request();
        final Map<String, String> requestParameters = authorizationRequest.getRequestParameters();

        final String clientInstanceId = requestParameters != null ? requestParameters.get(PARAM_CLIENT_INSTANCE_ID) : null;
        if (clientInstanceId == null || clientInstanceId.length() == 0) {
            return superKey;
        }

        final Map<String, String> values = new LinkedHashMap<>(2);
        values.put(KEY_SUPER_KEY, superKey);
        values.put(KEY_CLIENT_INSTANCE_ID, clientInstanceId);

        return generateKey(values);
    }

}

который вы затем вводите аналогичным образом:

final JdbcTokenStore tokenStore = new JdbcTokenStore(mDataSource);
tokenStore.setAuthenticationKeyGenerator(new EnhancedAuthenticationKeyGenerator());

HTTP-запрос будет выглядеть примерно так

POST /oauth/token HTTP/1.1
Host: {{host}}
Authorization: Basic {{auth_client_basic}}
Content-Type: application/x-www-form-urlencoded

grant_type=password&username={{username}}&password={{password}}&client_instance_id={{instance_id}}

Преимущество использования этого подхода состоит в том, что, если клиент не отправляет client_instance_id, будет создан ключ по умолчанию, и если предоставляется экземпляр, один и тот же ключ возвращается каждый раз для одного и того же экземпляра. Кроме того, ключ не зависит от платформы. Недостатком является то, что дайджест MD5 (используется внутри) вызывается два раза.

Космин Раду
источник