Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When to use Network.Google.Auth.authorize & why doesn't Credentials.FromClient have AccessToken & RefreshToken? #109

Open
saurabhnanda opened this issue Jun 11, 2018 · 2 comments

Comments

@saurabhnanda
Copy link

I've been trying to wrap my head around this one:

  • After the oauth flow of an "installed application", the user is given a one-time code, which he/she is supposed to share with the application
  • The application then exchanges the one-time code for an oauth access-token & refresh-token:
oauthReturn :: Maybe Text -> AppM Text
oauthReturn Nothing = throwIO $ OAuthError "Did not receive `code` as a URL queryParam at the end of oauth flow"
oauthReturn (Just code_) = do
  env <- ask
  let oauthCreds = Google.allow (plusLoginScope Google.! userInfoEmailScope) $ Google.FromClient (env ^. oAuthClient) (OAuthCode code_)
  auth <- Google.exchange oauthCreds (env ^. googleLogger) (env ^. googleManager)
  pure ([qc|{code_} has been exchanged to {_token auth}|])
  • After that, if one wants to use Network.Google.send along with Network.Google.runGoogle, one needs to construct a value of type Network.Google.Env. Here's the type signature of newEnvWith:
newEnvWith :: (MonadIO m, MonadCatch m, AllowScopes s) => Credentials s -> Logger -> Manager -> m (Env s)
  • The only type related to oauth authentication is Credentials s, and none of the constructors of Credentials s bother with taking the oauth access-token & refresh-token obtained from the step above!

What am I missing here?

@saurabhnanda
Copy link
Author

Okay, managed to figure out how to create an Env at the end of the oauth flow, which calls exchange internally to get the access/refresh tokens:

oauthReturn :: Maybe Text -> AppM Text
oauthReturn Nothing = throwIO $ OAuthError "Did not receive `code` as a URL queryParam at the end of oauth flow"
oauthReturn (Just code_) = do
  env <- ask
  let oauthCreds = Google.allow (plusLoginScope Google.! userInfoEmailScope) $ Google.FromClient (env ^. oAuthClient) (OAuthCode code_)
  googleEnv <- Google.newEnvWith oauthCreds (env ^. googleLogger) (env ^. googleManager)
  auth <- retrieveAuthFromStore $ googleEnv ^. Google.envStore
  pure ([qc|{code_} has been exchanged to {_token auth}|])

@Stealthmate
Copy link

I experienced a similar problem with this as well. Creating Credentials from an auth code is fine, but in my case I wanted to create them directly with the refresh token which wasn't possible.

What I ended up doing is to generate the tokens with FromClient, exchange the result to get an Auth record, convert to AuthorizedUser with authToAuthorizedUser and then saveAuthorizedUser in a file. After that you can use the file to generate the Credentals.

The file itself is stored as a json with the client_id, client_secret and refresh_token so it's perfectly possible to ignore the above steps and just use that, but it would be nice if we could get a way of skipping the file and just getting a Credentials record from a client and a refresh token.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants