OAuth 2.0 เป็นโปรโตคอลการอนุญาตมาตรฐานอุตสาหกรรมที่ให้แอปพลิเคชันบุคคลที่สามเข้าถึงทรัพยากรของผู้ใช้อย่างจำกัดโดยไม่ต้องแชร์ข้อมูลประจำตัวของพวกเขา โปรโตคอลได้กลายเป็นมาตรฐานโดยพฤตินัยสำหรับการอนุญาตแบบมอบหมายในเว็บและแอปพลิเคชันมือถือ ซึ่งใช้โดยแพลตฟอร์มเช่น Google, Facebook, Apple และ GitHub ตาม IETF RFC 6749 (2025) OAuth 2.0 ถูกใช้ในมากกว่า 85% ของการรวม API ทั้งหมดที่ต้องการการเข้าถึงข้อมูลแบบมอบหมาย
ประเด็นสำคัญ
OAuth 2.0 คือโปรโตคอลการอนุญาตที่กำหนดใน IETF RFC 6749 ซึ่งช่วยให้แอปพลิเคชันบุคคลที่สามสามารถเข้าถึงทรัพยากรของผู้ใช้ได้อย่างจำกัดโดยไม่ต้องเปิดเผยชื่อผู้ใช้และรหัสผ่านของพวกเขา โปรโตคอลแก้ปัญหาพื้นฐานของโมเดลรหัสผ่าน: แอปพลิเคชันที่คุณไว้วางใจให้รหัสผ่านจะสามารถเข้าถึงข้อมูลบัญชีทั้งหมดได้อย่างไร้ขีดจำกัด OAuth 2.0 แทนที่แนวทางนี้ด้วยการออกโทเค็นชั่วคราวที่มีขอบเขตการเข้าถึงจำกัดอย่างชัดเจน
สถาปัตยกรรมของ OAuth 2.0 คือการอนุญาตแบบมอบหมาย ผู้ใช้ (Resource Owner) อนุญาตให้แอปพลิเคชัน (Client) เข้าถึงข้อมูลของตนที่เก็บไว้บนเซิร์ฟเวอร์ทรัพยากร (Resource Server) ผ่านตัวกลาง: เซิร์ฟเวอร์อนุญาต (Authorization Server) เซิร์ฟเวอร์อนุญาตออก Access Token: สตริงเข้ารหัสที่แอปพลิเคชันนำเสนอต่อเซิร์ฟเวอร์ทรัพยากรเพื่อเข้าถึงข้อมูล ความแตกต่างสำคัญระหว่าง OAuth 2.0 กับ SAML หรือ OpenID Connect: OAuth 2.0 แก้ปัญหางานการอนุญาต (สิ่งที่ได้รับอนุญาต) ไม่ใช่การยืนยันตัวตน (ผู้ใช้คือใคร) สำหรับการยืนยันตัวตนบน OAuth 2.0 จะสร้างโปรโตคอล OpenID Connect (OIDC)
โปรโตคอลรองรับโดยแพลตฟอร์มหลักทั้งหมด Google ใช้ OAuth 2.0 สำหรับการเข้าถึง Google APIs (Gmail, Drive, Calendar), Facebook สำหรับ Graph API, Apple สำหรับ Sign in with Apple (ASAuthorizationAppleIDProvider), GitHub สำหรับการเข้าถึงที่เก็บโค้ด ในบริบทของการพัฒนามือถือ OAuth 2.0 เป็นกลไกมาตรฐานสำหรับการรวมบริการบุคคลที่สาม: การเข้าสู่ระบบผ่านเครือข่ายสังคม, การเข้าถึงพื้นที่จัดเก็บคลาวด์ และการเผยแพร่เนื้อหาในนามของผู้ใช้
โปรโตคอล OAuth 2.0 กำหนดสี่บทบาทซึ่งการโต้ตอบกันก่อให้เกิดวงจรการอนุญาตที่สมบูรณ์ การทำความเข้าใจแต่ละบทบาทเป็นสิ่งจำเป็นสำหรับการนำโปรโตคอลไปใช้อย่างถูกต้องในแอปพลิเคชันมือถือ
| บทบาท | คำอธิบาย | ตัวอย่าง |
|---|---|---|
| Resource Owner | เจ้าของข้อมูล: ผู้ใช้อนุญาตให้เข้าถึงทรัพยากรของตน | ผู้ใช้แอปพลิเคชันที่คลิก “เข้าสู่ระบบด้วย Google” |
| Client | แอปพลิเคชันที่ขอเข้าถึงทรัพยากรในนามของเจ้าของ | แอปมือถือที่ต้องการเข้าถึง Google Drive |
| Authorization Server | เซิร์ฟเวอร์ที่ออกโทเค็นหลังจากการยืนยันตัวตนและการอนุญาต | accounts.google.com: เซิร์ฟเวอร์อนุญาตของ Google |
| Resource Server | API ที่ให้การเข้าถึงทรัพยากรที่ได้รับการป้องกันผ่านโทเค็น | www.googleapis.com: เซิร์ฟเวอร์ทรัพยากรของ Google Drive API |
เอนทิตีหลักของโปรโตคอลคือ Access Token, Refresh Token และ Authorization Code Access Token คือโทเค็นอายุสั้น (ปกติ 15–60 นาที) ที่นำเสนอต่อเซิร์ฟเวอร์ทรัพยากรในทุกคำขอข้อมูล Refresh Token คือโทเค็นอายุยาว (วันหรือสัปดาห์) ที่ใช้เพื่อรับ Access Token ใหม่โดยไม่ต้องให้ผู้ใช้เข้าสู่ระบบอีกครั้ง Authorization Code คือรหัสชั่วคราวที่ออกหลังจากการอนุญาตผู้ใช้และแลกเปลี่ยนเป็น Access Token และ Refresh Token
OAuth 2.0 กำหนด Grant Types หลายประเภท: สถานการณ์การรับโทเค็น ซึ่งแต่ละประเภทออกแบบมาสำหรับประเภทไคลเอ็นต์และบริบทความปลอดภัยเฉพาะ การเลือก Grant Type ที่ถูกต้องเป็นการตัดสินใจทางสถาปัตยกรรมที่สำคัญเมื่อออกแบบการอนุญาตในแอปพลิเคชันมือถือ
Grant Types หลักคือ: Authorization Code (ปลอดภัยที่สุดสำหรับแอปมือถือและเว็บที่มีส่วนประกอบเซิร์ฟเวอร์), Authorization Code กับ PKCE (Proof Key for Code Exchange: สำหรับแอปมือถือและ SPA ที่ไม่มีแบ็กเอนด์เซิร์ฟเวอร์), Client Credentials (สำหรับการยืนยันตัวตนเซิร์ฟเวอร์ต่อเซิร์ฟเวอร์โดยไม่ต้องมีผู้ใช้), Resource Owner Password Credentials (เลิกใช้แล้ว: ส่งรหัสผ่านโดยตรง) PKCE เป็นส่วนขยายบังคับสำหรับไคลเอ็นต์สาธารณะ (แอปมือถือ, SPA) ตามคำแนะนำของ OAuth Security BCP (RFC 9700)
Authorization Code Flow กับ PKCE คือการกำหนดค่า OAuth 2.0 ที่แนะนำสำหรับแอปพลิเคชันมือถือแบบเนทีฟ PKCE (Proof Key for Code Exchange) เพิ่มชั้นการป้องกันพิเศษที่ป้องกันการโจมตีแบบสกัดกั้น authorization code โปรโตคอลอธิบายใน IETF RFC 7636
ลำดับขั้นตอน: (1) ไคลเอ็นต์สร้าง code_verifier สุ่ม (สตริง 43–128 อักขระที่ใช้อักขระที่ไม่ได้สงวนไว้เท่านั้น), (2) ไคลเอ็นต์คำนวณ code_challenge = SHA-256(code_verifier), (3) ไคลเอ็นต์เปิดเบราว์เซอร์สำหรับการอนุญาตผู้ใช้บน Authorization Server โดยส่ง code_challenge, (4) หลังจากการอนุญาตสำเร็จ เซิร์ฟเวอร์ส่งคืน authorization code ให้แอปพลิเคชันผ่านสคีมา URI ที่กำหนดเอง (ดีปลิงก์ของแอป), (5) ไคลเอ็นต์ส่ง authorization code + code_verifier ไปยังเซิร์ฟเวอร์, (6) เซิร์ฟเวอร์ตรวจสอบ SHA-256(code_verifier) === code_challenge และออก Access Token + Refresh Token
ข้อดีของ PKCE: แม้ว่าผู้โจมตีจะสกัดกั้น authorization code ในสคีมา URI พวกเขาก็ไม่สามารถแลกเปลี่ยนเป็นโทเค็นได้หากไม่มี code_verifier ซึ่งมีเพียงไคลเอ็นต์ที่ถูกต้องเท่านั้นที่รู้ ในแอปพลิเคชันมือถือ การเปิดเบราว์เซอร์ควรใช้ Chrome Custom Tabs (Android) หรือ ASWebAuthenticationSession (iOS): ซึ่งรับประกันว่าเบราว์เซอร์ระบบไม่สามารถเข้าถึง code_verifier จากหน่วยความจำของแอปพลิเคชันได้
AppAuth คือการนำอ้างอิงของ OAuth 2.0 และ OpenID Connect สำหรับแอปพลิเคชันแบบเนทีฟที่แนะนำโดย IETF ไลบรารีรองรับ PKCE, Chrome Custom Tabs, สคีมา URI ที่กำหนดเองสำหรับส่งคืน authorization code และการรีเฟรชโทเค็นอัตโนมัติ AppAuth สำหรับ Android พร้อมใช้งานผ่าน dependency `net.openid:appauth:0.11.1`
val serviceConfig = AuthorizationServiceConfiguration.fromUrl(
Uri.parse("https://accounts.google.com/.well-known/openid-configuration")
)
val request = AuthorizationRequest.Builder(
serviceConfig,
"CLIENT_ID.apps.googleusercontent.com",
ResponseTypeValues.CODE,
Uri.parse("com.example.app:/oauth2callback")
)
.setScope("openid profile email")
.setCodeVerifier(
CodeVerifierUtil.generateRandomCodeVerifier()
)
.build()
val authService = AuthorizationService(context)
val intent = authService.getAuthorizationRequestIntent(request)
// เปิดใช้ Chrome Custom Tab สำหรับการอนุญาต
startActivityForResult(intent, REQUEST_CODE_AUTH)
หลังจากได้รับ authorization code (onActivityResult) แอปพลิเคชันจะแลกเปลี่ยนเป็น Access Token และ Refresh Token ผ่าน TokenRequest โทเค็นถูกบันทึกใน SharedPreferences ด้วยการเข้ารหัสผ่าน EncryptedSharedPreferences (Android Security Crypto) Refresh Token ควรถูกเก็บใน KeyStore: ที่เก็บคีย์บนฮาร์ดแวร์ที่แอปพลิเคชันอื่นไม่สามารถเข้าถึงได้ ทุกครั้งที่ Access Token หมดอายุ แอปพลิเคชันใช้ Refresh Token เพื่อรับใหม่: ผู้ใช้ไม่จำเป็นต้องยืนยันตัวตนอีกครั้ง
// แลกเปลี่ยน authorization code เป็นโทเค็น
val data = intent?.data ?: return
val resp = AuthorizationResponse.fromIntent(data)
val exchangeReq = resp?.createTokenExchangeRequest()
?: return
authService.performTokenRequest(
exchangeReq,
ClientAuthentication.none()
) { tokenResp, ex ->
if (tokenResp != null) {
// ได้รับ Access Token และ Refresh Token แล้ว
val accessToken = tokenResp.accessToken
val refreshToken = tokenResp.refreshToken
// บันทึกใน EncryptedSharedPreferences
saveTokens(accessToken, refreshToken)
}
}
โค้ดด้านบนสาธิตโฟลว์ OAuth 2.0 แบบสมบูรณ์กับ PKCE: การสร้างการกำหนดค่าเซิร์ฟเวอร์ผ่าน OpenID Connect Discovery, การสร้างคำขออนุญาตด้วย code_verifier, การเริ่ม Chrome Custom Tab, การรับ authorization code ผ่านสคีมา URI ที่กำหนดเอง และการแลกเปลี่ยนรหัสเป็นโทเค็นผ่าน Token Request การจัดการการหมดอายุของ Access Token เป็นสิ่งสำคัญ: เมื่อได้รับการตอบสนอง HTTP 401 จาก Resource Server แอปพลิเคชันควรใช้ Refresh Token เพื่อรับ Access Token ใหม่และดำเนินการขออีกครั้ง
OAuth 2.0 เป็นโปรโตคอลที่ซับซ้อนที่มีเวกเตอร์การโจมตีมากมาย IETF Security BCP (RFC 9700) อธิบายช่องโหว่ของ OAuth 2.0 มากกว่า 20 คลาส สำหรับแอปพลิเคชันมือถือ สิ่งที่สำคัญที่สุดคือ: การสกัดกั้น authorization code ผ่านสคีมา URI ที่กำหนดเอง, การโจมตี CSRF บนจุดสิ้นสุด callback, การขโมย Refresh Token จากพื้นที่จัดเก็บที่ไม่ปลอดภัย และการปลอมแปลงไคลเอ็นต์ผ่านการสกัดกั้น intent
การป้องกันจากการโจมตีเหล่านี้รวมถึงมาตรการบังคับ: (1) PKCE กับ S256 code_challenge: ป้องกันการสกัดกั้น authorization code แม้ว่าสคีมา URI จะถูกสกัดกั้น; (2) การใช้พารามิเตอร์ nonce หรือ state เพื่อป้องกัน CSRF: เซิร์ฟเวอร์ตรวจสอบว่า authorization code ตรงกับคำขอเดิม; (3) การเก็บ Refresh Token ใน KeyStore (Android) หรือ Keychain (iOS) เท่านั้น: ไม่เคยใน SharedPreferences หรือ UserDefaults; (4) การใช้ TLS กับ Certificate Pinning เพื่อป้องกัน MITM ที่เลเยอร์การขนส่ง; (5) การตรวจสอบ redirect_uri: เซิร์ฟเวอร์อนุญาตต้องตรวจสอบความตรงกับ URI ที่ลงทะเบียนอย่างเคร่งครัด
คำแนะนำเพิ่มเติมจาก IETF: แอปพลิเคชันมือถือควรใช้ AppAuth หรือไลบรารีที่คล้ายกันที่ผ่านการตรวจสอบความปลอดภัย; ไม่พึ่งพา WebView สำหรับ OAuth (WebView ไม่แยกข้อมูลจากแอปพลิเคชันหลัก); นำการหมุนเวียน Refresh Token อัตโนมัติไปใช้ (แต่ละ Refresh Token สามารถใช้ได้เพียงครั้งเดียว); เพิ่ม Certificate Pinning ผ่าน TrustManager สำหรับ Android และ URLSession สำหรับ iOS OpenID Connect Discovery (จุดสิ้นสุด well-known) ช่วยกำหนดจุดสิ้นสุดที่ถูกต้องของเซิร์ฟเวอร์อนุญาตโดยอัตโนมัติและหลีกเลี่ยงการเปลี่ยนเส้นทางไปยังหน้าฟิชชิ่ง
คำถามที่พบบ่อย
OAuth 2.0 คือโปรโตคอลการอนุญาต (สิ่งที่ได้รับอนุญาตให้ทำ?) ในขณะที่ OpenID Connect (OIDC) คือโปรโตคอลการยืนยันตัวตน (ผู้ใช้คือใคร?) OIDC สร้างขึ้นบน OAuth 2.0 และเพิ่ม ID Token: โทเค็น JWT ที่มีข้อมูลเกี่ยวกับตัวตนของผู้ใช้ OAuth 2.0 ให้ Access Token, OIDC เสริมด้วย ID Token และจุดสิ้นสุด UserInfo สำหรับรับโปรไฟล์ผู้ใช้
Bearer Token คือ Access Token ที่นำเสนอในส่วนหัว HTTP Authorization: Bearer อันตรายของมันอยู่ที่ใครก็ตามที่มีโทเค็นสามารถเข้าถึงทรัพยากรได้: โทเค็นไม่ได้ผูกกับไคลเอ็นต์ ดังนั้น Bearer Token ควรส่งผ่าน TLS (HTTPS) เท่านั้น มีอายุสั้น (15–60 นาที) และไม่เคยเก็บในบันทึกหรือพารามิเตอร์ URL
แอปพลิเคชันมือถือเป็นไคลเอ็นต์สาธารณะที่ไม่มี client_secret (ความลับไม่สามารถป้องกันใน APK/IPA ได้) หากไม่มี PKCE ผู้โจมตีสามารถสกัดกั้น authorization code ผ่านสคีมา URI ที่กำหนดเอง (เช่น malformed://callback?code=ABC) และแลกเปลี่ยนเป็นโทเค็น PKCE เพิ่ม code_verifier ที่รู้เฉพาะแอปพลิเคชัน ทำให้รหัสที่ถูกสกัดกั้นไร้ประโยชน์
Access Token ทั่วไปมีอายุ 15–60 นาที (กำหนดค่าได้บนเซิร์ฟเวอร์อนุญาต) ทุกคำขอ HTTP ไปยัง Resource Server จะตรวจสอบการตอบสนอง: หากรหัสเป็น 401 แอปพลิเคชันจะเรียกใช้ Refresh Token Flow เพื่อรับ Access Token ใหม่ Refresh Token มีอายุตั้งแต่ 24 ชั่วโมงถึงหลายเดือน ขึ้นอยู่กับนโยบายความปลอดภัยของผู้ให้บริการ เมื่อ Refresh Token เปลี่ยนแปลง โทเค็นเก่าจะถูกทำให้ใช้ไม่ได้
ไม่: IETF Security BCP (RFC 9700) ห้าม WebView สำหรับ OAuth 2.0 ในแอปพลิเคชันมือถือ WebView ไม่แยกคุกกี้และข้อมูลจากแอปพลิเคชันหลัก ซึ่งทำให้แอปพลิเคชันสามารถสกัดกั้นข้อมูลประจำตัวของผู้ใช้ แทนที่ WebView ให้ใช้ Chrome Custom Tabs (Android) หรือ ASWebAuthenticationSession (iOS): ส่วนประกอบเบราว์เซอร์ระบบที่แยกจากแอปพลิเคชัน
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม