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.