I'm making a purely client-side web app that displays some information from the user's Google calendar. They go through OAuth, give permission for calendar access, and then see the derived information. Following the Google Calendar JS Quickstart I have this basically working.
The problem is, the access token is only good for 1hr (3599s). After that, I need to send the user through the whole OAuth flow again to get a new token, which is four clicks across three screens. Is there any way to keep from having to ask for new consent each time?
If you could fetch a refresh token, then you could regularly use that to create new access tokens, and it should work up to six months. However, refresh tokens, because of that additional power, require client authentication, the client (that is, your app) has to provide a client ID and a client secret, and the authorization server can check more carefully and revoke a client if it's been compromised.
In this case, though, you can't have a client (as in, OAuth client) secret in your client (as in, Web client) code; you shared the web page and the source of web pages is easily visible. (And implicitly there is more concern that an in-browser token can be stolen by an attacker, and so there's an interest in reducing the power that such a token has by itself.) So Google's library doesn't even provide the capability to request refresh tokens from the browser-based Javascript library. That flow uses an "implicit grant" where the client is not authenticated and the user just follows a redirect in their user agent, which is simpler, but has some security limitations, and so Google and others typically intend this just for current session applications where the user is currently using the page.
If you spin up a small server (and use one of Google's server-side libraries), you can fetch and securely store refresh tokens and get newly updated access tokens for as long as you want, each time making an updated request from the server with your id/secret.
There are also some flows that would let a client-side application get a longer-lived refresh token, by having the user on a separate device go to a separate URL and enter a code, which I believe still lets the client (your app) be authenticated (because you're running an additional small service that handles that and can use a client secret). But I don't know that Google's OAuth2 set-up supports that.
(OAuth terminology feels confusing to me every time I read about it again, so apologies to the actual experts if I've misstated anything here.)