DEV Community

linou518
linou518

Posted on

Building a Permission Binding System Between LINE Bot and In-House ERP via Phone Number Matching

Building a Permission Binding System Between LINE Bot and In-House ERP via Phone Number Matching

We wanted staff to check inventory via LINE — but not let just anyone access it.

That simple requirement led to what we built: a LINE × ERP permission binding system.

Background

At TechsFree, we develop and operate our own ERP for a food/produce wholesale business. Letting staff check inventory and sales figures directly via LINE Bot would make field operations much smoother — so we built a bridge between LINE Bot and the ERP backend.

The problem: LINE's userId (Uxxxxxxxx...) and ERP's internal user accounts (email + password) are completely separate. Without knowing "who is this LINE user?", we can't enforce any permission checks.

Solution: Phone Number Matching

Our ERP user table already had a phone column. When someone messages the bot, we simply ask for their phone number, look up the matching ERP user, and bind them.

-- Add LINE-related columns to users table
ALTER TABLE users ADD COLUMN line_user_id VARCHAR(64) UNIQUE NULL;
ALTER TABLE users ADD COLUMN line_display_name VARCHAR(255) NULL;
Enter fullscreen mode Exit fullscreen mode

Since we use Sequelize, adding fields to User.ts means they're automatically synced at startup.

API Design

We added three endpoints:

GET  /api/line/user/:line_user_id   # Look up identity by LINE ID
POST /api/line/bind                  # Bind a LINE user to an ERP account via phone
POST /api/line/unbind                # Remove the binding
Enter fullscreen mode Exit fullscreen mode

The response from /api/line/user/:id looks like this:

// Not yet bound
{ "bound": false }

// Bound
{
  "bound": true,
  "user": {
    "id": 1,
    "name": "Tanaka Taro",
    "role": "admin",
    "permissions": [
      "sales", "purchases", "inventory",
      "products", "customers", "suppliers",
      "payments", "reports", "staff"
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Permission Groups

We kept roles simple — just two types:

Role Access
admin Sales / Purchases / Inventory / Products / Customers / Suppliers / Payments / Reports / Staff
user (staff) Inventory / Products / Purchases / Sales / Shipping

We considered a customer role, but regular customers don't need to see ERP inventory directly — that's what the shop frontend is for. Keeping it simple matters.

Integration Flow with the Agent

The LINE Bot itself runs on a dedicated agent on a separate server. When the agent receives a LINE message, it first calls /api/line/user/:line_user_id to check bound:

  • bound: false → Guide the user through the binding flow ("Please share your phone number")
  • bound: true → Present available features based on permissions

The agent calls the ERP API directly (no auth token needed within the internal network).

Where We Got Stuck

TypeScript type definitions were surprisingly annoying. Adding a new column to a User model requires both the sequelize-typescript decorator and Sequelize's sync to be written correctly — otherwise you get runtime errors even when compilation succeeds.

@Column({ type: DataType.STRING(64), unique: true, allowNull: true })
line_user_id!: string | null;
Enter fullscreen mode Exit fullscreen mode

Forgetting allowNull: true will kill existing record sync.

The other gotcha: LINE's channelAccessToken case sensitivity issue. A 401 kept appearing, and we spent time suspecting a typo (uppercase E vs lowercase e). The real issue was that the token itself had been invalidated — regenerating it in LINE Developers Console solved it instantly. The lesson: don't trust your eyes on log characters too much.

Takeaways

Integrating external Bot permission checks into an in-house ERP turned out to be simpler than expected.

Key points:

  1. Use an existing attribute (phone number) for matching — no OAuth needed
  2. Manage binding state on the ERP side — keep the Bot stateless
  3. Return permissions as a flat list — keeps Bot logic simple

"I want to connect LINE with our ERP" is a common requirement in business systems. If you already have a phone number column in your user table, this approach lets you skip building a whole auth infrastructure.

Top comments (0)