How can I retrieve this AUTH Token from GoToWebinar's API in PHP?

1.6k views Asked by At

GTW has updated their API and I'm in the middle of refactoring some code to accommodate these required changes but I'm a little stuck on the Auth Token part.

As per their instructions (https://goto-developer.logmeininc.com/how-get-access-token-and-organizer-key):

1 - Request Authorization Code Create an authorization request on behalf of a GoTo product user. It sends them to a product login page.

In the My Apps page, open your application and copy the Consumer Key value. Insert the Consumer Key value into the following URL to replace {consumerKey}: https://api.getgo.com/oauth/v2/authorize?client_id={consumerKey}&response_type=code The product account holder sends the URL. They are directed to the sign-in page for the product. If they are not already logged in, they sign in with their credentials and must click Allow to allow access for the developer application. The user is then automatically redirected to the redirect URL you defined in the developer center application. The redirect URI (in the browser address bar) has a Response Key added to it.

IMPORTANT: You may see an error on the page such as 404 NOT FOUND. This is not a problem. Look at the URL in the browser. It contains the responseKey you need for the next step. It will look something like:

http://example.com/oauthreturn/?code={responseKey} You can include an optional redirect URI and/or a state parameter. For details, see the section, Optional: Add a Redirect URI, below.

Of most interest here is this line:

IMPORTANT: You may see an error on the page such as 404 NOT FOUND. This is not a problem. Look at the URL in the browser. It contains the responseKey you need for the next step. It will look something like:

It actually works just fine if I do this in a browser...I provide the appropriate credentials and I'm redirected to what amounts to an error page (and a header code of 404 is returned) but the URL contains the auth token.

I'm trying to retrieve this auth token with CURL but I can't actually get the redirected URL in any data that is returned from the CURL request.

2

There are 2 answers

0
MichaelF On

If you prefer to handle the auth process yourself, please have a look at the implementation in this repo:

https://github.com/cleverreach/citrix

  • which is based off of the teodortalov/citrix implementation but updated to the v2 version of the GTW API.

Since the package handles the entire process I'd suggest using it as is, but if you prefer to implement your own, it's still a great example and a helpful starting point.

0
mraguda On

I've just gone through this whole process, but this is how it should work. I understand that the API docs provided on GoTo Connect are a bit confusing!

The better docs can be found here

The workflow involves three main steps:

  1. Initializing the authentication flow using the Auth Code Grant flow to get an authorization code. Here you will call the authentication API with your client id, you will be directed to a browser window where you will provide authentication and are returned an {AUTHORIZATION CODE} using OAuth.
import http.client

conn = http.client.HTTPSConnection("authentication.logmeininc.com")

conn.request("GET", "/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URL)

res = conn.getresponse()
data = res.read()
res.getheaders()

res.getheaders() should return headers object that looks like this (The url to visit to complete the Oauth is located in the Location header):

[('Date', 'Fri, 23 Sep 2022 23:13:48 GMT'),
 ('Content-Length', '0'),
 ('Connection', 'keep-alive'),
 ('Set-Cookie',
  'csrftoken=; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/'),
 ('Location',
  'https://authentication.logmeininc.com/login?service=xxxxxxxxxxxxxx'),
 ('Content-Language', 'en')]

This portion is not programmatic, and requires user intervention in a browser window. Once you've completed the authentication flow, you will be directed to your {REDIRECT URI} along with your new authorization code tagged on as a parameter: https://yourredirecturi.com/?CODE=XXXXXXXXXXXXX

  1. Retrieve Initial Access Token by Exchanging the Auth Code for an Access Token using the same API but pass different params (auth here is encoded in base64 (base64("{CLIENT_ID}:{CLIENT_SECRET}")):
import json

code = YOURAUTHORIZATION_CODE_FROM_STEP1
conn = http.client.HTTPSConnection("authentication.logmeininc.com")
payload = "grant_type=authorization_code&code=" + code + "&redirect_uri=YOUR_REDIRECT_URI&client_id=YOUR_CLIENT_ID"

headers = {
    'Authorization': "Basic " + auth,
    'content-type': "application/x-www-form-urlencoded",
    'Accept' : "application/json"
    }

conn.request("POST", "/oauth/token", payload, headers)

res = conn.getresponse()
data = res.read()

returned = data.decode("utf-8")
returned_json = json.loads(returned)
access_token = returned_json["access_token"]
refresh_token = returned_json["refresh_token"]

This should return an access_token and a refresh_token

  1. Periodically retrieve a new refresh token. Once authentication has been established, you can programmatically request a refresh token (I do this daily with a Python script) by calling the same API, but by changing the grant_type parameter from authorization_code to refresh_token
import http.client
import json

code = YOURAUTHORIZATION_CODE_FROM_STEP1
conn = http.client.HTTPSConnection("authentication.logmeininc.com")
payload = "grant_type=refresh_token&refresh_token=" + refresh_token

headers = {
    'Authorization': "Basic " + auth,
    'content-type': "application/x-www-form-urlencoded",
    'Accept' : "application/json"
    }

conn.request("POST", "/oauth/token", payload, headers)

res = conn.getresponse()
data = res.read()

returned = data.decode("utf-8")
returned_json = json.loads(returned)
access_token = returned_json["access_token"]
try :
  refresh_token = returned_json["refresh_token"]
except :
  refresh_token = refresh_token

Final Thoughts

To keep things simple, I manually complete steps 1 and 2. I run step 3 as a service on Google Cloud Functions with a Chron job nightly and store them in Google Secrets Manager to ensure I have a fresh access_token and refresh_token.

Hope that helps!