เพิ่มการยืนยันตัวตนให้กับแอป Auth.js (Next Auth) ของคุณ (Add authentication to your Auth.js (Next Auth) application)
คู่มือนี้จะแสดงวิธีการผสาน Logto เข้ากับแอป Next.js ของคุณด้วย Auth.js (ชื่อเดิม Next Auth)
- ในคู่มือนี้ เราถือว่าคุณได้ตั้งค่า Next Auth ในโปรเจกต์ Next.js ของคุณแล้ว หากยังไม่ได้ตั้งค่า โปรดดู เอกสาร Next Auth เพื่อเริ่มต้น
ข้อกำหนดเบื้องต้น
- มีบัญชี Logto Cloud หรือ Logto แบบโฮสต์เอง
- สร้างแอปพลิเคชันแบบ traditional ใน Logto แล้ว
- มีโปรเจกต์ Next.js ที่ติดตั้ง Auth.js แล้ว ดูรายละเอียดได้ที่ เอกสาร Auth.js
การติดตั้ง
ติดตั้ง Auth.js ผ่านตัวจัดการแพ็กเกจที่คุณชื่นชอบ:
- npm
- pnpm
- yarn
npm i next-auth@beta
pnpm add next-auth@beta
yarn add next-auth@beta
ดูรายละเอียดเพิ่มเติมได้ที่ เอกสาร Auth.js
การผสานระบบ
ตั้งค่าผู้ให้บริการ Auth.js
คุณสามารถค้นหาและคัดลอก "App Secret" ได้จากหน้ารายละเอียดแอปพลิเคชันใน Admin Console:

