Skip to main content

Passwordless Sign-in Flow

In-container passwordless sign-in uses the Client SDK to obtain a one-time code. The app backend then exchanges the code for the current user's identity. The SDK handles the client-side authorization request; application pages do not call the client authorization API directly.

Prerequisites​

Configure the following items under "Internal Apps" in the admin console:

  1. The app is enabled, published, and has client display enabled.
  2. The desktop or mobile app entry point is configured.
  3. The actual application page is included in the in-container passwordless sign-in URL allowlist.
  4. The current user is within the app's visibility scope.

Flow​

Application page
│ 1. SDK calls requestWorkbenchAuthCode() and obtains a one-time code
│ 2. Sends the code to the app backend over HTTPS
▼
App backend
│ 3. POST /auth/v1/oauth/token to obtain access_token
│ 4. POST /auth/v1/oauth/userinfo?access_token=... with the code
▼
App backend receives {userId, nickName, avatar} and creates its own session

Frontend example​

<script src="/assets/sdk/twt-link-universal.umd.min.js"></script>
<script>
async function loginFromWorkbench() {
const sdk = window.__TWT_LINK__;
if (!sdk || !sdk.isTwtLinkPlateform()) {
window.location.href = "/login";
return;
}

const { code } = await sdk.requestWorkbenchAuthCode();
const response = await fetch("/api/workbench/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ code }),
});

if (!response.ok) {
throw new Error("Sign-in failed. Request a new authorization code.");
}
}

loginFromWorkbench();
</script>

The frontend only obtains and submits the code. It must not store client_secret, access_token, or user identity data.

Backend API calls​

1. Obtain an app token​

The app backend uses the server-side client_id and client_secret to call the Token API:

POST /auth/v1/oauth/token
Content-Type: application/json

{
"client_id": "app ID",
"client_secret": "app secret",
"grant_type": "client_credentials"
}

Successful response:

{
"access_token": "app access token",
"expires_in": 7200
}

2. Get the current user's information​

Use the returned access_token and the one-time frontend code to call the UserInfo API:

POST /auth/v1/oauth/userinfo?access_token=<access_token>
Content-Type: application/x-www-form-urlencoded

code=<code>

Successful response:

{
"userId": "10001",
"nickName": "Zhang San",
"avatar": "https://cdn.example.com/avatar/10001.png"
}

The code is single-use and becomes invalid immediately after exchange. Keep client_secret and access_token on the app backend; never expose them to the frontend.

Common errors​

HTTP statusError codeHandling
400INVALID_REQUESTCheck access_token, code, and the request format.
400INVALID_GRANTThe code expired, was already used, or does not match the app; request a new code.
401INVALID_TOKENObtain a new app access_token.
403USER_NOT_VISIBLECheck whether the user is within the app's visibility scope.
500SERVER_ERRORRetry later.