생체 인증
지문 및 안면 인식 인증
개요
기기의 지문 또는 안면 인식을 웹 페이지에서 JavaScript로 호출합니다. Android와 iOS 모두 지원합니다.
| 기능 | Android | iOS |
|---|---|---|
| 지문 인증 | ✓ BiometricPrompt (Android 7.0+) | ✓ Touch ID |
| 안면 인증 | ✓ BiometricPrompt (Android 7.0+) | ✓ Face ID |
지원 플랜: Standard 이상 (라이선스 기능 biometric 필요)
사전 준비
Android
AndroidManifest.xml에는 생체 인증 권한이 주석 처리된 상태로 배포됩니다. 생체 인증을 사용하려면 주석을 해제하세요.
<uses-permission android:name="android.permission.USE_BIOMETRIC" />iOS
Face ID를 사용하려면 Info.plist에 NSFaceIDUsageDescription 키를 추가해야 합니다. Face ID와 Touch ID 중 어떤 것을 사용할지는 기기가 자동으로 결정합니다.
<key>NSFaceIDUsageDescription</key>
<string>본인 확인을 위해 Face ID를 사용합니다.</string>생체 인증 실행
unveilyBridge.auth.biometric(cb)를 호출하면 시스템 생체 인증 프롬프트가 표시됩니다. cb는 결과를 받을 콜백 함수 이름 문자열입니다. 생략하면 기본값 'onBiometricResult'가 사용됩니다.
// 콜백 이름을 직접 지정
window.unveilyBridge.auth.biometric("onBiometricResult");
// 또는 기본 콜백(onBiometricResult) 사용
window.unveilyBridge.auth.biometric();
function onBiometricResult(result) {
if (result.success) {
proceedWithSecureAction(); // 인증 성공
return;
}
if (result.cancelled) {
return; // 사용자가 취소
}
// 그 외 실패 — 미등록/미지원/플랜 미지원 등은 error 메시지로 전달됨
console.error("인증 실패:", result.error);
showPasswordFallback();
}결과는 이미 파싱된 JS 객체로 전달됩니다. JSON.parse()를 호출할 필요가 없습니다. 생체 정보 미등록, 하드웨어 미지원, 플랜 미충족 등은 모두 result.error 메시지로 확인할 수 있습니다.
응답 구조
콜백은 다음 세 가지 형태 중 하나의 객체를 받습니다.
{ "success": true }{ "success": false, "cancelled": true }{ "success": false, "error": "..." }| 필드 | 설명 |
|---|---|
success | 인증 성공 여부 (true / false) |
cancelled | 사용자가 프롬프트를 취소하면 true |
error | 실패 사유 메시지 (미등록/미지원/플랜 미충족 등) |
서버 세션 연동
생체 인증 성공 후 서버에서 세션을 확정하는 패턴입니다.
function onBiometricResult(result) {
if (result.success) {
// 서버에 인증 완료 신호 전달
fetch('/api/auth/biometric-verified', { method: 'POST' })
.then(() => window.location.href = '/secure-area');
}
}app.post('/api/auth/biometric-verified', (req, res) => {
// 이미 로그인된 세션에서 생체 인증 완료 플래그 설정
if (!req.session.userId) {
return res.status(401).json({ error: 'Not logged in' });
}
req.session.biometricVerified = true;
res.json({ ok: true });
});[HttpPost("auth/biometric-verified")]
[Authorize]
public IActionResult BiometricVerified()
{
HttpContext.Session.SetString("BiometricVerified", "true");
return Ok(new { ok = true });
}@PostMapping("/api/auth/biometric-verified")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<?> biometricVerified(HttpSession session) {
session.setAttribute("biometricVerified", true);
return ResponseEntity.ok(Map.of("ok", true));
}<?php
session_start();
if (!isset($_SESSION['user_id'])) {
http_response_code(401);
exit(json_encode(['error' => 'Not logged in']));
}
$_SESSION['biometric_verified'] = true;
echo json_encode(['ok' => true]);<%
If Session("user_id") = "" Then
Response.Status = "401 Unauthorized"
Response.End
End If
Session("biometric_verified") = True
Response.ContentType = "application/json"
Response.Write "{""ok"": true}"
%>