davmail
davmail copied to clipboard
Refresh Token does not update after the initial save
It seems DavMail does not update the persisted refresh token after it was initially saved. Consequently, the refresh token expires every 90 days or so.
According to Microsoft documentation
whenever a refresh token is used to acquire a new access token, a new refresh token is also issued.
Essentially, when the grant_type is refresh_token, the returned JSON response includes a new refresh_token. Although the original refresh token isn't revoked, the new refresh token has a refreshed lifetime.
It seems that setJsonToken in O365Token does parse this updated refresh_token, but it doesn't save the new refresh token. Is it possible to change this behavior?
I can contribute $100 (USD) toward a bounty to fix this.
@mitechzone @cwarden : mguessan implemented refresh token updates in a couple recent commits. You should try them out and see if it resolves your issues. (The trunk builds from appveyor have the patches: https://github.com/mguessan/davmail )
In my case, storing the new refresh token received upon refresh doesn't solve the problem because it expires at the same time as the original refresh token as described in https://github.com/mguessan/davmail/pull/238#issuecomment-1276066527.
To avoid session expiration, I'm stuck updating [email protected] in davmail.properties from outside of davmail and restarting davmail.
It hasn't been 90 days yet, but the patch from @piyushgarg seems to have reduced the frequency I needed to manually update the token. Previously, I had to update the token every other week. With the patch, I haven't manually updated the token since November. I'll try the new update, but it will take a while to confirm.
I installed the latest development version of davmail on my Ubuntu 22.04 machine on January 14, but my token still expired at the 90 day mark like it usually does. I'm not sure why one message below says that it was inactive for 90 days, as it was not. But it wasn't used in the day or two before expiry, in case that matters. (I only use davmail for outgoing mail on that machine, and didn't send any messages from it recently.)
I do have davmail.oauth.persistToken=true in my config file.
2023-01-30 09:19:04,899 INFO [davmail.smtp.SmtpServer] davmail.connection - CONNECT - 127.0.0.1:32878
2023-01-30 09:19:06,562 ERROR [SmtpConnection-32878] davmail.exchange.auth.O365Token - refresh token failed invalid_grant AADSTS700082: The refresh token has expired due to inactivity. The token was issued on 2022-11-01T13:15:35.5309537Z and was inactive for 90.00:00:00.
Trace ID: 4770db56-b993-43bf-b657-1e9c577dcf00
Correlation ID: 58804365-98b9-467f-87a1-f7fafb3684ef
Timestamp: 2023-01-30 14:19:06Z
2023-01-30 09:19:06,575 ERROR [SmtpConnection-32878] davmail.exchange.auth.O365ManualAuthenticator - Authentication failed, code not available
2023-01-30 09:19:06,576 INFO [SmtpConnection-32878] davmail.connection - FAILED - 127.0.0.1:32878 [email protected]
2023-01-30 09:19:06,578 ERROR [SmtpConnection-32878] davmail - Authentication failed null
davmail.exception.DavMailException: Authentication failed null
at davmail.exchange.auth.O365ManualAuthenticator.authenticate(O365ManualAuthenticator.java:120)
at davmail.exchange.ExchangeSessionFactory.getInstance(ExchangeSessionFactory.java:182)
at davmail.exchange.ExchangeSessionFactory.getInstance(ExchangeSessionFactory.java:93)
at davmail.smtp.SmtpConnection.authenticate(SmtpConnection.java:229)
at davmail.smtp.SmtpConnection.run(SmtpConnection.java:106)
2023-01-30 09:19:06,586 INFO [SmtpConnection-32878] davmail.connection - DISCONNECT - 127.0.0.1:32878
On another Ubuntu 22.04 machine, it looks like the token is going to expire in about a hour:
2023-01-30 09:35:09,830 DEBUG [ImapConnection-57302] davmail.exchange.auth.O365Token - Access token expires Mon Jan 30 10:38:23 EST 2023
Is there anything I should watch for here? On this machine, I'm polling for new mail every 30 seconds.
From the code, it looks like davmail only requests a new token if it is within 60 seconds of expiry? Is that right?
From the code, it looks like davmail only requests a new token if it is within 60 seconds of expiry? Is that right?
I think that it requests new tokens when the access token is within 60 seconds of expiry (or has expired), which should happen every hour. We should receive a new refresh token as well at the same time, which should be stored. I added some comments to the commit about logging some information that might help debug this.
Machine 2 (which does frequent polling) is still able to connect to Office 365, after 91 days, so something seems to be working better there. Not sure why Machine 1 had its token expire. The main differences are: Machine 1 only uses davmail for outgoing mail, and only occasionally, while Machine 2 uses davmail for incoming and outgoing mail, and polls frequently (every 30s) for incoming mail.
Ok, I checked through my logs and found that I didn't send a single message from Machine 1 since upgrading davmail with the new code, so davmail never asked for a new access token and therefore never got a new refresh token. Sorry for the noise, I think this is working correctly.
One idea: davmail could keep track of the expiry date on the refresh token, and make sure to renew it well in advance, say a week ahead or a month ahead. It's a rare situation, so maybe isn't worth it.