Google Data Studio 连接器在第三方进行身份验证

Google Data Studio connector authenticate at third party

我正在构建一个 Google Data Studio 连接器到第三方源 Siteimprove。 Siteimprove 有一个 api 需要 Basic Access Authentication.

我已经在我的 google 应用程序脚本中设置了 username and token 的身份验证(我也尝试了用户名和密码),所有必需的功能都基于文档

-edit- 根据要求这些函数的完整代码

/**
 * 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);
}

和清单文件

{
  "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"
  }
}

当我 运行 脚本时,我收到输入凭据的提示,但这是连接 google 帐户的提示

但我需要一种方法来为第三方服务提供凭据。 如果我使用我的 google 帐户,我会从 Siteimprove API 收到 401 响应,因此这似乎按预期工作。

关于我如何获得为第三方服务提供凭据的提示的任何线索?

Data Studio 将始终根据您的脚本范围首先提示 Google 授权,然后根据您的 getAuthType() 函数进行其他配置。由于您的 getAuthType() 函数是 USER_TOKEN,在使用 google 授权后,您将看到一个额外的提示,要求您使用这些凭据进行授权。

The 4th step 的 Codelab 概述了连接器的流程,因此您可以了解什么时候调用了哪些函数。

您还需要确保至少定义了 getAuthType()getData()getSchema()getConfig()。由于您使用的是 USER_TOKEN 的身份验证类型,因此您必须定义其他方法,如 Authentication

中所述
/**
* 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);
  };