16
$\begingroup$

From here I know how to build a a basic service connection.

And that's fine in simple authentication cases but how do I do this for OAuth services?

Even more specifically, how can I do this for Google Drive?

$\endgroup$
17
$\begingroup$

Code

See this for the main issue that made it take so long to get this up

If you just want the service connection you can get it like this:

PacletInstall["ServiceConnection_GoogleDrive",
 "Site"->"http://www.wolframcloud.com/objects/b3m2a1.paclets/PacletServer"
 ]

Post

So this turned out to be a bit of a bear to get the details right for, but not terribly complex once they're dealt with.

Mathematica's built-in OAuth package has some inline docs which are helpful, but there was a lot of trial an error too.

Mostly, we need to provide the following parameters in the "ClientInfo" field (i.e. the one that lays-out how to implement the authentication):

"AuthorizeEndpoint"

Which is the endpoint from which we pass our auth code.

For google this is: "https://accounts.google.com/o/oauth2/v2/auth"

"AccessEndpoint"

The endpoint from which we get the auth token after obtaining an auth code.

For google this is: "https://www.googleapis.com/oauth2/v4/token"

"RedirectURI"

The standard OAuth redirect URI. I set this up like so (well I put in a helper function in my template package that implements this at run time):

HTTPHandling`StartWebServer[
 URLDispatcher[{___~~"oauth2callback"~~___}:>
  APIFunction[{code},<display_code>]
 ]

Note that this is maybe even easier to do by creating a ChannelObject to redirect to -- alternatively we could do something more than just display our auth code with the APIFunction too.

Then we need both

"ConsumerKey"

and

"ConsumerSecret"

I have an encoded keychain mechanism (implemented with Encode) built into my standard suite of tools so I just save these here.

You get these by registering an application at https://console.developers.google.com. I made one called MathematicaLink, but, alas, I can't share the client secret (literally -- Google doesn't allow this). Also see the answer here for a quick rundown on how to get that.

The last thing one needs for OAuth2 is a scope. This seems not to be adequately handled by the standard dialog so I had to cook this in myself.

But first, we'll need the "AuthenticationDialog" parameter:

(
 OAuthClient`tokenOAuthDialog[
   gooledriveauthorizationendpointurl@#,
   "GoogleDrive",
   googledrivedata["icon"]
   ] &)

We mostly just use the standard built-in token dialog, but notice the gooledriveauthorizationendpointurl. The OAuth client seems to pass an incorrect "scope" (it's blank). So that function will need to re-parse the passed URL and correct the scope. It's simple, but I generalized and so my block of code is more than I want to put there.

Then since we've passed all the requisite junk the OAuthSigning` package will operate correctly (for those interested in just getting tokens via this method that's where you'll want to dig around. Check out OAuthSigning`Private`OAuthFlow to see how to get an access token from all of this data).

So here's a quick auth example rundown.

First the basic auth dialog:

token dialog

Before that opens, if I'm coming from a fresh restart, it asks me for my keychain password (because of how I set it up -- not implemented by the OAuth` package), but otherwise just opens that. Follow the link, choose the appropriate Google account and approve:

approve

When I do this it routes to the redirect URI started with StartWebServer:

web server port

I copy that key in:

key

And the OAuth package takes care of the rest.

service object

And then just checking that the access token is being handled correctly:

In[11]:= $gd["ListFiles"]["files", All, "id"] // Normal // First

Out[11]= "1CfpLOne3LRBHXPFRNtlzjujuq66qIzX47ezNdr_XPls"

I'll get this paclet up for public consumption after I provide access to more than just the files API and make sure uploads work (I remember from a previous implementation of a Google Drive connection that it was a bit hairy -- hopefully the ServiceConnect framework smooths that out).

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.