- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Notify Moderator
As mentioned in our Overview of Alteryx Developer Platform blog post, The HTML GUI SDK lets users create custom GUIs using HTML5. This allows for greater UI customization than what standard Macro interfaces provide as well as more dynamic interaction with web-services. This makes building a connector with the HTML GUI SDK more attractive especially when it comes to authentication.
Authentication is almost always the very first step toward interacting with a web-service, making it the most crucial to get right. Even though it is possible to get through authentication using just the Download Tool within a macro, you may run into some hurdles depending on the web-service. Currently the Download Tool does not support HTTPS or redirect URIs, so you may have to get creative and maybe use a run command tool running a cURL script for certain web-services. For more information on creating your own connector in Alteryx using macros as well as the authentication process in macros and workflows, checkout the Guide to Creating Your Own Connector Series.
In this blog post, we will go over an example of how the authentication process can interact with the HTML GUI SDK. Specifically, we will look at an example from the newest version of the Google Analytics Connector. The new connector can be downloaded on the gallery but the code that we will be reviewing can only be found in our GitHub repository. The reason these two entities are different are because the files contained in the YXI package found in the gallery, which automatically get installed into C:\Users\{user}\AppData\Roaming\Alteryx\Tools, do not include developer dependencies or other files unnecessary for the tool to function such as node.js packages or component files. The YXI will only include a bundled file (bundle.js) generated via webpack that the HTML uses. In this post, we will be going over code located in the utils.js file located under .\Google Analytics\App\src\utils.
Before we jump into the code here is a short list of tools we used in this section of code:
- jquery - For ajax calls to validate our token and the API call for the offline authentication method.
- HTML GUI SDK - For extracting and setting values of widgets and DataItems. Note, this tool uses version 1 of the SDK. The only method we use from the SDK in this example is
Alteryx.Gui.manager.GetDataItem()
. In version 2 this was changed toAlteryx.Gui.Manager.getDataItem()
.
The connector has two client-side authentication methods: Online and Offline.
The Online method allows users to sign-in with their Google credentials however, they will be logged out after 60 minutes. This method requires using OAuth 2.0. To implement OAuth 2.0 authorization for Google APIs into your Alteryx plugin, follow Google's guide OAuth 2.0 for Client-side Web Applications.
The Offline method allows users to stay logged in permanently thus allowing workflows to be scheduled and ran indefinitely. This method requires a Client ID, Client Secret, and Refresh Token. Read our help documentation to obtain the credentials.
Online Method
Again the following code is from the utils.js module. We'll cover three functions:
login
gup
validateToken
Online Method - login
The login
function has a few constants needed for the request URL stored in the variable _url
.
const OAUTHURL = 'https://accounts.google.com/o/oauth2/auth?'
const SCOPE = 'https://www.googleapis.com/auth/analytics.readonly'
const CLIENTID = '552512737410-g6admen5hqg6q268dmt3d9bminlri7en.apps.googleusercontent.com'
const REDIRECT = 'https://developers.google.com/oauthplayground'
const TYPE = 'token'
const _url = OAUTHURL + 'scope=' + SCOPE + '&client_id=' + CLIENTID + '&redirect_uri=' + REDIRECT + '&response_type=' + TYPE
Then the variable win
is created using _url
as a parameter. Don't worry about the line right below win
. The data item is being used to store the error status, which we initialize with a blank value during the login process.
win
will open a new window to Google's OAuth URL where the user can login with their credentials.
const win = window.open(_url, 'windowname1', 'width=800, height=600')
Alteryx.Gui.manager.GetDataItem('errorStatus').setValue('')
While the window is open, a poll timer function is running every half second checking if the URL origin has changed to https://developers.google.com
. The URL origin will change if the user successfully logins. When that happens, steps 2 and 3 occur. The access token is parsed from the URL using the gup
function and stored in the 'access_token' DataItem so that it can be used for the downstream API call in the macro. The access token is then validated using the validateToken
function. Both are discussed in the next sections.
If the access token validates successfully the window is closed and the plugin's configuration page changes to the profile selection.
const pollTimer = window.setInterval(() => {
try {
if (win.document.location.origin === 'https://developers.google.com') {
const url = win.document.URL
const accessToken = gup(url, 'access_token')
Alteryx.Gui.manager.GetDataItem('accessToken').setValue(accessToken)
validateToken(accessToken)
win.close()
setPage('#profileSelectors')
}
} catch (e) {
// console.log("catch");
}
}, 500)
Online Method - gup
This is a simple function that takes the URL and the query parameter as arguments to identify the value needed. For example, if the function is invoked as gup('http://www.alteryx.com/index.html?foo=bar&?data=123', 'foo')
it will return 'bar'
.
const gup = (url, name) => {
name = name.replace(/[\[]/, '\\\[').replace(/[\]]/, '\\\]')
const regexS = '[\\#&]' + name + '=([^&#]*)'
const regex = new RegExp(regexS)
const results = regex.exec(url)
if (results == null) {
return ''
} else {
return results[1]
}
}
Online Method - validateToken
After the access token is parsed from the URL, it is validated with the JQuery ajax
method. The settings
object is the only argument for $.ajax
needed because it contains the validation URL and the access token.
If $.ajax
is successful, then the Google Analytics will continue to run normally otherwise the tool will error out.
const validateToken = (token) => {
const VALIDURL = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='
// API call settings
const settings = {
'async': true,
'crossDomain': true,
'url': VALIDURL + token,
'method': 'GET',
'dataType': 'jsonp'
}
return $.ajax(settings)
.done(ajaxSuccess)
.fail(connectionError)
}
Offline Method
The Offline method is a little more straight forward. As stated above, the user will can get their developer credentials through the help documentation.
Here we'll cover two main functions:
getAccessTokenAjaxCall
checkToken
Offline Method - getAccessTokenAjaxCall
Since the credentials are stored in Alteryx widgets, we can obtain them using the GetDataItem method as shown below. Similar to the validateToken
function above, store the values of the credentials in the settings
object and use it as an argument for $.ajax
.
const getAccessTokenAjaxCall = () => {
// Add vars for each of the user text box inputs
const clientID = Alteryx.Gui.manager.GetDataItem('client_id').value
const clientSecret = Alteryx.Gui.manager.GetDataItem('client_secret').value
const refreshToken = Alteryx.Gui.manager.GetDataItem('refresh_token').value
// API call settings
const settings = {
'async': true,
'crossDomain': true,
'url': 'https://accounts.google.com/o/oauth2/token',
'method': 'POST',
'dataType': 'json',
'headers': {
'cache-control': 'no-cache',
'content-type': 'application/x-www-form-urlencoded'
},
'data': {
'client_id': clientID,
'client_secret': clientSecret,
'refresh_token': refreshToken,
'Host': 'accounts.google.com',
'grant_type': 'refresh_token'
}
}
return $.ajax(settings)
.done(checkToken)
.fail(connectionError)
}
Offline Method - checkToken
If the AJAX request was successful, checkToken will proceed to run. Here we obtain the access token and set the value of the 'accessToken' DataItem to the access token we just received. Once set, we remove any error messaging and display the proper HTML page to the user.
const checkToken = (data) => {
if (typeof data.errors === 'undefined') {
// Set access token
const accessToken = data.access_token
Alteryx.Gui.manager.GetDataItem('accessToken').setValue(accessToken)
}
// Remove any error messaging
store.errorStatus = ''
// Change page to current page or profileSelectors
console.log('store page: ' + store.page)
switch (store.page) {
case '':
displayFieldset('#accessMethod')
break
case '#offlineCreds':
store.page = '#profileSelectors'
displayFieldset('#profileSelectors')
break
default:
displayFieldset(store.page)
}
}
Store Access Token in Data Items
Now if you noticed in both the Online and Offline methods, the access token is stored in the accessToken
DataItem. Once this value is stored in this DataItem, it will actually be passed down into a textbox interface tool inside Google_Analytics.yxmc macro, which is the engine of the connector. This DataItem can be associated with the TextBox interface matching annotation name. When this happens the DataItem will now be present in this tools configuration XML. When the tool runs, the access token will be available in stream and will eventually get passed on to a Download tool as a header in the subsequent calls. This must done for any key-value pair if it needs to be used in the macro engine.
And that's it! This is how authentication works for the Google Analytics connector. Other tools that use this method include Adobe Analytics and Google Sheets.
Please ask any questions and share any comments or tools you've created! We love seeing what fellow Alteryx developers build.
Software Engineer
Ozzie is a Software Engineer that began his career at Alteryx as a Customer Support Engineer in January of 2016. After learning the in's and out's of Alteryx and having a love for building stuff, he couldn't help himself but tinker more with the product and create custom tools and macros every chance he could. Ozzie now spends his days building tools that keep pushing the boundaries of what Alteryx can provide. When he is not coding, he is probably traveling or critiquing beer.
Ozzie is a Software Engineer that began his career at Alteryx as a Customer Support Engineer in January of 2016. After learning the in's and out's of Alteryx and having a love for building stuff, he couldn't help himself but tinker more with the product and create custom tools and macros every chance he could. Ozzie now spends his days building tools that keep pushing the boundaries of what Alteryx can provide. When he is not coding, he is probably traveling or critiquing beer.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.