จาก custom-made ถึง plug-and-play forms ของ authentication Ruby developers มีมากมายให้เลือกในวันนี้ แม้ว่าเช่นที่คุณรู้ การสร้างโซลูชันของตัวเองอาจมีค่าใช้จ่ายสูงและอันตราย หาก Devise เป็น de facto standard สำหรับทีมส่วนใหญ่ ตัวเลือกทางเลือกอาจทำให้ชีวิตของส่วนใหญ่ง่ายขึ้น
บทความนี้จะครอบคลุมการตั้งค่าและการใช้งาน Auth0 ในแอปพลิเคชัน Ruby on Rails รวมถึงทุกสิ่งที่คุณต้องการเพื่อเริ่มต้นอย่างถูกต้อง จากการจัดการ roles ไปจนถึงการพึ่งพา multiple providers เพื่อ authenticate users
เริ่มต้นใช้งาน
นี่คือสิ่งที่เราต้องการเพื่อเริ่มต้น:
- AppSignal account
- Ruby on Rails application (version 7.x onwards)
Auth0 เป็น third-party authentication service ที่มี free tier ให้คุณจัดการได้ถึง 7,000 users นั่นเพียงพอที่จะเริ่มต้น และ pricing ของมัน reasonable หากคุณต้องการ advanced features มากขึ้น
การกำหนดค่า Ruby App ของเราใน Auth0
เนื่องจากแอปพลิเคชันของคุณจะพึ่งพา Auth0 เพื่อ authenticate users ผ่าน redirects และ calls เราต้องแน่ใจว่ามันอยู่ในความปลอดภัย
ในบัญชี Auth0 ของเรา มาสร้าง application ภายใน tenant คุณสามารถสร้าง multiple tenants ในบัญชีเพื่อแยก:
- Domain names
- Environments ที่ต่างกัน (development, production, ฯลฯ)
- ประเทศหรือภูมิภาคที่ข้อมูลจะถูกจัดเก็บ
เมื่อคุณสร้าง tenant แรกแล้ว คุณสามารถสร้าง application ได้ นั่นคือที่เราจะเริ่ม
ไปที่แท็บ "Settings" ใน application panel คุณต้อง copy และ paste ต่อไปนี้และบันทึกไว้ในที่ปลอดภัย:
- Domain name:
app-name.[eu,us,..].auth0.com - Client's ID
- Client's Secret
เราต้องกรอก Application URIs ต่อไปนี้ด้วย เราจะใช้ค่าเหล่านี้สำหรับ local development setup:
- Allowed Callback URLs:
https://localhost:3000/auth/auth0/callback(URL ที่ Auth0 จะ redirect ไปหลัง authentication) - Allowed Logout URLs:
https://localhost:3000(URL ที่ Auth0 จะ redirect ไปหลังจากใครบางคน logout)
มาเริ่มกำหนดค่าแอปของเรา
การเตรียม Ruby on Rails Application ของเรา
คุณสามารถเริ่มต้นด้วย vanilla Ruby on Rails application โดยใช้คำสั่ง rails new
มาสร้างตัวหนึ่งที่พึ่งพา SQLite3 สำหรับ database และ Tailwind สำหรับ CSS library ข้ามการติดตั้ง mini-test และตั้งชื่อแอปพลิเคชันว่า "Auth0 article":
สร้าง User model ด้วยแค่ attributes น้อยๆ:
สิ่งนี้สร้าง base ที่เรียบง่ายแต่มีประสิทธิภาพสำหรับแอปพลิเคชันของเรา
การเพิ่ม Auth0 Gem ลงในแอป
คุณจะต้องการ omniauth-auth0 และ omniauth-rails_csrf_protection เพื่อใช้ Auth0 ในแอปพลิเคชัน Ruby on Rails ของคุณ
การกำหนดค่า Auth0
เราต้องสร้าง configuration file เล็กๆ (config/auth0.yml) เพื่อจัดเก็บ credentials ใน development environment
เรายังสามารถพึ่งพา environment variables ได้ที่นี่ด้วยการใช้ erb บางอย่าง:
โดยปبعòn การพึ่งพา Rails credentials ทำให้สิ่งต่างๆ อยู่ในสภาพ up-to-date มากกว่า
ไฟล์นี้จะถูกใช้ใน Auth0 initializer (config/initializers/auth0.rb) ซึ่งเราจะสร้างตอนนี้:
ตามที่คุณเห็นที่นี่ เราใช้ Rails.application.config_for เพื่อโหลด content ของ YAML file เป็น hash ที่สะดวก เราสามารถแทนที่สิ่งนี้ด้วย secret handling library ใดๆ รวมถึง Rails encrypted credentials storage
โปรดสังเกตสิ่งต่อไปนี้:
- Provider name (
:auth0) - สามรายการจาก YAML file อ่านและใช้ผ่าน hash
AUTH0_CONFIG callback_pathkey และ value ตรงกับที่เรากำหนดใน Auth0 interfaceauthorize_paramsและscopekey ภายในมัน เราจะกลับมาที่นี่ภายหลัง
เราต้องสร้าง interface และ routing elements เพื่ออนุญาตให้ authentication
การตั้งค่า Routes และ UI ด้วย Tailwind
ในตัวอย่างนี้ เราจะทำงานกับ Ruby on Rails application ที่ใช้ framework version 7.1 พร้อม TailwindCSS
ใช้คำสั่งต่อไปนี้:
เราสามารถเพิ่มสอง controllers พร้อม index action เพื่อเตรียมทดสอบกระบวนการ authentication:
กับสองคำสั่งนั้น สิ่งต่อไปนี้ถูกสร้าง:
- ทั้ง
public_controller.rbและprivate_controller.rbcontrollers พร้อม index action พร้อมใช้งาน - Related routes ทั้งสอง
- Related views ทั้งสอง
มาเพิ่ม Auth0 controller เพื่อจัดการ callbacks และ failures สร้าง controller file (bin/rails g controller auth0) และเพิ่มสิ่งต่อไปนี้:
จากนั้นอัปเดต routes ให้ใช้สาม actions นั้น:
และจากนั้นเราสามารถเพิ่มปุ่ม Login และ Logout ใน public และ private views ตามลำดับ:
ตอนนี้คุณสามารถไปที่ 'https://localhost:3000' ใช้ปุ่ม Login และคุณจะถูก redirect ไปยังหน้า private ที่นั่น คุณจะพบปุ่ม Logout
สองสิ่งที่ขาดไป อย่างไรก็ตาม:
- Data จาก user profile
- การระบุ user และการจัดการ authorization
การทำงานกับ Scopes และ Data
มาย้อนกลับหลายขั้นและนำ initializer กลับมา (config/initializers/auth0.rb):
ชิ้นสำคัญที่นี่คือ scope: openid profile นี้บอก Auth0 เราสนใจในข้อมูลบางชิ้น นั่นคือ:
- Provider name (Auth0)
uid: Unique identifier เพื่อ match userinfohash: มี name, URL ไปยัง profile picture และ 'email' key ว่างextra_infohash: อีกครั้ง มี name และ profile picture แต่ยังมีคู่ given และ family names
อ่านเพิ่มเติมเกี่ยวกับหัวข้อ scopes ในเอกสารของ Auth0
ข้อมูลข้างต้นมีค่า และคุณควรแน่ใจว่า อย่างน้อยเมื่อ first login คุณ copy data นั้นเข้าไปในตารางในแอปพลิเคชันของคุณ
เพื่อทำเช่นนั้น เราต้องใช้ content ของ request-response ใน auth0_controller และ โดยเฉพาะใน callback action:
ใช้ breakpoint ก่อน redirect เพื่อขุดลึกเข้าไปใน hash และทดลอง
เราปกติจะอยากได้ email address ด้วย เพื่อให้ได้มัน คุณสามารถอัปเดต scope:
หลังจาก reload application server และผ่านขั้นตอน login คุณจะต้องให้ application เข้าถึงข้อมูลเพิ่มเติม
ตอนนี้เราสามารถทำอย่างนี้ใน callback action:
สิ่งนี้จะรับรองว่าเรามี local, up-to-date profile สำหรับ user
คำพูดเกี่ยวกับ Sessions
Session เป็น hash พิเศษในแอปพลิเคชัน Ruby on Rails มันมี limited storage ที่เข้าถึงได้จาก controllers และ views และ unique ต่อแต่ละ visitor
เราสามารถ "open" และ "close" sessions ได้ หากเราต้องการ dataset เฉพาะ เราสามารถตัดสินใจว่า session เปิด หากไม่มี data มันปิด
จำบรรทัดต่อไปนี้ใน Auth0 controller ของเรา:
บรรทัดแรกเขียนค่าใน key raw_info ของ hash ไปยัง session hash ในขณะที่บรรทัดที่สองแค่ clear up session hash
เราสามารถกำหนด helper method ต่อไปนี้ใน ApplicationHelper:
A Security Concern (ข้อกังวลด้านความปลอดภัย)
ตอนนี้มใช้สิ่งนี้เป็น concern สำหรับ controllers ของเรา แนวคิดคือกำหนด controller ที่ต้องการ users logged in เพื่อเข้าถึง เช่น private_controller ของเรา
เราสามารถเขียน concern file ต่อไปนี้:
เราสามารถใช้มันใน controllers ของเราได้อย่างนี้:
หาก visitor ไม่ได้ล็อกอิน แต่พยายามเปิดหน้า /private/index พวกเขาจะถูก redirect ไปยัง root ของไซต์โดยอัตโนมัติ
การบูรณาการกับ Providers อื่นๆ
คุณสามารถพึ่งพา multiple providers ผ่าน Auth0 อย่างไรก็ตาม Google ถูกกำหนดเป็น default สำหรับบริษัทหลายแห่ง นั่นเพียงพอแล้ว
หากคุณต้องการ providers มากขึ้น ไปที่เมนู Authentication สำหรับ tenant ที่เกี่ยวข้องใน Auth0 และจากนั้น Social submenu ที่คุณสามารถตั้งค่า additional providers
ยังคุ้มค่าที่จะบันทึกว่า คุณสามารถกำหนด multi-factor authentication (MFA) กับ Auth0 ได้เช่นกัน
กระบวนการจะคงที่เหมือนเดิม ยกเว้นขั้นตอนการกำหนดค่าเหล่านั้น แอปพลิเคชันของเราจะแค่คืน visitor data เพื่อพิสูจน์ว่า visitor ได้รับการ authenticated
การเปิดทางสู่ Authorization
ตอนนี้เราสามารถ authenticate users และส่งข้อมูลของพวกเขาไปยังแอปพลิเคชันของเราผ่าน callback เราได้เห็นแล้วว่าจะได้ email address ของ user จาก hash และหา user ที่เกี่ยวข้องใน database ของเราอย่างไร
จากนั้น เราสามารถกำหนด authorization policies
Pundit เป็นตัวเลือกที่ยอดเยี่ยมสำหรับกำหนดและใช้ authorization policies แต่พึ่งพาการตรวจสอบ role ของ user
การใช้ attribute role เป็นวิธีที่ง่ายที่สุด คุณสามารถกรอกมันตอนสร้าง user ใน Rails console หรือ back-end interface ของแอปพลิเคชันของคุณ ก่อน first login attempt ของ user
หรือคุณสามารถได้ list of admins' emails และ match email ของ user ต่อ list เมื่อสร้าง user
และนั่นคือทั้งหมด!
สิ่งที่เราครอบคลุม
ในบทความนี้ เราตั้งค่า:
- Tenant และ application ใน Auth0
- Auth0-related gems ใน Ruby on Rails application
- Routes และ views ในแอปพลิเคชัน
เราจากนั้น:
- Reviewed session concept และเห็นวิธีใช้มัน
- Created base tooling เพื่อตรวจสอบว่า user ล็อกอินหรือไม่
- Added controller concern เพื่อ secure controllers 後ろに login requirement
- Saw วิธี match users กับ roles ของพวกเขา
Auth0 และ authentication providers อื่นๆ สามารถช่วยคุณ integrate state-of-the-art authentication ในแอปพลิเคชัน Ruby on Rails ของคุณโดยไม่ต้องเขียนโค้ดมาก มันมักเป็นตัวเลือกที่ดีกว่ามากเมื่อเทียบกับการพึ่งพาการ implement authentication layer ของตัวเอง หรือแม้แต่การใช้ gems อย่าง Devise
Happy coding!
P.S. หากคุณอยากอ่าน Ruby Magic posts ทันทีที่พวกเขาออก ให้ subscribe Ruby Magic newsletter ของเรา และไม่เคยพลาดโพสต์เดี่ยว!
Thomas Riboulet
ผู้เขียนรับเชิญ Thomas เป็น Consultant Backend และ Cloud Infrastructure Engineer ที่ตั้งอยู่ใน France มากกว่า 13 ปี เขาทำงานกับ startups และบริษัทเพื่อ scale teams, products และ infrastructure ของพวกเขา เขายังเผยแพร่หลายครั้งในนิตยสาร GNU/Linux ของ France และบน blog ของเขา
บทความทั้งหมดโดย Thomas Riboulet