OAuth2.0 in the Joplin Plugin

Hi,
I want to use the Google OAuth2.0 mechanism to get third-party access in the Joplin Plugin, but I don't see a safe way to store the client secret (which is a secret used by the OAuth Client to authenticate to the Authorization Server).

I searched a lot for a way to avoid using client_secret and I found a solution to this problem by using PKCE (proof key for code exchange). I tried a lot to use this method, but after several attempts, I discovered that Google supports PKCE only for mobile and desktop applications, not javascript client (It uses PKCE as extra security, not as an alternative to client_secret in javascript web applications.).

One of the ideas I thought of is to make a hosted server just take code from the client and return a refresh token (Once I have the refresh token, I can easily generate an access token every time without having to go back to the server again.),

But I don't know if it is a good idea or not. Does anyone have another better solution or any tricks?

For OneDrive we use a local server to do the OAuth process - maybe you can do something similar?

Also doesn't Gmail support regular imap, which maybe would avoid the need for OAuth support?

1 Like

Does it store the credentials locally? Or is this code uploaded to the hosted server?

I think there is hope :smile:

I think I found the solution by using OAuth 2.0 for Client-side created by Google

It's not much different from the basic method, but the difference in this process is that there is no intermediary between the user and the email provider, and it doesn't give you a refresh token to update. It just calls the getToken function to get the access token, and when the access token expires, it refreshes automatically but must run The page based on a pre-defined protocol between me and the email provider like http://localhost:5000 to ensure that this user is indeed the one who authorized the access.

I tested this with a quick example index.html

After taking the access token and passing it along with the email to imap, this is the successful connection log and also displays all email mailboxes:

[connection] Connected to host
<= '* OK Gimap ready for requests from 197.63.191.116 l26mb465876882wmc'
=> 'A0 CAPABILITY'
<= '* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN AUTH=OAUTHBEARER AUTH=XOAUTH'
<= 'A0 OK Thats all she wrote! l26mb465876892wmc'
=> 'A1 AUTHENTICATE XOAUTH2 
<= '* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE ENABLE MOVE CONDSTORE ESEARCH UTF8=ACCEPT LIST-EXTENDED LIST-STATUS LITERAL- SPECIAL-USE APPENDLIMIT=35651584'
<= 'A1 OK bishoy.magdy.adeeb@gmail.com authenticated (Success)'
=> 'A2 NAMESPACE'
<= '* NAMESPACE (("" "/")) NIL NIL'
<= 'A2 OK Success'
=> 'A3 LIST "" ""'
<= '* LIST (\\Noselect) "/" "/"'
<= 'A3 OK Success'
=> 'A4 LIST "" "*"'
<= '* LIST (\\HasNoChildren) "/" "INBOX"'
<= '* LIST (\\HasChildren) "/" "Mailspring"'
<= '* LIST (\\HasNoChildren) "/" "Mailspring/Snoozed"'
<= '* LIST (\\HasChildren \\Noselect) "/" "[Gmail]"'
<= '* LIST (\\All \\HasNoChildren) "/" "[Gmail]/All Mail"'
<= '* LIST (\\Drafts \\HasNoChildren) "/" "[Gmail]/Drafts"'
<= '* LIST (\\HasNoChildren \\Important) "/" "[Gmail]/Important"'
<= '* LIST (\\HasNoChildren \\Sent) "/" "[Gmail]/Sent Mail"'
<= '* LIST (\\HasNoChildren \\Junk) "/" "[Gmail]/Spam"'
<= '* LIST (\\Flagged \\HasNoChildren) "/" "[Gmail]/Starred"'
<= '* LIST (\\HasNoChildren \\Trash) "/" "[Gmail]/Trash"'
<= '* LIST (\\HasNoChildren) "/" "test1B"'
<= 'A4 OK Success'
{
  INBOX: {
    attribs: [ '\\HasNoChildren' ],
    delimiter: '/',
    children: null,
    parent: null
  },
  Mailspring: {
    attribs: [ '\\HasChildren' ],
    delimiter: '/',
    children: { Snoozed: [Object] },
    parent: null
  },
  '[Gmail]': {
    attribs: [ '\\HasChildren', '\\Noselect' ],
    delimiter: '/',
    children: {
      'All Mail': [Object],
      Drafts: [Object],
      Important: [Object],
      'Sent Mail': [Object],
      Spam: [Object],
      Starred: [Object],
      Trash: [Object]
    },
    parent: null
  },
  test1B: {
    attribs: [ '\\HasNoChildren' ],
    delimiter: '/',
    children: null,
    parent: null
  }
}

I just need a little time to dig deeper.

I found a more practical solution, which is that we don't need OAuth because Google and other providers provide "App passwords", It simply generates a 16-character password for external applications through which to gain access permission.

Thus, we can easily monitor mailboxes because there is no expiration time and the password can also be revoked if the user wants this, like this

The mechanism of App passwords there exists in most email providers like Gmail, Outlook, Yahoo, and AOL, ...

I tried this method in Gmail, Yahoo, AOL and it works very well