I tried verifying connectivity for each authentication method using ZAF's Secure Settings

I tried verifying connectivity for each authentication method using ZAF's Secure Settings

In ZAF Secure Settings, secure values are not returned to JavaScript, and placeholders are string substitution only. Based on this mechanism, here is a summary of the connectivity test results for authenticated APIs using multiple authentication methods, and the correct way to connect with Basic authentication.
2026.07.11

This page has been translated by machine translation. View original

Introduction

There was a situation where I needed to connect from a ZAF (Zendesk Apps Framework) app to an endpoint with Basic authentication provided by the other party. At first, authentication kept failing with 401 and I was a bit confused, but the cause was that I had misunderstood how ZAF's Secure Settings work.

Secure setting values are not returned to JavaScript. Placeholders only perform string substitution and do not perform base64 encoding. Keeping these two points in mind will allow you to smoothly connect to APIs with authentication.

This article summarizes the results of testing connectivity to an authenticated API from ZAF using multiple authentication methods, along with the knowledge gained from that experience.

Target Audience

  • Those who want to connect to an external API with authentication from a ZAF app
  • Those struggling with authentication failures despite using Secure Settings

References

The Problem

Initially, I held the authentication credentials username and password as separate settings and assembled the Authorization header on the frontend. It was written something like 'Basic ' + base64(user + ':' + password). At that time, the secure option in client.request was not set.

This worked locally. However, after deploying to the tenant and entering actual values into the secure settings, the authenticated API started returning 401 and an error saying "please check your credentials" would not go away. Also, the browser reacted to the WWW-Authenticate returned by the server, and a native Basic authentication dialog appeared.

Basic authentication dialog

Root Cause Investigation

Re-reading the official documentation revealed the cause. Setting values declared with secure: true are not returned to the frontend via client.metadata().

The correct approach was to write a {{setting.NAME}} placeholder in the header to include the secure value in the request, and set secure to true in client.request. This causes the Zendesk proxy to substitute the actual value on the server side. There is no need to assemble base64 on the frontend — in fact, you must not assemble it there.

Connectivity Testing

Using httpbingo.org as the authentication endpoint, I tested 5 authentication methods with ZAF's client.request(). The results are as follows.

# Authentication Method Result What I Learned
1 Basic · manually base64-encoded value as a single secure setting Success (200) Works if you base64-encode in advance and put it in one setting
2 Basic · basic_auth.token Success (200) Proxy handles base64 encoding, no manual conversion needed
3 Bearer token Success (200) Works as-is with placeholder + secure
4 API key header Success (200) Works without specifying scope · explicit specification recommended
5 Frontend base64 generation Failure (401) Gets base64-encoded before substitution, and authentication dialog appears

Result 1
Connectivity testing using a sidebar app. Cases 1~3

Result 2
Connectivity testing using a sidebar app. Cases 3~5

Case 1 is a method where the user:passwd value is manually base64-encoded and stored in a single secure setting, with only a placeholder written in the header.

// Basic authentication · storing a manually base64-encoded value in a single secure setting
client.request({
  url: 'https://httpbingo.org/basic-auth/user/passwd',
  type: 'GET',
  secure: true,
  headers: { Authorization: 'Basic {{setting.basicManualB64}}' }
});

Case 2 uses the official basic_auth mechanism. You pass the username and password, and write {{basic_auth.token}} in the header; the proxy concatenates them and base64-encodes them. No manual base64 encoding is required.

// Basic authentication · basic_auth.token method · proxy handles base64 encoding
client.request({
  url: 'https://httpbingo.org/basic-auth/user/passwd',
  type: 'GET',
  basic_auth: { username: 'user', password: '{{setting.basicPassword}}' },
  secure: true,
  headers: { Authorization: 'Basic {{basic_auth.token}}' }
});

Case 4 is worth noting. Since httpbingo's /headers returns the request headers as-is, you can see the actual values after the proxy has inserted them on the server side. Traces of the Zendesk proxy appear in this echo, confirming that the request is sent from the server side via the proxy rather than directly from the frontend.

The actual value inserted by the proxy appears in X-Api-Key, and traces of the Zendesk proxy appear in Via and X-Zendesk-*.

{
  "headers": {
    "X-Api-Key": ["(actual value inserted by proxy)"],
    "Via": ["zorg, 1.1 fly.io, 1.1 fly.io"],
    "X-Zendesk-User-Role": ["admin"],
    "X-Requested-With": ["XMLHttpRequest"],
    "Zendesk-Internet-Path": ["cloudflare"]
  }
}

On the other hand, in the browser's developer tools Network tab, the same header is displayed as the placeholder {{setting.apiKey}}. This confirms that actual values only appear beyond the proxy.

Case 4 · Network tab shows placeholder as-is
Only the placeholder appears in the browser; the actual value is inserted on the server side

Why You Must Not base64-Encode on the Frontend

Case 5 reproduces the implementation I originally wrote. It uses btoa() on the frontend to base64-encode the placeholder before inserting it into the header.

// Approach to avoid · base64-encoding the placeholder with btoa
client.request({
  url: 'https://httpbingo.org/basic-auth/user/passwd',
  type: 'GET',
  secure: true,
  headers: { Authorization: 'Basic ' + btoa('{{setting.basicManualB64}}') }
});

Since btoa() runs before the proxy's substitution, the placeholder string itself gets base64-encoded and sent. The {{setting.NAME}} pattern that the proxy looks for is destroyed, so no substitution occurs, and the incorrect credentials arrive, resulting in 401.

Furthermore, since this 401 is accompanied by WWW-Authenticate, the browser's native Basic authentication dialog appears even via client.request. Not only does authentication fail, but the user is also shown an authentication dialog.

Case 5 · Browser Basic authentication dialog appears on 401
Frontend base64 encoding causes authentication failure and even triggers a dialog

What I Learned

The knowledge gained from the connectivity testing is as follows.

Since secure values are not returned to the frontend, avoid designing authentication credentials to be assembled on the frontend. For Basic authentication, either base64-encode the value yourself and store it in a single secure setting, or use the basic_auth.token method to have the proxy handle base64 encoding. Bearer tokens and API keys work as-is with placeholder + secure.

For operational purposes, it is recommended to explicitly specify the scope. Without it, secure values may be used with unintended scopes. Also, after saving, the Admin Center input field for secure settings will appear empty, but this does not mean the value was not saved.

Secure settings
Go to Admin Center → Zendesk Support Apps → select the created app, enter the secure settings, and update

Empty display
After updating, the input field appears empty

Summary

ZAF's Secure Settings are designed so that secure values are not returned to the frontend, and placeholders only perform string substitution. Keeping these two points in mind will allow you to connect to APIs with authentication. The connectivity testing confirmed that for Basic authentication, you can either base64-encode the value yourself or use the basic_auth.token method. I hope this is helpful for those who have been confused by the same issues.


Zendeskの導入支援ならクラスメソッドへ

クラスメソッドはZendeskのライセンス販売パートナーです。Zendesk導入にあたって、設定代行、オペレーターや管理者向けのトレーニング、独自のアプリ開発、データ移行など、様々なサービスをご提供しております。既に導入済みのお客様に対してもご支援できますので、まずはお気軽にご相談ください。

Zendeskの導入支援の詳細を見る

Share this article