1
0
Fork 0
mirror of https://github.com/M66B/FairEmail.git synced 2025-01-04 06:20:26 +00:00

Auto expire tokens

This commit is contained in:
M66B 2021-11-27 12:58:25 +01:00
parent 8b19bceb7a
commit 180d270239
3 changed files with 45 additions and 9 deletions

View file

@ -45,6 +45,8 @@ import com.sun.mail.util.MailConnectException;
import com.sun.mail.util.SocketConnectException; import com.sun.mail.util.SocketConnectException;
import com.sun.mail.util.TraceOutputStream; import com.sun.mail.util.TraceOutputStream;
import org.json.JSONException;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
@ -114,6 +116,7 @@ public class EmailService implements AutoCloseable {
private Session isession; private Session isession;
private Service iservice; private Service iservice;
private StoreListener listener; private StoreListener listener;
private ServiceAuthenticator authenticator;
private ExecutorService executor = Helper.getBackgroundExecutor(0, "mail"); private ExecutorService executor = Helper.getBackgroundExecutor(0, "mail");
@ -409,7 +412,7 @@ public class EmailService implements AutoCloseable {
} }
properties.put("mail." + protocol + ".forcepasswordrefresh", "true"); properties.put("mail." + protocol + ".forcepasswordrefresh", "true");
ServiceAuthenticator authenticator = new ServiceAuthenticator(context, authenticator = new ServiceAuthenticator(context,
auth, provider, keep_alive, user, password, intf); auth, provider, keep_alive, user, password, intf);
if ("imap.wp.pl".equals(host)) if ("imap.wp.pl".equals(host))
@ -425,7 +428,7 @@ public class EmailService implements AutoCloseable {
if (auth == AUTH_TYPE_OAUTH && "imap.mail.yahoo.com".equals(host)) if (auth == AUTH_TYPE_OAUTH && "imap.mail.yahoo.com".equals(host))
properties.put("mail." + protocol + ".yahoo.guid", "FAIRMAIL_V1"); properties.put("mail." + protocol + ".yahoo.guid", "FAIRMAIL_V1");
connect(host, port, auth, user, authenticator, factory); connect(host, port, auth, user, factory);
} catch (AuthenticationFailedException ex) { } catch (AuthenticationFailedException ex) {
//if ("outlook.office365.com".equals(host) && //if ("outlook.office365.com".equals(host) &&
// "AUTHENTICATE failed.".equals(ex.getMessage())) // "AUTHENTICATE failed.".equals(ex.getMessage()))
@ -437,7 +440,7 @@ public class EmailService implements AutoCloseable {
if (auth == AUTH_TYPE_GMAIL || auth == AUTH_TYPE_OAUTH) { if (auth == AUTH_TYPE_GMAIL || auth == AUTH_TYPE_OAUTH) {
try { try {
authenticator.refreshToken(true); authenticator.refreshToken(true);
connect(host, port, auth, user, authenticator, factory); connect(host, port, auth, user, factory);
} catch (Exception ex1) { } catch (Exception ex1) {
Log.e(ex1); Log.e(ex1);
throw new AuthenticationFailedException( throw new AuthenticationFailedException(
@ -489,8 +492,7 @@ public class EmailService implements AutoCloseable {
} }
private void connect( private void connect(
String host, int port, int auth, String host, int port, int auth, String user,
String user, Authenticator authenticator,
SSLSocketFactoryService factory) throws MessagingException { SSLSocketFactoryService factory) throws MessagingException {
InetAddress main = null; InetAddress main = null;
boolean require_id = (purpose == PURPOSE_CHECK && boolean require_id = (purpose == PURPOSE_CHECK &&
@ -533,7 +535,7 @@ public class EmailService implements AutoCloseable {
} }
EntityLog.log(context, "Connecting to " + main); EntityLog.log(context, "Connecting to " + main);
_connect(main, port, require_id, user, authenticator, factory); _connect(main, port, require_id, user, factory);
} catch (UnknownHostException ex) { } catch (UnknownHostException ex) {
throw new MessagingException(ex.getMessage(), ex); throw new MessagingException(ex.getMessage(), ex);
} catch (MessagingException ex) { } catch (MessagingException ex) {
@ -653,7 +655,7 @@ public class EmailService implements AutoCloseable {
try { try {
EntityLog.log(context, "Falling back to " + iaddr); EntityLog.log(context, "Falling back to " + iaddr);
_connect(iaddr, port, require_id, user, authenticator, factory); _connect(iaddr, port, require_id, user, factory);
return; return;
} catch (MessagingException ex1) { } catch (MessagingException ex1) {
ex = ex1; ex = ex1;
@ -671,8 +673,7 @@ public class EmailService implements AutoCloseable {
} }
private void _connect( private void _connect(
InetAddress address, int port, boolean require_id, InetAddress address, int port, boolean require_id, String user,
String user, Authenticator authenticator,
SSLSocketFactoryService factory) throws MessagingException { SSLSocketFactoryService factory) throws MessagingException {
isession = Session.getInstance(properties, authenticator); isession = Session.getInstance(properties, authenticator);
@ -854,6 +855,10 @@ public class EmailService implements AutoCloseable {
return false; return false;
} }
public void check() {
authenticator.checkToken();
}
public boolean isOpen() { public boolean isOpen() {
return (iservice != null && iservice.isConnected()); return (iservice != null && iservice.isConnected());
} }
@ -862,6 +867,8 @@ public class EmailService implements AutoCloseable {
try { try {
if (iservice != null && iservice.isConnected()) if (iservice != null && iservice.isConnected())
iservice.close(); iservice.close();
if (authenticator != null)
authenticator = null;
} finally { } finally {
context = null; context = null;
} }

View file

@ -121,6 +121,32 @@ public class ServiceAuthenticator extends Authenticator {
return password; return password;
} }
void checkToken() {
Long expiration = null;
try {
if (auth == AUTH_TYPE_GMAIL) {
GmailState authState = GmailState.jsonDeserialize(password);
expiration = authState.getAccessTokenExpirationTime();
} else if (auth == AUTH_TYPE_OAUTH) {
AuthState authState = AuthState.jsonDeserialize(password);
expiration = authState.getAccessTokenExpirationTime();
}
} catch (JSONException ex) {
Log.e(ex);
}
if (expiration != null && expiration - keep_alive < new Date().getTime()) {
try {
refreshToken(true);
} catch (Throwable ex) {
Log.w(ex);
}
throw new IllegalStateException("Token needs refresh");
}
}
interface IAuthenticated { interface IAuthenticated {
void onPasswordChanged(Context context, String newPassword); void onPasswordChanged(Context context, String newPassword);
} }

View file

@ -1997,6 +1997,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
throw new StoreClosedException(iservice.getStore(), "Unrecoverable", cause); throw new StoreClosedException(iservice.getStore(), "Unrecoverable", cause);
} }
// Check token expiration
iservice.check();
// Sends store NOOP // Sends store NOOP
if (EmailService.SEPARATE_STORE_CONNECTION) { if (EmailService.SEPARATE_STORE_CONNECTION) {
EntityLog.log(this, EntityLog.Type.Account, EntityLog.log(this, EntityLog.Type.Account,