# How to Use LIFF with LINEJS: Complete Integration Guide

> Integrate LIFF with LINEJS using the built-in LiffService. Automate token issuance consent and message sending with the client liff API for seamless LIFF operations.

- Repository: [Evex  Developers/linejs](https://github.com/evex-dev/linejs)
- Tags: how-to-guide
- Published: 2026-03-01

---

**LINEJS provides a built-in `LiffService` that automates LIFF token issuance, consent handling, and message sending through the `client.liff` API, requiring only a logged-in `BaseClient` instance to execute LIFF operations.**

The LINE Frontend Framework (LIFF) enables web applications to integrate with the LINE messaging platform and access user context. LINEJS, an open-source TypeScript library for LINE automation, abstracts the complex LIFF protocol through its `LiffService` class. This guide demonstrates how to use LIFF with LINEJS to issue access tokens, handle user consent flows, and send messages without managing low-level Thrift encoding manually.

## Architecture of LIFF Integration in LINEJS

LINEJS implements LIFF support through a layered architecture centered on the `BaseClient` class. When you instantiate a client, it automatically creates a `LiffService` instance exposed as `client.liff`.

### Core Components

- **BaseClient** – The central entry point defined in [`packages/linejs/base/core/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/core/mod.ts) that initializes `LiffService` and exposes it as `client.liff`. It handles authentication, storage, and request routing.
- **LiffService** – The primary implementation located in [`packages/linejs/base/service/liff/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/service/liff/mod.ts) that provides `issueLiffView`, `getLiffToken`, `sendLiff`, and consent helpers (`tryConsentLiff`, `tryConsentAuthorize`).
- **LINETypes** – TypeScript definitions for LIFF structures such as `LiffViewResponse` stored in [`packages/types/line_types.ts`](https://github.com/evex-dev/linejs/blob/main/packages/types/line_types.ts).
- **RequestClient** – Low-level Thrift request wrapper in [`packages/linejs/request/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/request/mod.ts) used internally by `LiffService` to communicate with LINE's backend.

### LIFF Token Flow

When you call `client.liff.getLiffToken()`, the service executes this workflow:

1. **Issue LIFF View** – Calls `issueLiffView` to request a short-lived access token for the specified user or chat.
2. **Consent Handling** – If the server returns `CONSENT_REQUIRED`, the service automatically executes `tryConsentLiff` (in-app flow) or `tryConsentAuthorize` (web flow) to obtain user approval without manual intervention.
3. **Token Retrieval** – Extracts the `accessToken` from the `LiffViewResponse` and caches it for subsequent operations.

## Step-by-Step: Using LIFF with LINEJS

Follow these steps to integrate LIFF functionality into your LINEJS application:

1. **Initialize BaseClient** – Create a client instance with your preferred device type (iOS, Android, Desktop, etc.).
2. **Authenticate** – Log in using email/password, QR code, or OAuth token to establish a valid session.
3. **Configure LIFF ID** – Optionally override the default LIFF ID (`2006747340-AoraPvdD`) with your registered application ID.
4. **Obtain LIFF Token** – Call `client.liff.getLiffToken()` with the target chat MID to retrieve an access token.
5. **Send Messages** – Use `client.liff.sendLiff()` to post messages to the target conversation using the obtained token.

## Complete Code Example

The following example demonstrates a full LIFF workflow from initialization to message delivery:

```typescript
import { BaseClient } from "@evex/linejs";

// 1️⃣ Initialise the client (device must be one of the supported strings)
const client = new BaseClient({
  device: "iOS",            // or "Android", "DESKTOP", …
  version: "15.0",          // optional device version
});

// 2️⃣ Perform login (example: email/password)
await client.loginProcess.login({
  email: "you@example.com",
  password: "yourPassword",
});

// 3️⃣ Obtain a LIFF token for a specific chat (or user MID)
const liffToken = await client.liff.getLiffToken({
  chatMid: "u1234567890abcdef", // target user MID (optional)
  liffId: "2006747340-AoraPvdD", // replace with your own LIFF ID if needed
});

// 4️⃣ Send a simple text message via LIFF
await client.liff.sendLiff({
  to: "u1234567890abcdef", // same MID as above
  messages: [{ type: "text", text: "Hello from LINE JS + LIFF!" }],
});

```

### Implementation Breakdown

| Line | Component | Description |
|------|-----------|-------------|
| `new BaseClient(...)` | **BaseClient** | Instantiates the core client, which creates `client.liff` automatically. |
| `loginProcess.login(...)` | **Auth** | Authenticates the session and sets `client.authToken`. |
| `client.liff.getLiffToken(...)` | **LiffService** | Calls `issueLiffView` internally; handles consent automatically if required. |
| `client.liff.sendLiff(...)` | **LiffService** | Posts the message array to `https://api.line.me/message/v3/share` using the retrieved token. |

> **Note** – If `issueLiffView` returns a `CONSENT_REQUIRED` error, the `LiffService` automatically executes `tryConsentLiff` (in‑app flow) or `tryConsentAuthorize` (web flow) and retries the token request without manual intervention.

## Advanced LIFF Operations

### Custom LIFF ID Configuration

While LINEJS uses a default LIFF ID (`2006747340-AoraPvdD`), production applications should register their own LIFF app in the LINE Developers Console and override this default:

```typescript
const customId = "12345678-YourCustomId";
await client.liff.getLiffToken({
  chatMid: "u1234567890abcdef",
  liffId: customId,
});

```

### Consent Flow Implementation Details

The `LiffService` in [`packages/linejs/base/service/liff/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/service/liff/mod.ts) implements two consent strategies:

- **In‑app consent** (`tryConsentLiff`): Posts to `https://access.line.me/dialog/api/permissions` with the channel ID and current LINE access token. This flow executes when the client runs on desktop or mobile environments with direct API access.
- **Web consent** (`tryConsentAuthorize`): Fetches the consent page, extracts the CSRF token using the regex `/<input type="hidden" name="__csrf"…/`, then POSTs the permission grant to `https://access.line.me/oauth2/v2.1/authorize/consent`.

Both methods return a boolean indicating success; `getLiffToken` automatically retries the LIFF view request upon successful consent.

### Token Caching Strategy

`LiffService` maintains an internal `liffTokenCache` object that stores access tokens mapped by target MID to avoid redundant `issueLiffView` calls. To bypass caching and force a fresh token issuance—useful when permissions change or tokens expire prematurely—set the `forceIssue: true` option:

```typescript
await client.liff.sendLiff({
  to: "u1234567890abcdef",
  messages: [{ type: "text", text: "Forced refresh" }],
  forceIssue: true,
});

```

## Summary

- **LINEJS** exposes LIFF functionality through the `client.liff` API, which is an instance of `LiffService` created automatically by `BaseClient` during initialization in [`packages/linejs/base/core/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/core/mod.ts).
- The **`getLiffToken`** method handles the complete LIFF lifecycle: issuing views via `issueLiffView`, processing consent via `tryConsentLiff` or `tryConsentAuthorize`, and retrieving access tokens.
- **Source files** for LIFF operations are located in [`packages/linejs/base/service/liff/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/service/liff/mod.ts) (service logic) and [`packages/linejs/base/core/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/core/mod.ts) (client initialization).
- **Token caching** is automatic, but you can force fresh issuance with `forceIssue: true` when calling `sendLiff`.
- All network communication uses the internal `RequestClient` (Thrift-based) and standard HTTP POSTs to LINE's messaging endpoints.

## Frequently Asked Questions

### How do I handle LIFF consent errors manually in LINEJS?

You typically do not need to handle consent manually. The `LiffService` in [`packages/linejs/base/service/liff/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/service/liff/mod.ts) automatically detects `CONSENT_REQUIRED` errors from `issueLiffView` and executes either `tryConsentLiff` (in-app flow) or `tryConsentAuthorize` (web flow) before retrying the token request. If you need to disable automatic consent or implement a custom flow, you would need to extend the `LiffService` class and override the consent methods.

### What is the default LIFF ID in LINEJS and should I change it?

The default LIFF ID used by LINEJS is `2006747340-AoraPvdD`, defined in the `LiffService` implementation. For production applications, you should register your own LIFF application in the LINE Developers Console and override this default by passing your custom `liffId` parameter to `getLiffToken` or `sendLiff` methods. Using your own LIFF ID ensures proper branding and permission scopes for your specific use case.

### How does LINEJS cache LIFF tokens and when should I force a refresh?

`LiffService` maintains an internal `liffTokenCache` object that stores access tokens mapped by target MID to avoid redundant `issueLiffView` calls. Tokens are reused for subsequent `sendLiff` operations until they expire or the process restarts. To bypass caching and force a fresh token issuance—useful when permissions change or tokens expire prematurely—set the `forceIssue: true` option in your `sendLiff` or `getLiffToken` method calls.

### Can I use LINEJS LIFF features without logging in?

No, LIFF operations require an authenticated session because `LiffService` relies on the `authToken` and device information stored in `BaseClient` to sign Thrift requests to LINE's backend. The `issueLiffView` method specifically requires valid authentication credentials to generate access tokens for specific users or chats. You must complete the login process via `client.loginProcess.login()` before invoking any `client.liff` methods.