Chapter 3: Essential Weapon for Taiwan's Freelance Projects: Line Login Developer Console Setup and Callback Integration

In the previous chapter, we successfully conquered Google Login. However, in the business environments of Taiwan, Japan, and Southeast Asia, almost no B2C (Business-to-Consumer) project can skip Line Login.

Clients will inevitably demand: "I want users to log in with one click—no passwords to remember! Every Taiwanese has Line on their phone!"
The business value behind this statement is staggering: If you successfully guide users to log in via Line, you not only gain their basic profile data but can also directly link them to your Line Official Account. Once linked, you can use the Line Messaging API to send "personalized promotional messages" straight to their phones with push notifications! This is the most powerful marketing weapon for modern SaaS platforms.

In this chapter, we'll guide you step-by-step through the Line Developers Console and elegantly integrate Line Login into our existing Auth.js architecture.


🟢 Step 1: Line Developers Console Survival Guide

Unlike Google Cloud Console's enterprise-grade interface, Line's backend is simpler but hides many pitfalls.

1. Create a Provider (Company/Developer Name)

  1. Go to the LINE Developers Console and log in with your personal Line account.
  2. Click the Create button next to Providers.
    (Note: A Provider represents the "company or team name developing this application," e.g., `VibeTutor Inc.`. This name appears on the user authorization screen, so use a real and professional name.)

2. Create a LINE Login Channel

