Search code examples
restoauthgoogle-oauthdesktop-application

OAuth - what to store on disk


TL;DR When using google oauth on desktop app, what to save on disk to avoid repeated sign in? Save the google user id? or the token? or an session id?

I'm creating an little desktop app, whitch must authenticate to my REST API server. I'm using google oauth2 for that.

The idea is, that when the desktop app will be authentivated, it generates some data that will be send to my server. The server will store the data with the google user id received from https://www.googleapis.com/userinfo/v2/me.

On the first run of the desktop app, it will open the default browser, with and url for my server and start an local http server. then:

  1. my server will redirect the browser to google (with the clientid, secret, etc.)
  2. user logs in and it will be redirected back to the server with the oauth code
  3. server uses the code to get the token, and then the user profile and stores the token and the profile in db, then redirects the browser to localhost with an paramerer
  4. the desktop app catches the parameter and stores it in an file on the disk

next time the desktop app will start it only reads the file for the parameter to send the generated data with it to my server

my question is: what the parameter should be? the google user id? the oauth token? an generated session id for this desktop app? or something else?

  • when it will be the google user id, it can conveniently sent the data with the user id and the rest server will just store it in db as is. but I don't think it's safe
  • when it will be the token, the rest server has to with every request also get the user profile from google with the token. and imho sending the token with every request isn't safe either
  • generating an session id means to store it with the user and the token on the server and the desktop app will just store it and send it with every request. but I don't know if it's safe to do that

Solution

  • As it's normally the case in software development you have a couple of options depending on requirements.

    The mandatory requirement is that your client (desktop) application needs to send something to your REST API so that the API can perform up to two decisions:

    1. Decide who the user is.
    2. Decide if the user is authorized to perform the currently requested action.

    The second step may not be applicable if all authenticated users have access to exactly the same set of actions so I'll cover both scenarios.

    Also note that, for the first step, sending the Google user ID is not a valid option as that information can be obtained by other parties and does not ensure that the user did authenticate to use your application.

    Option 1 - Authentication without fine-grained authorization

    Either always sending the id_token or exchanging that token with your custom session identifier both meet the previous requirement, because the id_token contains an audience that clearly indicates the user authenticated to use your application and the session identifier is generated by your application so it can also ensure that. The requests to your API need to use HTTPS, otherwise it will be too easy for the token or session ID to be captured by an attacker.

    If you go with the id_token alternative you need to take in consideration that the token will expire; for this, a few options again:

    • repeat the authentication process another time; if the user still has a session it will indeed be quicker, but you still have to open a browser, local server and repeat the whole steps.
    • request offline_access when doing the first authentication.

    With the last option you should get a refresh token that would allow for your application to have a way to identify the user even after the first id_token expires. I say should, because Google seems to do things a bit different than the specification, for example, the way to obtain the refresh token is by providing access_type=offline instead of the offline_access from OpenID Connect.

    Personally, I would go with the session identifier as you'll have more control over lifetime and it may also be simpler.

    Option 2 - Authentication + fine-grained authorization

    If you need a fine-grained authorization system for your REST API then the best approach would be to authenticate your users with Google, but then have an OAuth 2.0 compliant authorization server that would issue access tokens specific for your API.

    For the authorization server implementation, you could either:

    • Implement it yourself or leverage open source components
          may be time consuming, complex and mitigation of security risks would all fall on you

    • Use a third-party OAuth 2.0 as a servive authorization provider like Auth0
          easy to get started, depending on amount of usage (the free plan on Auth0 goes up to 7000 users) it will cost you money instead of time

    Disclosure: I work at Auth0.