Android/IOS Секретное управление истечением с потоком учетных данных клиента

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

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

Я видел, что есть способы безопасного хранения секретов, по крайней мере, в приложениях для Android, но как вы управляете истечением срока действия секрета, не публикуя новую версию приложения?

2 ответа

Решение

Вот как мы сделали в нашем приложении следующие стандарты OAuth Refresh Token.

Шаг 1. Ваш API должен отправлять стандартный ответ токена аутентификации, как указано здесь

 HTTP/1.1 200 OK
 Content-Type: application/json;charset=UTF-8
 Cache-Control: no-store
 Pragma: no-cache

 {
   "access_token":"2YotnFZFEjr1zCsicMWpAA",
   "token_type":"example",
   "expires_in":3600,
   "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
   "example_parameter":"example_value"
 }

Шаг 2: Сохраните этот ответ в Shared Preferences/Local Cache/Local Database, мы использовали Shared Preferences (при условии accountToken объект класса, созданный из Response of Auth Token)

SharedPreferences.Editor editor = getContext().getSharedPreferences("AUTH_PREFS_NAME", Context.MODE_PRIVATE).edit();
editor.putString("AUTH_ACCESS_TOKEN_KEY", accountToken.getAccess_token());
editor.putString("AUTH_REFRESH_TOKEN_KEY", accountToken.getRefresh_token());
editor.putLong("AUTH_EXPIRES_IN_KEY", accountToken.getExpires_in());
editor.putLong("AUTH_TIME_SAVED_KEY", ((int) (System.currentTimeMillis() / 1000)));
editor.commit();

Шаг 3: Каждый раз, когда вам нужно использовать сохраненный токен доступа, убедитесь, что он не истек

public boolean needsTokenRefresh(String accessToken) {
    if (accessToken == null || accessToken.length() == 0) {
        // no access token to refresh. Don't refresh.
        return false;
    }

    SharedPreferences pref = mContext.getSharedPreferences("AUTH_PREFS_NAME", Context.MODE_PRIVATE);
    String refreshToken = pref.getString("AUTH_REFRESH_TOKEN_KEY", null);
    if (refreshToken == null || refreshToken.length() == 0) {
        // no refresh token. Can't refresh.
        return false;
    }

    Integer timeSaved = pref.getInt("AUTH_TIME_SAVED_KEY", 0);
    if (timeSaved == 0) {
        // No recording of having saved the token. Don't refresh.
        return false;
    }

    long expiresIn = pref.getLong("AUTH_EXPIRES_IN_KEY", 0);
    int now = (int) (System.currentTimeMillis() / 1000);
    int timePassed = Math.abs(now - timeSaved);
    boolean expired = false;
    if (expiresIn <= timePassed) {
        expired = true;
    }
    return expired;
}

Если needsTokenRefresh() возвращается false затем используйте сохраненный токен авторизации. Если он вернется true затем перейдите к следующему шагу.

Шаг 4. Сделайте повторный вызов с помощью grant_type установить как refresh_token как указано в стандартах

Шаг 5: вызов Auth должен вернуть стандартный ответ Auth, как описано в шаге 1, с обновленным токеном и новым refresh_token

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

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