ข้ามไปยังเนื้อหาหลัก

เพิ่มการยืนยันตัวตนให้กับแอป Passport.js ของคุณ (Add authentication to your Passport.js application)

คู่มือนี้จะแสดงวิธีผสาน Logto เข้ากับแอปพลิเคชันของคุณโดยใช้ Passport.js และกลยุทธ์ OIDC

เคล็ดลับ:
  • ในคู่มือนี้ เราถือว่าคุณได้ตั้งค่า Express พร้อม session ในโปรเจกต์ของคุณแล้ว หากยังไม่ได้ตั้งค่า โปรดดูที่ เว็บไซต์ Express.js เพื่อเริ่มต้น

ข้อกำหนดเบื้องต้น

การติดตั้ง

ติดตั้ง Logto SDK ผ่านตัวจัดการแพ็กเกจที่คุณชื่นชอบ:

npm i passport passport-openidconnect

การผสานระบบ

เริ่มต้นใช้งาน Passport.js ด้วยกลยุทธ์ OIDC

passport.ts
import passport from 'passport';
import OpenIDConnectStrategy, { type Profile, type VerifyCallback } from 'passport-openidconnect';

const endpoint = '<your-logto-endpoint>';
const appId = '<your-application-id>';
const appSecret = '<your-application-secret>';

export default function initPassport() {
passport.use(
new OpenIDConnectStrategy(
{
issuer: `${endpoint}/oidc`,
authorizationURL: `${endpoint}/oidc/auth`,
tokenURL: `${endpoint}/oidc/token`,
userInfoURL: `${endpoint}/oidc/me`,
clientID: appId,
clientSecret: appSecret,
callbackURL: '/callback',
scope: ['profile', 'offline_access'],
},
(issuer: string, profile: Profile, callback: VerifyCallback) => {
callback(null, profile);
}
)
);

passport.serializeUser((user, callback) => {
callback(null, user);
});

passport.deserializeUser(function (user, callback) {
callback(null, user as Express.User);
});
}

โค้ดนี้เป็นการเริ่มต้นใช้งาน Passport ด้วย OpenIDConnectStrategy โดยกำหนดวิธี serialize และ deserialize สำหรับการสาธิต

ตรวจสอบให้แน่ใจว่าได้เริ่มต้นและแนบ middleware ของ Passport ในแอปพลิเคชันของคุณ:

your-app-entry.ts
import initPassport from './passport';

// ... โค้ดอื่น ๆ
initPassport();
// ... โค้ดอื่น ๆ
app.use(passport.authenticate('session'));
// ... โค้ดอื่น ๆ

กำหนดค่า redirect URI

ก่อนที่เราจะลงลึกในรายละเอียด นี่คือภาพรวมประสบการณ์ของผู้ใช้ปลายทาง กระบวนการลงชื่อเข้าใช้สามารถสรุปได้ดังนี้:

  1. แอปของคุณเรียกใช้งานเมธอดลงชื่อเข้าใช้
  2. ผู้ใช้จะถูกเปลี่ยนเส้นทางไปยังหน้าลงชื่อเข้าใช้ของ Logto สำหรับแอปเนทีฟ ระบบจะเปิดเบราว์เซอร์ของระบบ
  3. ผู้ใช้ลงชื่อเข้าใช้และถูกเปลี่ยนเส้นทางกลับไปยังแอปของคุณ (ตามที่กำหนดไว้ใน redirect URI)

เกี่ยวกับการลงชื่อเข้าใช้แบบเปลี่ยนเส้นทาง (redirect-based sign-in)

  1. กระบวนการยืนยันตัวตนนี้เป็นไปตามโปรโตคอล OpenID Connect (OIDC) และ Logto บังคับใช้มาตรการรักษาความปลอดภัยอย่างเข้มงวดเพื่อปกป้องการลงชื่อเข้าใช้ของผู้ใช้
  2. หากคุณมีหลายแอป คุณสามารถใช้ผู้ให้บริการข้อมูลระบุตัวตน (Logto) เดียวกันได้ เมื่อผู้ใช้ลงชื่อเข้าใช้แอปหนึ่งแล้ว Logto จะดำเนินการลงชื่อเข้าใช้โดยอัตโนมัติเมื่อผู้ใช้เข้าถึงแอปอื่น

หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับเหตุผลและประโยชน์ของการลงชื่อเข้าใช้แบบเปลี่ยนเส้นทาง โปรดดูที่ อธิบายประสบการณ์การลงชื่อเข้าใช้ของ Logto


บันทึก:

ในตัวอย่างโค้ดต่อไปนี้ เราถือว่าแอปของคุณกำลังทำงานอยู่ที่ http://localhost:3000/

กำหนดค่า Redirect URI

ไปที่หน้ารายละเอียดแอปพลิเคชันใน Logto Console เพิ่ม redirect URI http://localhost:3000/callback

Redirect URI in Logto Console

