Skip to content

Commit

Permalink
update auth token upon client start - server could have been down and…
Browse files Browse the repository at this point in the history
… token therefore expired. issue #2724
  • Loading branch information
j-dimension committed Dec 8, 2024
1 parent d6d5e94 commit df84e10
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,16 @@ private void refreshFolders(boolean showErrorDialogOnFailure) throws Exception {
for (MailboxSetup ms : mailboxes) {

try {

if(ms.isMsExchange()) {
try {
ClientSettings settings=ClientSettings.getInstance();
JLawyerServiceLocator locator = JLawyerServiceLocator.getInstance(settings.getLookupProperties());
locator.lookupEmailServiceRemote().updateAuthToken(ms.getId());
} catch (Exception ex) {
log.error("unable to update auth token for mailbox " + ms.getEmailAddress(), ex);
}
}

this.connect(showErrorDialogOnFailure, ms);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,10 @@ public class FolderContainer {

double retentionTime = -1;

// private Message[] cachedMessages=null;
// private String cachedMessagesKey=null;


static {
folderNameMapping.put(CommonMailUtils.INBOX, "Posteingang");
folderNameMapping.put(CommonMailUtils.SENT, "Gesendet");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,7 @@ You should also get your employer (if you work as a programmer) or school,
public interface EmailServiceRemote {

String getAuthToken(String mailboxId) throws Exception;
boolean updateAuthToken(String mailboxId) throws Exception;
String[] requestDeviceCode(String mailboxId) throws Exception;
boolean pollForTokens(String mailboxId, String deviceCode) throws Exception;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -728,79 +728,100 @@ public void refreshAuthTokens() {

List<MailboxSetup> mailboxes = this.mailboxSetupFacade.findByMsExchange(true);
for (MailboxSetup ms : mailboxes) {
if (ms.getTokenExpiry() == 0 || ((ms.getTokenExpiry() - System.currentTimeMillis()) < (6l * 60l * 1000l))) {
try {
log.info("attempting to update tokens for " + ms.getEmailAddress());
boolean success=this.updateAuthToken(ms);
if(!success)
log.error("failed to update tokens for " + ms.getEmailAddress());
else
log.info("successfully updated tokens for " + ms.getEmailAddress());
} catch (Exception ex) {
log.error("failed to retrieve new access token for mailbox " + ms.getEmailAddress(), ex);
}
}
}

}
try {

private boolean updateAuthToken(MailboxSetup mailbox) throws Exception {
boolean success = this.updateAuthTokenForMailbox(ms);
if (!success) {
log.error("failed to update tokens for " + ms.getEmailAddress());
} else {
log.info("successfully updated tokens for " + ms.getEmailAddress());
}
} catch (Exception ex) {
log.error("failed to retrieve new access token for mailbox " + ms.getEmailAddress(), ex);
}

if (ServerStringUtils.isEmpty(mailbox.getTenantId())) {
log.error("Tenant ID is empty when updating access token for " + mailbox.getEmailAddress());
return false;
}

if (ServerStringUtils.isEmpty(mailbox.getClientId())) {
log.error("Client ID is empty when updating access token for " + mailbox.getEmailAddress());
return false;
}
}

if (ServerStringUtils.isEmpty(mailbox.getRefreshToken())) {
log.error("Refresh token is empty when updating access token for " + mailbox.getEmailAddress());
@Override
@RolesAllowed({"loginRole"})
public boolean updateAuthToken(String mailboxId) throws Exception {

MailboxSetup ms = this.mailboxSetupFacade.find(mailboxId);
if (ms != null) {
return this.updateAuthTokenForMailbox(ms);
} else {
log.error("Auth token update requested for a non-existing mailbox with id " + mailboxId);
return false;
}

}

private boolean updateAuthTokenForMailbox(MailboxSetup mailbox) throws Exception {

String TOKEN_ENDPOINT = "https://login.microsoftonline.com/" + mailbox.getTenantId() + "/oauth2/v2.0/token";
if (mailbox.getTokenExpiry() == 0 || ((mailbox.getTokenExpiry() - System.currentTimeMillis()) < (6l * 60l * 1000l))) {

try (CloseableHttpClient client = HttpClients.createDefault()) {
HttpPost post = new HttpPost(TOKEN_ENDPOINT);
log.info("attempting to update tokens for " + mailbox.getEmailAddress());

if (ServerStringUtils.isEmpty(mailbox.getTenantId())) {
log.error("Tenant ID is empty when updating access token for " + mailbox.getEmailAddress());
return false;
}

// Create URL-encoded body
String body = "grant_type=" + URLEncoder.encode("refresh_token", StandardCharsets.UTF_8)
+ "&refresh_token=" + URLEncoder.encode(mailbox.getRefreshToken(), StandardCharsets.UTF_8)
+ "&client_id=" + URLEncoder.encode(mailbox.getClientId(), StandardCharsets.UTF_8);
//"&client_secret=" + URLEncoder.encode(CLIENT_SECRET, StandardCharsets.UTF_8);
if (ServerStringUtils.isEmpty(mailbox.getClientId())) {
log.error("Client ID is empty when updating access token for " + mailbox.getEmailAddress());
return false;
}

post.setEntity(new StringEntity(body));
post.setHeader("Content-Type", "application/x-www-form-urlencoded");
if (ServerStringUtils.isEmpty(mailbox.getRefreshToken())) {
log.error("Refresh token is empty when updating access token for " + mailbox.getEmailAddress());
return false;
}

ObjectMapper objectMapper = new ObjectMapper();
try (CloseableHttpResponse response = client.execute(post)) {
if (response.getStatusLine().getStatusCode() == 200) {
Map<String, Object> responseBody = objectMapper.readValue(
response.getEntity().getContent(),
Map.class
);

String accessToken = (String) responseBody.get("access_token");
String refreshToken = (String) responseBody.get("refresh_token");
int expiresIn = (int) responseBody.get("expires_in");
// Calculate token expiry time (current time + expires_in seconds)
long tokenExpiryTime = System.currentTimeMillis() + (expiresIn * 1000l);

mailbox.setAuthToken(accessToken);
mailbox.setRefreshToken(refreshToken);
mailbox.setTokenExpiry(tokenExpiryTime);
this.mailboxSetupFacade.edit(mailbox);
return true;
} else {
log.error("failed to retrieve new access token for mailbox " + mailbox.getEmailAddress() + ", response was HTTP " + response.getStatusLine().getStatusCode() + " with content:");
log.error(response.getEntity().getContent());
return false;
String TOKEN_ENDPOINT = "https://login.microsoftonline.com/" + mailbox.getTenantId() + "/oauth2/v2.0/token";

try (CloseableHttpClient client = HttpClients.createDefault()) {
HttpPost post = new HttpPost(TOKEN_ENDPOINT);

// Create URL-encoded body
String body = "grant_type=" + URLEncoder.encode("refresh_token", StandardCharsets.UTF_8)
+ "&refresh_token=" + URLEncoder.encode(mailbox.getRefreshToken(), StandardCharsets.UTF_8)
+ "&client_id=" + URLEncoder.encode(mailbox.getClientId(), StandardCharsets.UTF_8);
//"&client_secret=" + URLEncoder.encode(CLIENT_SECRET, StandardCharsets.UTF_8);

post.setEntity(new StringEntity(body));
post.setHeader("Content-Type", "application/x-www-form-urlencoded");

ObjectMapper objectMapper = new ObjectMapper();
try (CloseableHttpResponse response = client.execute(post)) {
if (response.getStatusLine().getStatusCode() == 200) {
Map<String, Object> responseBody = objectMapper.readValue(
response.getEntity().getContent(),
Map.class
);

String accessToken = (String) responseBody.get("access_token");
String refreshToken = (String) responseBody.get("refresh_token");
int expiresIn = (int) responseBody.get("expires_in");
// Calculate token expiry time (current time + expires_in seconds)
long tokenExpiryTime = System.currentTimeMillis() + (expiresIn * 1000l);

mailbox.setAuthToken(accessToken);
mailbox.setRefreshToken(refreshToken);
mailbox.setTokenExpiry(tokenExpiryTime);
this.mailboxSetupFacade.edit(mailbox);
return true;
} else {
log.error("failed to retrieve new access token for mailbox " + mailbox.getEmailAddress() + ", response was HTTP " + response.getStatusLine().getStatusCode() + " with content:");
log.error(response.getEntity().getContent());
return false;
}
}
}
}
return true;
}

@Override
Expand All @@ -819,9 +840,9 @@ public String[] requestDeviceCode(String mailboxId) throws Exception {
// String body = "client_id=" + ms.getClientId()
// + "&scope=https%3A%2F%2Fgraph.microsoft.com%2Fmail.read%20offline_access";
String body = "client_id=" + ms.getClientId()
+ "&scope=https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All%20"
+ "https%3A%2F%2Foutlook.office365.com%2FSMTP.Send%20"
+ "offline_access";
+ "&scope=https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All%20"
+ "https%3A%2F%2Foutlook.office365.com%2FSMTP.Send%20"
+ "offline_access";

post.setEntity(new StringEntity(body));
post.setHeader("Content-Type", "application/x-www-form-urlencoded");
Expand Down Expand Up @@ -881,7 +902,7 @@ public boolean pollForTokens(String mailboxId, String deviceCode) throws Excepti

ms.setAuthToken(accessToken);
ms.setRefreshToken(refreshToken);
ms.setTokenExpiry(System.currentTimeMillis() + 10l*60l*1000l);
ms.setTokenExpiry(System.currentTimeMillis() + 10l * 60l * 1000l);
this.mailboxSetupFacade.edit(ms);
return true;

Expand Down

0 comments on commit df84e10

Please sign in to comment.