A Provider can host multiple Channels (e.g., one for Login, another for a Messaging API bot).

  1. Click your newly created Provider and select "Create a new channel."
  2. Choose "LINE Login."
  3. Fill in the details:
    • Channel type: LINE Login
    • Provider: VibeTutor Inc.
    • Region to provide the service: Select Taiwan or Global.
    • Channel icon: Highly recommended—this is the user's first impression.
    • Channel name: Enter `VibeTutor Website Login`.
    • Channel description: Briefly describe your service.
    • App types: Check `Web app` (we're building web login—do NOT check Native app).
  4. Agree to the terms and click Create.

3. Obtain the Keys (Channel ID & Secret)

After creation, you'll land on the Channel overview page.
Under the Basic settings tab, scroll down to find two critical pieces of information:

  • Channel ID: Copy this—it’s equivalent to the OAuth Client ID.
  • Channel secret: Copy this—it’s equivalent to the OAuth Client Secret.

4. Set the Callback URL

As we learned in the last chapter, after users log in via Line, Line needs to know where to send the "Authorization Code."

  1. Switch to the LINE Login tab.
  2. Under the Web app section, click Edit next to Callback URL.
  3. Enter Auth.js's default callback path:
    👉 `http://localhost:3000/api/auth/callback/line`
    (🚨 Note: When deploying to Vercel later, remember to add your production domain URL here.)
  4. Click Update to save.

5. The Final Boss: Publish Your Channel

This is where 99% of beginners get stuck!
At the top of the page, you'll see a label saying `Developing` (Under Development).
In this state, only your own Line account can log in—everyone else will see an error!

  • Click the `Developing` label and boldly press `Publish`.
  • Once the status changes to `Published`, your login feature is truly live.

📧 Step 2: Requesting Email Permission (A Special Pitfall)

Unlike Google, Line does NOT provide the user's email by default!
It only gives you the user's name (displayName) and profile picture (pictureURL).

If your website relies on email as a unique identifier (e.g., for receipts or password resets), you must explicitly request permission from Line.

  1. Under the Basic settings tab, scroll to the bottom.
  2. Find Email address permission.
  3. Click `Apply` or `Request`.
  4. The system will ask for a screenshot proving your website informs users about email collection (e.g., your Privacy Policy page).
  5. Submit for review. Approval rates are high for legitimate applications.

⚠️ Vibe Coding Note:
If you skip this step, Auth.js will fail when forcing email requests! If you only need the Line ID (Profile Subject) for identification, you can skip this.


💻 Step 3: Integrating Line Provider into Auth.js

With the backend configured, let’s return to the code.

1. Update Environment Variables (.env.local)

Add the Line credentials you copied earlier:

```env

Existing Google credentials...

AUTH_GOOGLE_ID="12345..." AUTH_GOOGLE_SECRET="GOCSPX-..."

Add Line OAuth credentials

AUTH_LINE_ID="your_Channel_ID" AUTH_LINE_SECRET="your_Channel_Secret" ```

2. Update Core Configuration (src/auth.ts)

Open `src/auth.ts` and add LineProvider to the array. Auth.js's architecture shines here—adding a login method takes just a few lines:

```typescript import NextAuth from "next-auth" import GoogleProvider from "next-auth/providers/google" import LineProvider from "next-auth/providers/line" // Import Line

export const { handlers, signIn, signOut, auth } = NextAuth({ providers: [ GoogleProvider({ clientId: process.env.AUTH_GOOGLE_ID, clientSecret: process.env.AUTH_GOOGLE_SECRET, }), LineProvider({ clientId: process.env.AUTH_LINE_ID, clientSecret: process.env.AUTH_LINE_SECRET,

  // 🚨 If you didn’t request email permission, DO NOT add extra scopes here.
  // By default, it only requests 'profile' and 'openid'.
  
  // 🚨 Hidden Landmine: OIDC Compliance
  // Auth.js v5 strictly follows OIDC standards, which may conflict with Line's state handling.
  // If you encounter state errors during login, uncomment this line:
  // checks: ["state"], 
}),

], }) ```

3. Test the Dual-Login Interface!

Ensure your `npm run dev` server is running.
Open your browser and navigate to: `http://localhost:3000/api/auth/signin`

Behold the magic! Your minimalist login page now displays two buttons:

  1. Sign in with Google
  2. Sign in with LINE

Clicking Line Login redirects to Line’s green authorization screen. On mobile, it even opens the Line App for passwordless auth! Upon success, you’ll seamlessly return to `localhost`.


🤝 Advanced Topic: The Challenge of Account Linking

When offering multiple login methods, architects face a critical business logic challenge:

Scenario:
Xiao Ming logged in yesterday with `ming@gmail.com` via Google and bought a course.
Today, on a new phone, he forgot his login method and clicked "Sign in with Line."
Coincidentally, his Line account also uses `ming@gmail.com`.

The Problem:
Should your system treat these as "the same Xiao Ming" or "two different users"?

  • Treating them as different users will frustrate Xiao Ming—his purchased course disappears.
  • Automatically merging them poses security risks (e.g., email spoofing).

This is known as Account Linking.

Fortunately, with Supabase Adapter (which we’ll use), the default behavior is:
"Different providers with the same email are NOT auto-merged unless explicitly consented, preventing account hijacking."
Handling this requires a robust relational database. Stay tuned for the next chapter: Ditching Cookie Sessions and embracing Supabase PostgreSQL Adapter integration!

Account Linking Flow

1. User signs in with Google (new account created in DB)
2. User signs out
3. User signs in with email/password (same email)
4. NextAuth + Supabase Adapter sees the email already exists
5. Instead of silently merging, system asks: "Link this account?"
6. User must explicitly confirm before accounts are linked
7. Once linked, user can sign in with either method

Why Not Auto-Merge?

| Concern | Explanation | |---------|-------------| | Email spoofing | An attacker could claim your email via an unverified provider | | User confusion | Merged accounts behave unexpectedly | | Audit trail | Which provider was used for which action? | | Security boundaries | Some providers have different trust levels |

Implementing Account Linking

// pages/api/auth/[...nextauth].js
import NextAuth from 'next-auth';
import GoogleProvider from 'next-auth/providers/google';
import CredentialsProvider from 'next-auth/providers/credentials';
import { SupabaseAdapter } from '@auth/supabase-adapter';

export const authOptions = {
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
    CredentialsProvider({
      name: 'Email',
      credentials: {
        email: { label: 'Email', type: 'email' },
        password: { label: 'Password', type: 'password' },
      },
      async authorize(credentials) {
        // Verify against your database
        const user = await db.users.findByEmail(credentials.email);
        if (user && user.password === hash(credentials.password)) {
          return user;
        }
        return null;
      },
    }),
  ],
  adapter: SupabaseAdapter({
    url: process.env.SUPABASE_URL,
    secret: process.env.SUPABASE_SERVICE_ROLE_KEY,
  }),
  callbacks: {
    async signIn({ user, account, profile }) {
      // Check if this email already has a different provider
      const existingAccounts = await db.accounts.findByUserId(user.id);
      
      if (existingAccounts.length > 0 && 
          !existingAccounts.find(a => a.provider === account.provider)) {
        // This is a new provider for an existing user
        // Return true to auto-link, or redirect to consent page
        return '/auth/link-account';
      }
      
      return true;
    },
  },
};

Summary

Account linking is the challenge of recognizing the same user across different authentication providers. The Supabase Adapter does NOT auto-merge by default, preventing account hijacking. Implement explicit consent flows and handle linking carefully.

Key takeaways:

  • Same email across different providers = potentially same user
  • Auto-merging by email alone is a security risk
  • Supabase Adapter stores accounts per provider, not per email
  • Users should explicitly consent to account linking
  • Implement a consent page for users to approve linking
  • Always maintain an audit trail of which provider was used

What's Next: Supabase PostgreSQL Adapter

The next chapter dives into the Supabase PostgreSQL adapter — replacing cookie sessions with a persistent database for production-grade authentication.

Unlock Full Tutorial

This chapter is paid content. Join the project to unlock over 5000 words of deep analysis, including 10+ god-tier Prompts and real Source Code examples!