เช่นเดียวกับการลงชื่อเข้าใช้ ผู้ใช้ควรถูกเปลี่ยนเส้นทางไปที่ Logto เพื่อออกจากเซสชันที่ใช้ร่วมกัน เมื่อเสร็จสิ้นแล้ว ควรเปลี่ยนเส้นทางผู้ใช้กลับไปยังเว็บไซต์ของคุณ ตัวอย่างเช่น เพิ่ม http://localhost:3000/ ในส่วน post sign-out redirect URI

จากนั้นคลิก "Save" เพื่อบันทึกการเปลี่ยนแปลง

สร้างเส้นทางสำหรับการลงชื่อเข้าใช้และออกจากระบบ

ต่อไปเราจะสร้าง route เฉพาะสำหรับกระบวนการยืนยันตัวตน:

your-app-entry.ts
app.get('/sign-in', passport.authenticate('openidconnect'));
app.get(
'/callback',
passport.authenticate('openidconnect', {
successReturnToOrRedirect: '/',
})
);
app.get('/sign-out', (request, response, next) => {
request.logout((error) => {
if (error) {
next(error);
return;
}
response.redirect(`${endpoint}/oidc/session/end?client_id=${appId}`);
});
});

จากนั้นเพิ่มไปยังหน้าแรก

your-app-entry.ts
app.get('/', (request: Request, response) => {
const { user } = request;
response.setHeader('content-type', 'text/html');

if (user) {
response.end(
`<h1>Hello Logto</h1><p>Signed in as ${JSON.stringify(
user
)}, <a href="/sign-out">Sign Out</a></p>`
);
} else {
response.end(`<h1>Hello Logto</h1><p><a href="/sign-in">Sign In</a></p>`);
}
});

จุดตรวจสอบ: ทดสอบแอปพลิเคชันของคุณ

ตอนนี้คุณสามารถทดสอบแอปพลิเคชันของคุณได้แล้ว:

  1. รันแอปพลิเคชันของคุณ คุณจะเห็นปุ่มลงชื่อเข้าใช้
  2. คลิกปุ่มลงชื่อเข้าใช้ SDK จะเริ่มกระบวนการลงชื่อเข้าใช้และเปลี่ยนเส้นทางคุณไปยังหน้าลงชื่อเข้าใช้ของ Logto
  3. หลังจากที่คุณลงชื่อเข้าใช้แล้ว คุณจะถูกเปลี่ยนเส้นทางกลับไปยังแอปพลิเคชันของคุณและเห็นปุ่มลงชื่อออก
  4. คลิกปุ่มลงชื่อออกเพื่อเคลียร์ที่เก็บโทเค็นและออกจากระบบ

ขอบเขต (Scopes) และการอ้างสิทธิ์ (Claims)

Logto ใช้แนวทาง ขอบเขต (Scope) และ การอ้างสิทธิ์ (Claim) ของ OIDC เพื่อกำหนดขอบเขตและการอ้างสิทธิ์สำหรับดึงข้อมูลผู้ใช้จากโทเค็น ID (ID token) และ OIDC จุดปลาย userinfo ทั้ง "ขอบเขต (Scope)" และ "การอ้างสิทธิ์ (Claim)" เป็นคำศัพท์จากข้อกำหนดของ OAuth 2.0 และ OpenID Connect (OIDC)

สำหรับการอ้างสิทธิ์ OIDC มาตรฐาน การรวมอยู่ในโทเค็น ID จะถูกกำหนดอย่างเคร่งครัดโดยขอบเขตที่ร้องขอ การอ้างสิทธิ์เพิ่มเติม (เช่น custom_data และ organizations) สามารถตั้งค่าเพิ่มเติมให้ปรากฏในโทเค็น ID ได้ผ่าน การตั้งค่า Custom ID token

โดยสรุป เมื่อคุณร้องขอขอบเขต (scope) ใด คุณจะได้รับการอ้างสิทธิ์ (claim) ที่เกี่ยวข้องในข้อมูลผู้ใช้ เช่น หากคุณร้องขอขอบเขต `email` คุณจะได้รับข้อมูล `email` และ `email_verified` ของผู้ใช้

โดยค่าเริ่มต้น Logto SDK จะร้องขอขอบเขตสามรายการเสมอ: `openid`, `profile` และ `offline_access` และไม่สามารถลบขอบเขตเริ่มต้นเหล่านี้ได้ แต่คุณสามารถเพิ่มขอบเขตเพิ่มเติมขณะตั้งค่า Logto ได้:

export default function initPassport() {
passport.use(
new OpenIDConnectStrategy(
{
// ... ตัวเลือกอื่น ๆ
clientID: appId,
clientSecret: appSecret,
callbackURL: '/callback',
scope: ['openid', 'offline_access', 'profile', 'email'],
}
// ... ตัวเลือกอื่น ๆ
)
);
// ... ตัวเลือกอื่น ๆ
}

ต่อไปนี้คือรายการขอบเขต (Scopes) ที่รองรับและการอ้างสิทธิ์ (Claims) ที่เกี่ยวข้อง:

ขอบเขต OIDC มาตรฐาน

openid (ค่าเริ่มต้น)

ชื่อการอ้างสิทธิ์ประเภทคำอธิบาย
substringตัวระบุที่ไม่ซ้ำของผู้ใช้

profile (ค่าเริ่มต้น)

