From 35a4b1fed9816d108097aaae1d3b6363f2a1103b Mon Sep 17 00:00:00 2001 From: M66B Date: Sat, 17 Jul 2021 13:33:25 +0200 Subject: [PATCH] Pre expire tokens --- .../java/eu/faircode/email/EmailService.java | 15 +++++++----- .../java/eu/faircode/email/GmailState.java | 13 ++++++++-- .../faircode/email/ServiceAuthenticator.java | 24 ++++++++++++++----- 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/EmailService.java b/app/src/main/java/eu/faircode/email/EmailService.java index d7c3a30eae..a9de8e181b 100644 --- a/app/src/main/java/eu/faircode/email/EmailService.java +++ b/app/src/main/java/eu/faircode/email/EmailService.java @@ -309,7 +309,7 @@ public class EmailService implements AutoCloseable { public void connect(EntityAccount account) throws MessagingException { connect( account.host, account.port, - account.auth_type, account.provider, + account.auth_type, account.provider, account.poll_interval, account.user, account.password, new ServiceAuthenticator.IAuthenticated() { @Override @@ -326,7 +326,7 @@ public class EmailService implements AutoCloseable { public void connect(EntityIdentity identity) throws MessagingException { connect( identity.host, identity.port, - identity.auth_type, identity.provider, + identity.auth_type, identity.provider, 0, identity.user, identity.password, new ServiceAuthenticator.IAuthenticated() { @Override @@ -342,14 +342,16 @@ public class EmailService implements AutoCloseable { public void connect( String host, int port, - int auth, String provider, String user, String password, + int auth, String provider, + String user, String password, String certificate, String fingerprint) throws MessagingException { - connect(host, port, auth, provider, user, password, null, certificate, fingerprint); + connect(host, port, auth, provider, 0, user, password, null, certificate, fingerprint); } private void connect( String host, int port, - int auth, String provider, String user, String password, + int auth, String provider, int keep_alive, + String user, String password, ServiceAuthenticator.IAuthenticated intf, String certificate, String fingerprint) throws MessagingException { SSLSocketFactoryService factory = null; @@ -378,7 +380,8 @@ public class EmailService implements AutoCloseable { } properties.put("mail." + protocol + ".forcepasswordrefresh", "true"); - ServiceAuthenticator authenticator = new ServiceAuthenticator(context, auth, provider, user, password, intf); + ServiceAuthenticator authenticator = new ServiceAuthenticator(context, + auth, provider, keep_alive, user, password, intf); try { if (auth == AUTH_TYPE_GMAIL || auth == AUTH_TYPE_OAUTH) { diff --git a/app/src/main/java/eu/faircode/email/GmailState.java b/app/src/main/java/eu/faircode/email/GmailState.java index c669334be5..edc01cd1bc 100644 --- a/app/src/main/java/eu/faircode/email/GmailState.java +++ b/app/src/main/java/eu/faircode/email/GmailState.java @@ -60,8 +60,17 @@ public class GmailState { return acquired + TOKEN_LIFETIME; } - void refresh(@NonNull Context context, @NonNull String user, boolean expire) throws AuthenticatorException, OperationCanceledException, IOException { - if (expire || acquired + TOKEN_LIFETIME < new Date().getTime()) + void refresh(@NonNull Context context, @NonNull String user, boolean expire, long keep_alive) + throws AuthenticatorException, OperationCanceledException, IOException { + Long expiration = getAccessTokenExpirationTime(); + if (expiration != null && expiration - keep_alive < new Date().getTime()) { + EntityLog.log(context, "Force invalidation" + + " expiration=" + new Date(expiration) + + " keep-alive=" + (keep_alive / 60 / 1000) + "m"); + expire = true; + } + + if (expire) try { if (token != null) { EntityLog.log(context, "Invalidating token user=" + user); diff --git a/app/src/main/java/eu/faircode/email/ServiceAuthenticator.java b/app/src/main/java/eu/faircode/email/ServiceAuthenticator.java index 9aada9a20f..acf2646ce8 100644 --- a/app/src/main/java/eu/faircode/email/ServiceAuthenticator.java +++ b/app/src/main/java/eu/faircode/email/ServiceAuthenticator.java @@ -47,6 +47,7 @@ public class ServiceAuthenticator extends Authenticator { private Context context; private int auth; private String provider; + private long keep_alive; private String user; private String password; private IAuthenticated intf; @@ -57,12 +58,13 @@ public class ServiceAuthenticator extends Authenticator { ServiceAuthenticator( Context context, - int auth, String provider, + int auth, String provider, int keep_alive, String user, String password, IAuthenticated intf) { this.context = context.getApplicationContext(); this.auth = auth; this.provider = provider; + this.keep_alive = keep_alive * 60 * 1000L; this.user = user; this.password = password; this.intf = intf; @@ -87,7 +89,7 @@ public class ServiceAuthenticator extends Authenticator { String refreshToken(boolean expire) throws AuthenticatorException, OperationCanceledException, IOException, JSONException, MessagingException { if (auth == AUTH_TYPE_GMAIL) { GmailState authState = GmailState.jsonDeserialize(password); - authState.refresh(context, user, expire); + authState.refresh(context, user, expire, keep_alive); Long expiration = authState.getAccessTokenExpirationTime(); if (expiration != null) EntityLog.log(context, user + " token expiration=" + new Date(expiration)); @@ -102,9 +104,7 @@ public class ServiceAuthenticator extends Authenticator { return authState.getAccessToken(); } else if (auth == AUTH_TYPE_OAUTH) { AuthState authState = AuthState.jsonDeserialize(password); - if (expire) - authState.setNeedsTokenRefresh(true); - OAuthRefresh(context, provider, authState); + OAuthRefresh(context, provider, authState, expire, keep_alive); Long expiration = authState.getAccessTokenExpirationTime(); if (expiration != null) EntityLog.log(context, user + " token expiration=" + new Date(expiration)); @@ -125,8 +125,20 @@ public class ServiceAuthenticator extends Authenticator { void onPasswordChanged(String newPassword); } - private static void OAuthRefresh(Context context, String id, AuthState authState) throws MessagingException { + private static void OAuthRefresh(Context context, String id, AuthState authState, boolean expire, long keep_alive) + throws MessagingException { try { + Long expiration = authState.getAccessTokenExpirationTime(); + if (expiration != null && expiration - keep_alive < new Date().getTime()) { + EntityLog.log(context, "OAuth force refresh" + + " expiration=" + new Date(expiration) + + " keep_alive=" + (keep_alive / 60 / 1000) + "m"); + authState.setNeedsTokenRefresh(true); + } + + if (expire) + authState.setNeedsTokenRefresh(true); + ClientAuthentication clientAuth; EmailProvider provider = EmailProvider.getProvider(context, id); if (provider.oauth.clientSecret == null)