ปรับแต่งการตั้งค่า API route ของ Auth.js โดยเพิ่ม Logto เป็นผู้ให้บริการ OIDC:
- Auth.js v5
- Next Auth v4
ตั้งค่าตัวแปรสภาพแวดล้อม:
AUTH_LOGTO_ISSUER=https://xxxx.logto.app/oidc
AUTH_LOGTO_ID=your-logto-app-id
AUTH_LOGTO_SECRET=your-logto-app-secret
import { handlers } from '@/auth';
export const { GET, POST } = handlers;
import NextAuth from 'next-auth';
import Logto from 'next-auth/providers/logto';
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [Logto],
});
จากนั้นคุณสามารถเพิ่ม Middleware เสริมเพื่อให้ session คงอยู่ได้:
export { auth as middleware } from '@/auth';
import NextAuth from 'next-auth';
const handler = NextAuth({
providers: [
{
id: 'logto',
name: 'Logto',
type: 'oauth',
// คุณสามารถรับ well-known URL ได้จากหน้า Application Details ของ Logto
// ในช่อง "OpenID Provider configuration endpoint"
wellKnown: 'https://xxxx.logto.app/oidc/.well-known/openid-configuration',
authorization: { params: { scope: 'openid offline_access profile email' } },
clientId: '<logto-app-id>',
clientSecret: '<logto-app-secret>',
client: {
id_token_signed_response_alg: 'ES384',
},
profile(profile) {
// คุณสามารถปรับแต่งการแมปโปรไฟล์ผู้ใช้ที่นี่
return {
id: profile.sub,
name: profile.name ?? profile.username,
email: profile.email,
image: profile.picture,
};
},
},
],
});
export { handler as GET, handler as POST };
- แทนที่ URL ใน
wellKnown
ด้วย "OpenID Provider configuration endpoint" ของแอป Logto ของคุณ - แทนที่
clientId
และclientSecret
ด้วย ID และ secret ของแอป Logto ของคุณ - ปรับแต่งฟังก์ชัน
profile
เพื่อแมปโปรไฟล์ผู้ใช้ไปยังอ็อบเจกต์ผู้ใช้ของ Next Auth โดยตัวอย่างจะแสดงการแมปเริ่มต้น - อย่าลืมตั้งค่า
id_token_signed_response_alg
เป็นES384
คุณสามารถดูรายละเอียดเพิ่มเติมได้ที่ เอกสาร Auth.js
กำหนดค่า sign-in redirect URI
ก่อนที่เราจะลงลึกในรายละเอียด นี่คือภาพรวมประสบการณ์ของผู้ใช้ปลายทาง กระบวนการลงชื่อเข้าใช้สามารถสรุปได้ดังนี้:
- แอปของคุณเรียกใช้งานเมธอดลงชื่อเข้าใช้
- ผู้ใช้จะถูกเปลี่ยนเส้นทางไปยังหน้าลงชื่อเข้าใช้ของ Logto สำหรับแอปเนทีฟ ระบบจะเปิดเบราว์เซอร์ของระบบ
- ผู้ใช้ลงชื่อเข้าใช้และถูกเปลี่ยนเส้นทางกลับไปยังแอปของคุณ (ตามที่กำหนดไว้ใน redirect URI)
เกี่ยวกับการลงชื่อเข้าใช้แบบเปลี่ยนเส้นทาง (redirect-based sign-in)
- กระบวนการยืนยันตัวตนนี้เป็นไปตามโปรโตคอล OpenID Connect (OIDC) และ Logto บังคับใช้มาตรการรักษาความปลอดภัยอย่างเข้มงวดเพื่อปกป้องการลงชื่อเข้าใช้ของผู้ใช้
- หากคุณมีหลายแอป คุณสามารถใช้ผู้ให้บริการข้อมูลระบุตัวตน (Logto) เดียวกันได้ เมื่อผู้ใช้ลงชื่อเข้าใช้แอปหนึ่งแล้ว Logto จะดำเนินการลงชื่อเข้าใช้โดยอัตโนมัติเมื่อผู้ใช้เข้าถึงแอปอื่น
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับเหตุผลและประโยชน์ของการลงชื่อเข้าใช้แบบเปลี่ยนเส้นทาง โปรดดูที่ อธิบายประสบการณ์การลงชื่อเข้าใช้ของ Logto
ในตัวอย่างโค้ดต่อไปนี้ เราถือว่าแอปของคุณกำลังทำงานอยู่ที่ http://localhost:3000/
ไปที่หน้ารายละเอียดแอปพลิเคชันของ Logto Console เพิ่ม Redirect URI http://localhost:3000/api/auth/callback/logto
แล้วคลิก "บันทึกการเปลี่ยนแปลง" (Save changes)

