Кілька доступних жетонів доступу до Oauth2


13

У мене є API, який використовує oAuth2 та власні мобільні додатки, які використовують цей API як резервний. Оскільки користувачі можуть одночасно входити через кілька пристроїв (наприклад, iPhone, iPad, планшетний ПК або телефон Android), мені потрібен API, щоб розрізняти кожне з'єднання. Я хотів би зробити це через окремі маркери доступу: кожен клієнт отримує окремий маркер доступу.

Проблема полягає в тому, що поточна реалізація, яку ми використовуємо (spring-security-oauth2), генерує унікальний ключ на основі client_id, ім’я користувача та область. Отже, отримуючи маркер доступу, усі клієнти отримують однаковий маркер доступу для одного і того ж користувача. Це робиться за допомогою DefaultAuthenticationKeyGenerator.

Чи безпечно ігнорувати генератор ключів аутентифікації та просто створити новий маркер доступу для кожного запиту клієнта?


2
Ви можете використовувати область для диференціації кожного клієнта? тобто надайте ios область "ios", андроїд - "андроїд" сфера, планшет - "планшет", сфера застосування і т. д. Але FWIW я закінчив написання власної реалізації 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" тощо
Vikash Rajpurohit

Відповіді:


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")
                    ........

        }

У бекенді ви можете отримати ID клієнта, як описано нижче

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

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


0

Одна відповідь полягає в тому, що кожна платформа додатків - це інший клієнт, тому має бути різний ідентифікатор клієнта. Один для програми iOS, один для веб-сайту тощо.

Щодо розмежування скажімо iPad від iPhone, я б запропонував не покладатися на це на системі OAuth.


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}}

Перевага використання цього підходу полягає в тому, що якщо клієнт не надсилає a client_instance_id, буде створений ключ за замовчуванням, а якщо надається екземпляр, той самий ключ повертається кожен раз для одного і того ж екземпляра. Також ключ - незалежний від платформи. Мінусом було б те, що дайджест MD5 (використовується внутрішньо) викликається два рази.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.