SMS OTP 양식을 최적화하고 사용자 환경을 개선하는 방법을 알아보세요.
사용자에게 SMS를 통해 전송된 OTP (일회용 비밀번호)를 제공하도록 요청하는 것은 사용자의 전화번호를 확인하는 일반적인 방법입니다. SMS OTP의 사용 사례는 다음과 같습니다.
- 2단계 인증 사용자 이름과 비밀번호 외에도 SMS OTP는 SMS OTP를 받은 사용자가 계정을 소유하고 있다는 강력한 신호로 사용할 수 있습니다.
- 전화번호 인증 일부 서비스에서는 전화번호를 사용자의 기본 식별자로 사용합니다. 이러한 서비스에서 사용자는 전화번호와 SMS를 통해 수신한 OTP를 입력하여 신원을 증명할 수 있습니다. PIN과 결합하여 2단계 인증을 구성하는 경우도 있습니다.
- 계정 복구 사용자가 계정에 액세스할 수 없게 되면 계정을 복구할 방법이 있어야 합니다. 등록된 이메일 주소로 이메일을 보내거나 전화번호로 SMS OTP를 보내는 것이 일반적인 계정 복구 방법입니다.
- 결제 확인 결제 시스템에서 일부 은행 또는 신용카드 발급기관은 보안상의 이유로 결제자에게 추가 인증을 요청합니다. SMS OTP가 일반적으로 이 목적으로 사용됩니다.
이 게시물에서는 위의 사용 사례에 맞게 SMS OTP 양식을 빌드하기 위한 권장사항을 설명합니다.
체크리스트
SMS OTP로 최상의 사용자 환경을 제공하려면 다음 단계를 따르세요.
<input>
요소는 다음과 함께 사용합니다.type="text"
inputmode="numeric"
autocomplete="one-time-code"
@BOUND_DOMAIN #OTP_CODE
을 OTP SMS 메시지의 마지막 줄로 사용합니다.- WebOTP API를 사용합니다.
<input>
요소 사용
<input>
요소가 있는 양식을 사용하는 것이 가장 중요한 권장사항입니다. 모든 브라우저에서 작동하기 때문입니다. 이 게시물의 다른 제안사항이 일부 브라우저에서 작동하지 않더라도 사용자는 OTP를 수동으로 입력하고 제출할 수 있습니다.
<form action="/verify-otp" method="POST">
<input type="text"
inputmode="numeric"
autocomplete="one-time-code"
pattern="\d{6}"
required>
</form>
다음은 입력란에서 브라우저 기능을 최대한 활용할 수 있도록 하는 몇 가지 아이디어입니다.
type="text"
OTP는 일반적으로 5자리 또는 6자리 숫자이므로 입력란에 type="number"
를 사용하면 휴대전화 키보드가 숫자로만 변경되므로 직관적으로 보일 수 있습니다. 브라우저는 입력란이 여러 숫자의 시퀀스가 아닌 셀 수 있는 숫자라고 예상하므로 예기치 않은 동작이 발생할 수 있으므로 이 방법은 권장하지 않습니다. type="number"
를 사용하면 입력란 옆에 위쪽 및 아래쪽 버튼이 표시됩니다. 이러한 버튼을 누르면 숫자가 증가 또는 감소하며 앞에 있는 0이 삭제될 수 있습니다.
대신 type="text"
를 사용하세요. 이렇게 해도 모바일 키보드가 숫자만 표시되지는 않지만 inputmode="numeric"
사용에 관한 다음 도움말에서 이 작업을 처리하므로 괜찮습니다.
inputmode="numeric"
inputmode="numeric"
를 사용하여 모바일 키보드를 숫자만 사용하도록 변경합니다.
일부 웹사이트에서는 포커스가 있을 때 모바일 키보드를 숫자 전용 (*
및 #
포함)으로 전환하기도 하므로 OTP 입력란에 type="tel"
를 사용합니다. 이 해킹은 과거 inputmode="numeric"
가 광범위하게 지원되지 않았을 때 사용되었습니다. Firefox에서 inputmode="numeric"
지원을 시작했으므로 의미상 잘못된 type="tel"
해킹을 사용할 필요가 없습니다.
autocomplete="one-time-code"
autocomplete
속성을 사용하면 개발자가 브라우저가 자동 완성 지원을 제공하는 데 필요한 권한을 지정하고 입력란에 예상되는 정보 유형을 브라우저에 알릴 수 있습니다.
autocomplete="one-time-code"
를 사용하면 사용자가 양식을 열어 둔 상태에서 SMS 메시지를 받을 때마다 운영체제에서 SMS의 OTP를 휴리스틱 방식으로 파싱하고 키보드에서 사용자가 입력할 OTP를 추천합니다. 이 기능은 iOS, iPadOS, macOS의 Safari 12 이상에서만 작동하지만, 이러한 플랫폼에서 SMS OTP 환경을 쉽게 개선할 수 있으므로 사용을 권장합니다.
autocomplete="one-time-code"
는 사용자 환경을 개선하지만 SMS 메시지가 출처 기반 메시지 형식을 준수하도록 하여 더 많은 작업을 할 수 있습니다.
SMS 텍스트 서식 지정
SMS를 통해 전송되는 출처 기반 일회용 코드 사양에 맞춰 OTP 입력 사용자 환경을 개선합니다.
형식 규칙은 간단합니다. 수신자 도메인 앞에 @
, OTP 앞에 #
를 붙여 SMS 메시지를 완성합니다.
예를 들면 다음과 같습니다.
Your OTP is 123456
@web-otp.glitch.me #123456
OTP 메시지에 표준 형식을 사용하면 코드를 더 쉽고 안정적으로 추출할 수 있습니다. OTP 코드를 웹사이트와 연결하면 사용자가 악성 사이트에 코드를 제공하도록 속이기 더 어려워집니다.
이 형식을 사용하면 다음과 같은 몇 가지 이점이 있습니다.
- OTP는 도메인에 연결됩니다. 사용자가 SMS 메시지에 지정된 도메인이 아닌 도메인에 있는 경우 OTP 추천이 표시되지 않습니다. 또한 피싱 공격 및 계정 도용 위험도 완화됩니다.
- 이제 브라우저는 불안정하고 불분명한 휴리스틱에 의존하지 않고도 OTP를 안정적으로 추출할 수 있습니다.
웹사이트에서 autocomplete="one-time-code"
를 사용하는 경우 iOS 14 이상을 실행하는 Safari에서는 위 규칙에 따라 OTP를 제안합니다.
이 SMS 메시지 형식은 Safari 이외의 브라우저에도 유용합니다. Android의 Chrome, Opera, Vivaldi도 autocomplete="one-time-code"
을 통해서는 아니지만 WebOTP API를 사용하여 출처에 연결된 일회용 코드 규칙을 지원합니다.
WebOTP API 사용
WebOTP API는 SMS 메시지로 수신된 OTP에 대한 액세스를 제공합니다. transport
에 sms
가 포함된 otp
유형 (OTPCredential
)으로 navigator.credentials.get()
를 호출하면 웹사이트는 출처에 연결된 일회용 코드를 준수하는 SMS가 전송되고 사용자가 액세스 권한을 부여할 때까지 기다립니다. OTP가 JavaScript에 전달되면 웹사이트에서 양식에 사용할 수 있거나 서버에 직접 POST할 수 있습니다.
navigator.credentials.get({
otp: {transport:['sms']}
})
.then(otp => input.value = otp.code);
WebOTP API로 웹에서 전화번호 인증에서 WebOTP API를 사용하는 방법을 자세히 알아보거나 다음 스니펫을 복사하여 붙여넣으세요. <form>
요소에 action
및 method
속성이 올바르게 설정되어 있는지 확인합니다.
// Feature detection
if ('OTPCredential' in window) {
window.addEventListener('DOMContentLoaded', e => {
const input = document.querySelector('input[autocomplete="one-time-code"]');
if (!input) return;
// Cancel the WebOTP API if the form is submitted manually.
const ac = new AbortController();
const form = input.closest('form');
if (form) {
form.addEventListener('submit', e => {
// Cancel the WebOTP API.
ac.abort();
});
}
// Invoke the WebOTP API
navigator.credentials.get({
otp: { transport:['sms'] },
signal: ac.signal
}).then(otp => {
input.value = otp.code;
// Automatically submit the form when an OTP is obtained.
if (form) form.submit();
}).catch(err => {
console.log(err);
});
});
}