สร้างปุ่มลงชื่อเข้าใช้และออกจากระบบ
สร้างปุ่มลงชื่อเข้าใช้และออกจากระบบ
import { signIn } from '@/auth';
export default function SignIn() {
return (
<form
action={async () => {
'use server';
await signIn('logto');
}}
>
<button type="submit">Sign In</button>
</form>
);
}
import { signOut } from '@/auth';
export function SignOut() {
return (
<form
action={async () => {
'use server';
await signOut();
}}
>
<button type="submit">Sign Out</button>
</form>
);
}
แสดงปุ่มลงชื่อเข้าใช้และออกจากระบบในหน้าเพจ
import SignIn from './components/sign-in';
import SignOut from './components/sign-out';
import { auth } from '@/auth';
export default function Home() {
const session = await auth();
return <div>{session?.user ? <SignOut /> : <SignIn />}</div>;
}
ข้างต้นเป็นตัวอย่างง่าย ๆ คุณสามารถดูรายละเอียดเพิ่มเติมได้ที่ เอกสาร Auth.js
เช็กพอยต์
ขณะนี้คุณสามารถทดสอบแอปพลิเคชันของคุณเพื่อดูว่าการยืนยันตัวตนทำงานถูกต้องหรือไม่
ดึงข้อมูลผู้ใช้
แสดงข้อมูลผู้ใช้
เมื่อผู้ใช้ลงชื่อเข้าใช้แล้ว ค่าที่ได้จาก auth()
จะเป็นอ็อบเจกต์ที่มีข้อมูลของผู้ใช้ คุณสามารถแสดงข้อมูลนี้ในแอปของคุณได้ดังนี้:
import { auth } from '@/auth';
export default async function Home() {
const session = await auth();
return (
<main>
{session?.user && (
<div>
<h2>การอ้างสิทธิ์ (Claims):</h2>
<table>
<thead>
<tr>
<th>ชื่อ</th>
<th>ค่า</th>
</tr>
</thead>
<tbody>
{Object.entries(session.user).map(([key, value]) => (
<tr key={key}>
<td>{key}</td>
<td>{String(value)}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</main>
);
}
ขอการอ้างสิทธิ์เพิ่มเติม
คุณอาจพบว่าข้อมูลผู้ใช้บางอย่างหายไปในอ็อบเจกต์ที่ส่งคืนจาก auth()
สาเหตุเนื่องจาก OAuth 2.0 และ OpenID Connect (OIDC) ถูกออกแบบมาให้สอดคล้องกับหลักการสิทธิ์น้อยที่สุด (principle of least privilege; PoLP) และ Logto ถูกสร้างขึ้นบนมาตรฐานเหล่านี้
โดยปกติแล้ว จะมีการส่งคืนการอ้างสิทธิ์ (claim) แบบจำกัด หากคุณต้องการข้อมูลเพิ่มเติม คุณสามารถร้องขอขอบเขต (scope) เพิ่มเติมเพื่อเข้าถึงการอ้างสิทธิ์ (claim) ที่มากขึ้นได้
"การอ้างสิทธิ์ (Claim)" คือการยืนยันข้อมูลบางอย่างเกี่ยวกับผู้ถูกอ้างถึง (subject); "ขอบเขต (Scope)" คือกลุ่มของการอ้างสิทธิ์ (claim) ในกรณีนี้ การอ้างสิทธิ์ (claim) คือข้อมูลบางอย่างเกี่ยวกับผู้ใช้
ตัวอย่างที่ไม่เป็นทางการของความสัมพันธ์ระหว่างขอบเขต (scope) กับการอ้างสิทธิ์ (claim) มีดังนี้:
การอ้างสิทธิ์ (claim) "sub" หมายถึง "ผู้ถูกอ้างถึง (subject)" ซึ่งคือตัวระบุที่ไม่ซ้ำของผู้ใช้ (เช่น user ID)
Logto SDK จะร้องขอขอบเขต (scope) สามรายการเสมอ ได้แก่ openid
, profile
และ offline_access
หากต้องการขอขอบเขต (scopes) เพิ่มเติม คุณสามารถกำหนดค่า params ของ Logto provider ได้ดังนี้:
import NextAuth from 'next-auth';
import Logto from 'next-auth/providers/logto';
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
Logto({
// ...
authorization: {
params: {
scope: 'openid offline_access profile email',
},
},
// ...
}),
],
});
การอ้างสิทธิ์ที่ต้องใช้การร้องขอผ่านเครือข่าย
เพื่อป้องกันไม่ให้โทเค็น ID มีขนาดใหญ่เกินไป การอ้างสิทธิ์บางอย่างจำเป็นต้องร้องขอผ่านเครือข่าย เช่น การอ้างสิทธิ์ custom_data
จะไม่ถูกรวมอยู่ในอ็อบเจกต์ผู้ใช้ แม้ว่าจะร้องขอไว้ใน scopes ก็ตาม หากต้องการเข้าถึงการอ้างสิทธิ์เหล่านี้ คุณต้องร้องขอข้อมูลผู้ใช้ผ่านเครือข่าย
รับโทเค็นการเข้าถึง (Access token)
อัปเดต config ของ NextAuth
เพื่อให้สามารถรับโทเค็นการเข้าถึงได้:
export const { handlers, signIn, signOut, auth } = NextAuth({
// ...
callbacks: {
async jwt({ token, account }) {
if (account) {
token.accessToken = account.access_token;
}
return token;
},
async session({ session, token }) {
// ใส่โทเค็นการเข้าถึงลงในอ็อบเจกต์ session
session.accessToken = token.accessToken;
return session;
},
},
});
ดึงข้อมูลผู้ใช้
ตอนนี้เข้าถึง OIDC user info endpoint ด้วยโทเค็นการเข้าถึง:
// ...
export default async function Home() {
const session = await auth();
// เปลี่ยน URL เป็น Logto endpoint ของคุณ ควรลงท้ายด้วย `/oidc/me`
const response = await fetch('https://xxx.logto.app/oidc/me', {
headers: {
Authorization: `Bearer ${session?.accessToken}`,
},
});
const user = await response.json();
console.log(user);
// ...
}
ตัวอย่างข้างต้นเป็นตัวอย่างง่าย ๆ อย่าลืมจัดการกรณีเกิดข้อผิดพลาดด้วย
การรีเฟรชโทเค็นการเข้าถึง (Access token refresh)
โทเค็นการเข้าถึงจะมีอายุสั้น โดยปกติ Next.js จะดึงโทเค็นใหม่เมื่อสร้าง session เท่านั้น หากต้องการทำให้รีเฟรชโทเค็นการเข้าถึงอัตโนมัติ ดูที่ Refresh token rotation
ขอบเขต (Scopes) และการอ้างสิทธิ์ (Claims)
Logto ใช้มาตรฐาน ขอบเขต (scopes) และ การอ้างสิทธิ์ (claims) ของ OIDC เพื่อกำหนดขอบเขตและการอ้างสิทธิ์สำหรับดึงข้อมูลผู้ใช้จากโทเค็น ID (ID token) และ OIDC userinfo endpoint ทั้ง "ขอบเขต (scope)" และ "การอ้างสิทธิ์ (claim)" เป็นคำศัพท์จากข้อกำหนดของ OAuth 2.0 และ OpenID Connect (OIDC)
ต่อไปนี้คือรายการขอบเขต (Scopes) ที่รองรับและการอ้างสิทธิ์ (Claims) ที่เกี่ยวข้อง:
openid
ชื่อการอ้างสิทธิ์ | ประเภท | คำอธิบาย | ต้องใช้ userinfo หรือไม่? |
---|---|---|---|
sub | string | ตัวระบุที่ไม่ซ้ำของผู้ใช้ | ไม่ |
profile
ชื่อการอ้างสิทธิ์ | ประเภท | คำอธิบาย | ต้องใช้ userinfo หรือไม่? |
---|---|---|---|
name | string | ชื่อเต็มของผู้ใช้ | ไม่ |
username | string | ชื่อผู้ใช้ของผู้ใช้ | ไม่ |
picture | string | URL ของรูปโปรไฟล์ของผู้ใช้ปลายทาง URL นี้ ต้อง อ้างอิงถึงไฟล์รูปภาพ (เช่น ไฟล์ PNG, JPEG หรือ GIF) ไม่ใช่หน้าเว็บที่มีรูปภาพ โปรดทราบว่า URL นี้ ควร อ้างอิงถึงรูปโปรไฟล์ของผู้ใช้ปลายทางที่เหมาะสมสำหรับการแสดงผลเมื่ออธิบายผู้ใช้ปลายทาง ไม่ใช่รูปภาพใด ๆ ที่ผู้ใช้ถ่ายเอง | ไม่ |
created_at | number | เวลาที่สร้างผู้ใช้ปลายทาง เวลานี้แสดงเป็นจำนวนมิลลิวินาทีตั้งแต่ Unix epoch (1970-01-01T00:00:00Z) | ไม่ |
updated_at | number | เวลาที่ข้อมูลของผู้ใช้ปลายทางถูกอัปเดตล่าสุด เวลานี้แสดงเป็นจำนวนมิลลิวินาทีตั้งแต่ Unix epoch (1970-01-01T00:00:00Z) | ไม่ |
การอ้างสิทธิ์มาตรฐาน อื่น ๆ เช่น family_name
, given_name
, middle_name
, nickname
, preferred_username
, profile
, website
, gender
, birthdate
, zoneinfo
, และ locale
จะถูกรวมอยู่ในขอบเขต profile
ด้วยโดยไม่ต้องร้องขอ endpoint userinfo ความแตกต่างเมื่อเทียบกับการอ้างสิทธิ์ข้างต้นคือ การอ้างสิทธิ์เหล่านี้จะถูกส่งกลับมาเฉพาะเมื่อค่าของมันไม่ว่างเปล่า ในขณะที่การอ้างสิทธิ์ข้างต้นจะส่งกลับ null
หากค่าเป็นค่าว่าง
ต่างจากการอ้างสิทธิ์มาตรฐาน การอ้างสิทธิ์ created_at
และ updated_at
ใช้หน่วยเป็นมิลลิวินาทีแทนที่จะเป็นวินาที
email
ชื่อการอ้างสิทธิ์ | ประเภท | คำอธิบาย | ต้องใช้ userinfo หรือไม่? |
---|---|---|---|
string | อีเมลของผู้ใช้ | ไม่ | |
email_verified | boolean | อีเมลได้รับการยืนยันแล้วหรือไม่ | ไม่ |
phone
ชื่อการอ้างสิทธิ์ | ประเภท | คำอธิบาย | ต้องใช้ userinfo หรือไม่? |
---|---|---|---|
phone_number | string | หมายเลขโทรศัพท์ของผู้ใช้ | ไม่ |
phone_number_verified | boolean | หมายเลขโทรศัพท์ได้รับการยืนยันแล้วหรือไม่ | ไม่ |
address
โปรดดูรายละเอียดของการอ้างสิทธิ์ที่อยู่ได้ที่ OpenID Connect Core 1.0
custom_data
ชื่อการอ้างสิทธิ์ | ประเภท | คำอธิบาย | ต้องใช้ userinfo หรือไม่? |
---|---|---|---|
custom_data | object | ข้อมูลกำหนดเองของผู้ใช้ | ใช่ |
identities
ชื่อการอ้างสิทธิ์ | ประเภท | คำอธิบาย | ต้องใช้ userinfo หรือไม่? |
---|---|---|---|
identities | object | ข้อมูลตัวตนที่เชื่อมโยงของผู้ใช้ | ใช่ |
sso_identities | array | ข้อมูล SSO ที่เชื่อมโยงของผู้ใช้ | ใช่ |
roles
ชื่อการอ้างสิทธิ์ | ประเภท | คำอธิบาย | ต้องใช้ userinfo หรือไม่? |
---|---|---|---|
roles | string[] | บทบาทของผู้ใช้ | ไม่ |
urn:logto:scope:organizations
ชื่อการอ้างสิทธิ์ | ประเภท | คำอธิบาย | ต้องใช้ userinfo หรือไม่? |
---|---|---|---|
organizations | string[] | รหัสองค์กรที่ผู้ใช้สังกัด | ไม่ |
organization_data | object[] | ข้อมูลขององค์กรที่ผู้ใช้สังกัด | ใช่ |
urn:logto:scope:organization_roles
ชื่อการอ้างสิทธิ์ | ประเภท | คำอธิบาย | ต้องใช้ userinfo หรือไม่? |
---|---|---|---|
organization_roles | string[] | บทบาทของผู้ใช้ในแต่ละองค์กรในรูปแบบ <organization_id>:<role_name> | ไม่ |
เพื่อประสิทธิภาพและขนาดข้อมูล หาก "ต้องใช้ userinfo หรือไม่?" เป็น "ใช่" หมายความว่าการอ้างสิทธิ์นั้นจะไม่ปรากฏในโทเค็น ID แต่จะถูกส่งกลับใน response ของ userinfo endpoint
ทรัพยากร API (API resources)
เราแนะนำให้อ่าน 🔐 การควบคุมการเข้าถึงตามบทบาท (RBAC) ก่อน เพื่อทำความเข้าใจแนวคิดพื้นฐานของ RBAC ใน Logto และวิธีตั้งค่าทรัพยากร API อย่างถูกต้อง
ตั้งค่าผู้ให้บริการ Logto
เมื่อคุณตั้งค่า ทรัพยากร API (API resources) เรียบร้อยแล้ว คุณสามารถเพิ่มทรัพยากรเหล่านี้ขณะกำหนดค่า Logto ในแอปของคุณได้:
import NextAuth from 'next-auth';
import Logto from 'next-auth/providers/logto';
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
Logto({
// ...
authorization: {
params: {
scope: 'openid offline_access profile email',
resource: 'https://shopping.your-app.com/api',
},
},
// ...
}),
],
});
แต่ละ ทรัพยากร API (API resource) จะมี สิทธิ์ (scopes) ของตัวเอง
ตัวอย่างเช่น ทรัพยากร https://shopping.your-app.com/api
มีสิทธิ์ shopping:read
และ shopping:write
และทรัพยากร https://store.your-app.com/api
มีสิทธิ์ store:read
และ store:write
หากต้องการร้องขอสิทธิ์เหล่านี้ คุณสามารถเพิ่มขณะกำหนดค่า Logto ในแอปของคุณได้:
import NextAuth from 'next-auth';
import Logto from 'next-auth/providers/logto';
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
Logto({
// ...
authorization: {
params: {
scope: 'openid offline_access profile email shopping:read shopping:write',
resource: 'https://shopping.your-app.com/api',
},
},
// ...
}),
],
});
คุณอาจสังเกตได้ว่า ขอบเขต (scopes) ถูกกำหนดแยกจาก ทรัพยากร API (API resources) นี่เป็นเพราะ Resource Indicators for OAuth 2.0 ระบุว่า ขอบเขตสุดท้ายสำหรับคำขอจะเป็นผลคูณคาร์ทีเซียนของขอบเขตทั้งหมดในบริการเป้าหมายทั้งหมด
ดังนั้น ในกรณีข้างต้น ขอบเขต (scopes) สามารถทำให้เรียบง่ายขึ้นจากการกำหนดใน Logto โดยทั้งสอง ทรัพยากร API (API resources) สามารถมีขอบเขต read
และ write
ได้โดยไม่ต้องมีคำนำหน้า จากนั้น ในการตั้งค่า Logto:
import NextAuth from 'next-auth';
import Logto from 'next-auth/providers/logto';
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
Logto({
// ...
authorization: {
params: {
scope: 'openid offline_access profile read write',
resource: 'https://shopping.your-app.com/api',
},
},
// ...
}),
],
});
สำหรับแต่ละ ทรัพยากร API (API resource) จะร้องขอทั้งขอบเขต read
และ write
คุณสามารถร้องขอขอบเขต (scopes) ที่ไม่ได้กำหนดไว้ใน ทรัพยากร API (API resources) ได้ เช่น คุณสามารถร้องขอขอบเขต email
ได้ แม้ว่า ทรัพยากร API (API resources) จะไม่มีขอบเขต email
ให้ ขอบเขตที่ไม่มีจะถูกละเว้นอย่างปลอดภัย
หลังจากลงชื่อเข้าใช้สำเร็จ Logto จะออกขอบเขตที่เหมาะสมให้กับ ทรัพยากร API (API resources) ตามบทบาทของผู้ใช้
ดึงโทเค็นการเข้าถึงสำหรับทรัพยากร API
Auth.js จะดึงโทเค็นการเข้าถึง (Access token) เพียงครั้งเดียวโดยไม่มีพารามิเตอร์ resource เราจำเป็นต้องเขียนกระบวนการดึงโทเค็นการเข้าถึงด้วยตนเอง
รับโทเค็นรีเฟรช (Refresh token)
อัปเดตการตั้งค่า Logto provider โดยเพิ่มพารามิเตอร์ "prompt" และตั้งค่าเป็น consent
และตรวจสอบให้แน่ใจว่ามีขอบเขต offline_access
รวมอยู่ด้วย:
import NextAuth from 'next-auth';
export const { handlers, signIn, signOut, auth } = NextAuth({
// ...
authorization: {
params: {
prompt: 'consent',
scope: 'openid offline_access shopping:read shopping:write',
resource: 'https://shopping.your-app.com/api',
// ...
},
},
// ...
});
จากนั้นเพิ่ม callback เพื่อบันทึก refresh_token
ลงใน session:
export const { handlers, signIn, signOut, auth } = NextAuth({
// ...
callbacks: {
async jwt({ token, account }) {
if (account) {
// ...
token.refreshToken = account.refresh_token;
}
return token;
},
async session({ session, token }) {
// ...
session.refreshToken = token.refreshToken;
return session;
},
},
});
ดึงโทเค็นการเข้าถึง (Fetch access token)
เมื่อมี refresh_token
แล้ว เราสามารถดึงโทเค็นการเข้าถึงจาก OIDC token endpoint ของ Logto ได้
// ...
export default async function Home() {
const session = await auth();
if (session?.refreshToken) {
// แทนที่ app ID และ secret ด้วยของคุณเอง สามารถดูได้ในส่วน "Integration"
const basicAuth = Buffer.from('<logto-app-id>:<logto-app-secret>').toString('base64');
// แทนที่ URL ด้วย endpoint Logto ของคุณ ควรลงท้ายด้วย `/oidc/token`
const response = await fetch('https://xxx.logto.app/oidc/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: `Basic ${basicAuth}`,
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: session.refreshToken,
resource: 'https://shopping.your-app.com/api',
}).toString(),
});
const data = await response.json();
console.log(data.access_token);
}
// ...
}
ดึงโทเค็นองค์กร
หากคุณยังไม่คุ้นเคยกับ องค์กร (Organization) โปรดอ่าน 🏢 องค์กร (หลายผู้เช่า; Multi-tenancy) เพื่อเริ่มต้น
คุณต้องเพิ่ม urn:logto:scope:organizations
ขอบเขต (scope) ขณะตั้งค่า Logto client:
import NextAuth from 'next-auth';
import Logto from 'next-auth/providers/logto';
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
Logto({
// ...
authorization: {
params: {
scope: 'openid offline_access urn:logto:scope:organizations',
},
},
// ...
}),
],
});
เมื่อผู้ใช้ลงชื่อเข้าใช้แล้ว คุณสามารถดึงโทเค็นองค์กร (organization token) สำหรับผู้ใช้ได้:
คล้ายกับโทเค็นการเข้าถึง (Access token) สำหรับทรัพยากร API เราสามารถใช้โทเค็นรีเฟรช (Refresh token) เพื่อดึงโทเค็นการเข้าถึงองค์กร (Organization access token) ได้
// ...
export default async function Home() {
const session = await auth();
if (session?.refreshToken) {
// แทนที่ app ID และ secret ด้วยของคุณเอง สามารถตรวจสอบได้ในส่วน "Integration"
const basicAuth = Buffer.from('<logto-app-id>:<logto-app-secret>').toString('base64');
// แทนที่ URL ด้วย Logto endpoint ของคุณ ควรลงท้ายด้วย `/oidc/token`
const response = await fetch('https://xxx.logto.app/oidc/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: `Basic ${basicAuth}`,
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: session.refreshToken,
resource: 'urn:logto:scope:organizations',
organization_id: 'organization-id',
}).toString(),
});
const data = await response.json();
console.log(data.access_token);
}
// ...
}
อ่านเพิ่มเติม
กระบวนการสำหรับผู้ใช้ปลายทาง: กระบวนการยืนยันตัวตน, กระบวนการบัญชี, และกระบวนการองค์กร ตั้งค่าตัวเชื่อมต่อ การอนุญาต (Authorization)การย้ายการผสาน Logto จาก NextAuth.js v4 ไปยัง v5