ชื่อการอ้างสิทธิ์ประเภทคำอธิบาย
namestringชื่อเต็มของผู้ใช้
usernamestringชื่อผู้ใช้ของผู้ใช้
picturestringURL ของรูปโปรไฟล์ผู้ใช้ปลายทาง (End-User) URL นี้ต้องอ้างถึงไฟล์รูปภาพ (เช่น PNG, JPEG, หรือ GIF) ไม่ใช่หน้าเว็บที่มีรูปภาพ โปรดทราบว่า URL นี้ควรอ้างอิงถึงรูปโปรไฟล์ของผู้ใช้ปลายทางโดยเฉพาะ เหมาะสำหรับแสดงเมื่ออธิบายผู้ใช้ปลายทาง ไม่ใช่รูปภาพใด ๆ ที่ผู้ใช้ถ่ายมาโดยพลการ
created_atnumberเวลาที่สร้างผู้ใช้ปลายทาง เวลานี้แสดงเป็นจำนวนมิลลิวินาทีตั้งแต่ Unix epoch (1970-01-01T00:00:00Z)
updated_atnumberเวลาที่ข้อมูลของผู้ใช้ปลายทางถูกอัปเดตล่าสุด เวลานี้แสดงเป็นจำนวนมิลลิวินาทีตั้งแต่ 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

ชื่อการอ้างสิทธิ์ประเภทคำอธิบาย
emailstringอีเมลของผู้ใช้
email_verifiedbooleanอีเมลได้รับการยืนยันแล้วหรือไม่

phone

ชื่อการอ้างสิทธิ์ประเภทคำอธิบาย
phone_numberstringเบอร์โทรศัพท์ของผู้ใช้
phone_number_verifiedbooleanเบอร์โทรศัพท์ได้รับการยืนยันแล้วหรือไม่

address

โปรดดูรายละเอียดของการอ้างสิทธิ์ที่อยู่ได้ที่ OpenID Connect Core 1.0

ข้อมูล:

ขอบเขตที่มีเครื่องหมาย (ค่าเริ่มต้น) จะถูกร้องขอเสมอโดย Logto SDK การอ้างสิทธิ์ภายใต้ขอบเขต OIDC มาตรฐานจะถูกรวมอยู่ในโทเค็น ID เสมอเมื่อมีการร้องขอขอบเขตที่เกี่ยวข้อง — ไม่สามารถปิดได้

ขอบเขตเพิ่มเติม

ขอบเขตต่อไปนี้เป็นขอบเขตที่ Logto ขยายขึ้นและจะคืนค่าการอ้างสิทธิ์ผ่าน userinfo endpoint การอ้างสิทธิ์เหล่านี้ยังสามารถตั้งค่าให้ถูกรวมอยู่ในโทเค็น ID ได้โดยตรงผ่าน Console > Custom JWT ดู Custom ID token สำหรับรายละเอียดเพิ่มเติม

custom_data

ชื่อการอ้างสิทธิ์ประเภทคำอธิบายรวมในโทเค็น ID โดยค่าเริ่มต้น
custom_dataobjectข้อมูลกำหนดเองของผู้ใช้

identities

ชื่อการอ้างสิทธิ์ประเภทคำอธิบายรวมในโทเค็น ID โดยค่าเริ่มต้น
identitiesobjectข้อมูลตัวตนที่เชื่อมโยงของผู้ใช้
sso_identitiesarrayข้อมูล SSO ที่เชื่อมโยงของผู้ใช้

roles

ชื่อการอ้างสิทธิ์ประเภทคำอธิบายรวมในโทเค็น ID โดยค่าเริ่มต้น
rolesstring[]บทบาท (Role) ของผู้ใช้

urn:logto:scope:organizations

ชื่อการอ้างสิทธิ์ประเภทคำอธิบายรวมในโทเค็น ID โดยค่าเริ่มต้น
organizationsstring[]รหัสองค์กรที่ผู้ใช้สังกัด
organization_dataobject[]ข้อมูลองค์กรที่ผู้ใช้สังกัด
บันทึก:

การอ้างสิทธิ์ขององค์กรเหล่านี้สามารถดึงได้ผ่าน userinfo endpoint เมื่อใช้ โทเค็นทึบ (Opaque token) อย่างไรก็ตาม โทเค็นทึบไม่สามารถใช้เป็นโทเค็นองค์กรสำหรับเข้าถึงทรัพยากรเฉพาะองค์กร ดู โทเค็นทึบและองค์กร สำหรับรายละเอียดเพิ่มเติม

urn:logto:scope:organization_roles

ชื่อการอ้างสิทธิ์ประเภทคำอธิบายรวมในโทเค็น ID โดยค่าเริ่มต้น
organization_rolesstring[]บทบาทขององค์กรที่ผู้ใช้สังกัดในรูปแบบ <organization_id>:<role_name>

อ่านเพิ่มเติม

กระบวนการสำหรับผู้ใช้ปลายทาง: กระบวนการยืนยันตัวตน, กระบวนการบัญชี, และกระบวนการองค์กร ตั้งค่าตัวเชื่อมต่อ การอนุญาต (Authorization)