Reputation: 225
I'm building a Google Data Studio connector to a third party source, Siteimprove. Siteimprove has an api which requires Basic Access Authentication.
I've setup the authentication for username and token (I've also tried username and password) in my google apps script, with all the required functions based on the documentation
-edit- as requested the full code for these functions
/**
* Returns the Auth Type of this connector.
* @return {object} The Auth type.
*/
function getAuthType() {
var cc = DataStudioApp.createCommunityConnector();
return cc.newAuthTypeResponse()
.setAuthType(cc.AuthType.USER_TOKEN)
.setHelpUrl('http://developer.siteimprove.com/v1/get-access/')
.build();
}
/**
* Resets the auth service.
*/
function resetAuth() {
var user_tokenProperties = PropertiesService.getUserProperties();
user_tokenProperties.deleteProperty('dscc.username');
user_tokenProperties.deleteProperty('dscc.password');
}
/**
* Returns true if the auth service has access.
* @return {boolean} True if the auth service has access.
*/
function isAuthValid() {
var userProperties = PropertiesService.getUserProperties();
var userName = userProperties.getProperty('dscc.username');
var token = userProperties.getProperty('dscc.token');
// This assumes you have a validateCredentials function that
// can validate if the userName and token are correct.
return validateCredentials(userName, token);
}
/**
* Sets the credentials.
* @param {Request} request The set credentials request.
* @return {object} An object with an errorCode.
*/
function setCredentials(request) {
var creds = request.userToken;
var username = creds.username;
var token = creds.token;
// Optional
// Check if the provided username and token are valid through a
// call to your service. You would have to have a `checkForValidCreds`
// function defined for this to work.
var validCreds = validateCredentials(username, token);
if (!validCreds) {
return {
errorCode: 'INVALID_CREDENTIALS'
};
}
var userProperties = PropertiesService.getUserProperties();
userProperties.setProperty('dscc.username', username);
userProperties.setProperty('dscc.token', token);
return {
errorCode: 'NONE'
};
}
function validateCredentials(userName,token){
var headers = {
"Authorization" : "Basic " + Utilities.base64Encode(userName + ':' + token)
};
var params = {
"method":"GET",
"headers":headers
};
var response = UrlFetchApp.fetch("https://api.siteimprove.com/v2/", params);
return response;
console.log(response);
}
And the manifest file
{
"dataStudio": {
"name": "Connector for Siteimprove",
"company": "<company name>",
"logoUrl": "<company logo url>",
"addonUrl": "",
"supportUrl": "",
"description": "This connector can be used to show basic data from Siteimprove"
}
}
When I run the script I get a prompt for credentials, but this is a prompt to connect with a google account
But I need a way to provide credentials for a third party service. If I use my google account I get a 401 response from the Siteimprove API, so that seems to work as expected.
Any clues how I would get a prompt to provide credentials for a third party service?
Upvotes: 2
Views: 2790
Reputation: 225
/**
* Returns the Auth Type of this connector.
* @return {object} The Auth type.
*/
function getAuthType() {
var cc = DataStudioApp.createCommunityConnector();
return cc.newAuthTypeResponse()
.setAuthType(cc.AuthType.USER_PASS)
.setHelpUrl('http://developer.siteimprove.com/v1/get-access/')
.build();
}
/**
* Resets the auth service.
*/
function resetAuth() {
var user_tokenProperties = PropertiesService.getUserProperties();
user_tokenProperties.deleteProperty('dscc.username');
user_tokenProperties.deleteProperty('dscc.password');
}
/**
* Returns true if the auth service has access.
* @return {boolean} True if the auth service has access.
*/
function isAuthValid() {
const usernameAndPassword = loadCurrentUsernameAndPassword();
return usernameAndPassword.username && usernameAndPassword.password && validateCredentials(usernameAndPassword.username, usernameAndPassword.password)
};
function loadCurrentUsernameAndPassword() {
const properties = PropertiesService.getUserProperties();
return {
username: properties.getProperty('dscc.username'),
password: properties.getProperty('dscc.password')
}
};
function setCredentials(request) {
var isCredentialsValid = validateCredentials(request.userPass.username, request.userPass.password);
if (!isCredentialsValid) {
return {
errorCode: "INVALID_CREDENTIALS"
};
} else {
storeUsernameAndPassword(request.userPass.username, request.userPass.password);
return {
errorCode: "NONE"
};
}
};
function validateCredentials(username, password) {
var rawResponse = UrlFetchApp.fetch('https://api.siteimprove.com/v2', {
method: 'GET',
headers: {
'Authorization': 'Basic ' + Utilities.base64Encode(username + ':' + password)
},
muteHttpExceptions: true
});
return rawResponse.getResponseCode() === 200;
}
function storeUsernameAndPassword(username, password) {
PropertiesService
.getUserProperties()
.setProperty('dscc.username', username)
.setProperty('dscc.password', password);
};
Upvotes: 3
Reputation: 789
Data Studio will always prompt first for Google Authorization, based on your script's scopes, and then for additional configuration based on your getAuthType()
function. Since your getAuthType()
function is USER_TOKEN
, after authorizing with google, you will have an additional prompt to authorize with those credentials.
The 4th step of the codelab outlines the flow of a connector, so you can see what functions are called when.
You also want to make sure that, at a minimum, you have defined getAuthType()
, getData()
, getSchema()
, and getConfig()
. Since you're using an auth type of USER_TOKEN
, there are additional methods you must defined as outlined in Authentication
Upvotes: 1