WebOTP API로 웹에서 전화번호 인증하기

SMS를 통해 받은 OTP로 사용자 지원

WebOTP API란 무엇인가요?

오늘날 전 세계 대부분의 사람들이 휴대기기를 소유하고 있으며 개발자는 일반적으로 서비스 사용자의 식별자로 전화번호를 사용합니다.

전화번호를 인증하는 방법에는 여러 가지가 있지만 SMS에서 전송하는 무작위로 생성된 일회용 비밀번호 (OTP)가 가장 일반적인 방법 중 하나입니다. 이 코드를 개발자의 서버로 다시 전송하면 전화번호를 제어할 수 있습니다.

이 아이디어는 다음을 달성하기 위해 이미 많은 시나리오에 배포되어 있습니다.

  • 사용자의 식별자로 사용되는 전화번호 새 서비스에 가입할 때 일부 웹사이트에서는 이메일 주소 대신 전화번호를 요청하고 이를 계정 식별자로 사용합니다.
  • 2단계 인증. 웹사이트에서는 추가 보안을 위해 비밀번호나 기타 확인 요소 외에도 SMS를 통해 전송된 일회용 코드를 요청합니다.
  • 결제 확인. 사용자가 결제할 때 SMS를 통해 전송된 일회성 코드를 요청하면 사용자의 의도를 확인하는 데 도움이 될 수 있습니다.

현재의 프로세스는 사용자를 불편하게 만듭니다. SMS 메시지에서 OTP를 찾은 다음 복사하여 양식에 붙여넣는 것은 번거롭기 때문에 중요한 사용자 여정에서 전환율이 낮아집니다. 이 작업을 용이하게 하는 것은 수많은 대규모 글로벌 개발자들이 오랫동안 웹에 대해 요구해 온 요청이었습니다. Android에는 이를 정확히 실행하는 API가 있습니다. iOSSafari도 마찬가지입니다.

WebOTP API를 사용하면 앱이 앱의 도메인에 바인딩된 특수 형식의 메시지를 수신할 수 있습니다. 이를 통해 프로그래매틱 방식으로 SMS 메시지에서 OTP를 가져오고 사용자의 전화번호를 더 쉽게 확인할 수 있습니다.

실제 사례 보기

사용자가 웹사이트에서 전화번호를 인증하려 한다고 가정해 보겠습니다. 웹사이트에서 SMS를 통해 사용자에게 문자 메시지를 보내고 사용자는 메시지의 OTP를 입력하여 전화번호의 소유권을 확인합니다.

WebOTP API를 사용하면 동영상에 설명된 대로 사용자가 탭 한 번으로 이러한 단계를 완료할 수 있습니다. 문자 메시지가 도착하면 하단 시트가 나타나고 사용자에게 전화번호를 확인하라는 메시지가 표시됩니다. 하단 시트에서 확인 버튼을 클릭하면 브라우저가 OTP를 양식에 붙여넣고 사용자가 계속을 누르지 않아도 양식이 제출됩니다.

전체 프로세스는 아래 이미지에 나와 있습니다.

WebOTP API 다이어그램

직접 데모를 사용해 보세요. 전화번호를 묻거나 기기로 SMS를 보내지는 않지만 데모에 표시된 텍스트를 복사하여 다른 기기에서 전송할 수 있습니다. WebOTP API를 사용할 때 발신자가 누구인지는 중요하지 않기 때문에 작동합니다.

  1. Android 기기의 Chrome 84 이상에서 https://web-otp.glitch.me로 이동합니다.
  2. 다른 휴대전화에서 내 휴대전화로 다음 SMS 문자 메시지를 보냅니다.
Your OTP is: 123456.

@web-otp.glitch.me #12345

SMS를 받고 입력 영역에 코드를 입력하라는 메시지가 표시되었습니까? 이것이 WebOTP API가 사용자를 위해 작동하는 방식입니다.

WebOTP API 사용은 다음 세 부분으로 구성됩니다.

  • 제대로 주석이 달린 <input> 태그
  • 웹 앱의 JavaScript
  • 서식이 지정된 메시지 텍스트가 SMS로 전송되었습니다.

<input> 태그를 먼저 살펴보겠습니다.

<input> 태그에 주석을 추가합니다.

WebOTP 자체는 HTML 주석 없이도 작동하지만 브라우저 간 호환성을 위해 사용자가 OTP를 입력할 것으로 예상되는 <input> 태그에 autocomplete="one-time-code"를 추가하는 것이 좋습니다.

이를 통해 Safari 14 이상에서는 사용자가 WebOTP를 지원하지 않더라도 SMS 메시지 형식 지정에 설명된 형식으로 SMS를 수신할 때 OTP로 <input> 필드를 자동 완성하도록 사용자에게 제안할 수 있습니다.

HTML

<form>
  <input autocomplete="one-time-code" required/>
  <input type="submit">
</form>

WebOTP API 사용

WebOTP는 간단하므로 다음 코드를 복사하여 붙여넣기만 하면 작업이 완료됩니다. 현재 어떤 일이 일어나고 있는지 안내해 드리겠습니다.

JavaScript

if ('OTPCredential' in window) {
  window.addEventListener('DOMContentLoaded', e => {
    const input = document.querySelector('input[autocomplete="one-time-code"]');
    if (!input) return;
    const ac = new AbortController();
    const form = input.closest('form');
    if (form) {
      form.addEventListener('submit', e => {
        ac.abort();
      });
    }
    navigator.credentials.get({
      otp: { transport:['sms'] },
      signal: ac.signal
    }).then(otp => {
      input.value = otp.code;
      if (form) form.submit();
    }).catch(err => {
      console.log(err);
    });
  });
}

기능 감지

특징 감지는 다른 많은 API와 동일합니다. DOMContentLoaded 이벤트를 수신 대기하는 것은 DOM 트리가 쿼리할 준비가 될 때까지 대기합니다.

JavaScript

if ('OTPCredential' in window) {
  window.addEventListener('DOMContentLoaded', e => {
    const input = document.querySelector('input[autocomplete="one-time-code"]');
    if (!input) return;
    …
    const form = input.closest('form');
    …
  });
}

OTP 처리

WebOTP API 자체는 매우 간단합니다. navigator.credentials.get()를 사용하여 OTP를 받습니다. WebOTP는 이 메서드에 새 otp 옵션을 추가합니다. 여기에는 하나의 속성 transport만 있으며 이 속성의 값은 'sms' 문자열이 포함된 배열이어야 합니다.

JavaScript

    …
    navigator.credentials.get({
      otp: { transport:['sms'] }
      …
    }).then(otp => {
    …

그러면 SMS 메시지가 도착할 때 브라우저의 권한 흐름이 트리거됩니다. 권한이 부여되면 반환된 프로미스는 OTPCredential 객체로 확인됩니다.

가져온 OTPCredential 객체의 콘텐츠

{
  code: "123456" // Obtained OTP
  type: "otp"  // `type` is always "otp"
}

그런 다음 OTP 값을 <input> 필드에 전달합니다. 양식을 직접 제출하면 사용자가 버튼을 탭하지 않아도 됩니다.

JavaScript

    …
    navigator.credentials.get({
      otp: { transport:['sms'] }
      …
    }).then(otp => {
      input.value = otp.code;
      if (form) form.submit();
    }).catch(err => {
      console.error(err);
    });
    …

메시지 취소

사용자가 수동으로 OTP를 입력하고 양식을 제출하는 경우 options 객체에서 AbortController 인스턴스를 사용하여 get() 호출을 취소할 수 있습니다.

JavaScript

    …
    const ac = new AbortController();
    …
    if (form) {
      form.addEventListener('submit', e => {
        ac.abort();
      });
    }
    …
    navigator.credentials.get({
      otp: { transport:['sms'] },
      signal: ac.signal
    }).then(otp => {
    …

SMS 메시지 서식 지정

API 자체는 충분히 간단해 보이지만 사용하기 전에 알아야 할 몇 가지 사항이 있습니다. 메시지는 navigator.credentials.get()가 호출된 후에 전송되어야 하며 get()가 호출된 기기에서 수신되어야 합니다. 마지막으로 메시지는 다음 형식을 따라야 합니다.

  • 메시지는 사람이 읽을 수 있는 텍스트 (선택사항)로 시작됩니다. 이 텍스트에는 4~10자의 영숫자 문자열과 하나 이상의 숫자가 URL 및 OTP의 마지막 줄에 남습니다.
  • API를 호출한 웹사이트 URL에서 도메인 부분 앞에는 @가 와야 합니다.
  • URL에는 우물 정자 ('#')와 OTP를 차례로 포함해야 합니다.

예를 들면 다음과 같습니다.

Your OTP is: 123456.

@www.example.com #123456

다음은 잘못된 예입니다.

잘못된 형식의 SMS 텍스트 예 작동하지 않는 이유
Here is your code for @example.com #123456 @은 마지막 줄의 첫 번째 문자여야 합니다.
Your code for @example.com is #123456 @은 마지막 줄의 첫 번째 문자여야 합니다.
Your verification code is 123456

@example.com\t#123456
@host에서 #code 사이에 1개의 공백이 있어야 합니다.
Your verification code is 123456

@example.com  #123456
@host에서 #code 사이에 1개의 공백이 있어야 합니다.
Your verification code is 123456

@ftp://example.com #123456
URL 스키마는 포함할 수 없습니다.
Your verification code is 123456

@https://example.com #123456
URL 스키마는 포함할 수 없습니다.
Your verification code is 123456

@example.com:8080 #123456
포트를 포함할 수 없습니다.
Your verification code is 123456

@example.com/foobar #123456
경로는 포함할 수 없습니다.
Your verification code is 123456

@example .com #123456
도메인에 공백이 없습니다.
Your verification code is 123456

@domain-forbiden-chars-#%/:<>?@[] #123456
도메인에 금지된 문자가 없습니다.
@example.com #123456

Mambo Jumbo
@host#code가 마지막 줄이 됩니다.
@example.com #123456

App hash #oudf08lkjsdf834
@host#code가 마지막 줄이 됩니다.
Your verification code is 123456

@example.com 123456
#가 누락되었습니다.
Your verification code is 123456

example.com #123456
@가 누락되었습니다.
Hi mom, did you receive my last text @#가 누락되었습니다.

데모

데모에서 다양한 메시지를 사용해 보세요. https://web-otp.glitch.me

https://glitch.com/edit/#!/web-otp에서 코드를 포크하여 직접 만들 수도 있습니다.

교차 출처 iframe에서 WebOTP 사용

교차 출처 iframe에 SMS OTP를 입력하는 것은 일반적으로 결제 확인(특히 3D Secure)에 사용됩니다. 교차 출처 iframe을 지원하는 공통 형식을 갖춘 WebOTP API는 중첩된 출처에 바인딩된 OTP를 제공합니다. 예를 들면 다음과 같습니다.

  • 사용자가 신용카드로 신발을 구매하기 위해 shop.example에 방문합니다.
  • 신용카드 번호를 입력하면 통합 결제 시스템 공급자는 iframe 내에서 bank.example의 양식을 표시하여 빠른 결제를 위해 사용자에게 전화번호 인증을 요청합니다.
  • bank.example는 사용자가 본인 확인을 위해 입력할 수 있도록 OTP가 포함된 SMS를 사용자에게 전송합니다.

교차 출처 iframe 내에서 WebOTP API를 사용하려면 다음 두 가지 작업을 실행해야 합니다.

  • SMS 문자 메시지에서 최상위 프레임 출처와 iframe 출처에 모두 주석을 추가합니다.
  • 교차 출처 iframe에서 사용자로부터 직접 OTP를 수신할 수 있도록 권한 정책을 구성합니다.
iframe 내에서 작동하는 WebOTP API

https://web-otp-iframe-demo.stackblitz.io에서 데모를 사용해 볼 수 있습니다.

SMS 문자 메시지에 바인드된 출처에 주석 추가

iframe 내에서 WebOTP API가 호출되면 SMS 텍스트 메시지에는 최상위 프레임 출처가 포함되어야 합니다. 최상위 프레임 출처는 앞에 @, OTP는 #, 마지막 줄의 @ 앞에는 iframe 출처가 있어야 합니다.

Your verification code is 123456

@shop.example #123456 @bank.exmple

권한 정책 구성

교차 출처 iframe에서 WebOTP를 사용하려면 삽입기가 의도치 않은 동작을 방지하기 위해 otp-credentials 권한 정책을 통해 이 API에 대한 액세스 권한을 부여해야 합니다. 일반적으로 다음과 같은 두 가지 방법으로 이 목표를 달성할 수 있습니다.

HTTP 헤더를 통해:

Permissions-Policy: otp-credentials=(self "https://bank.example")

iframe allow 속성 사용:

<iframe src="https://bank.example/…" allow="otp-credentials"></iframe>

권한 정책을 지정하는 방법에 대한 더 많은 예 를 참고하세요.

데스크톱에서 WebOTP 사용

Chrome에서 WebOTP는 다른 기기에서 수신된 SMS를 수신 대기하여 사용자가 데스크톱에서 전화번호 인증을 완료하도록 지원합니다.

데스크톱의 WebOTP API

이 기능을 사용하려면 사용자가 데스크톱 Chrome과 Android Chrome 모두에서 동일한 Google 계정에 로그인해야 합니다.

개발자는 모바일 웹사이트에서와 동일한 방식으로 데스크톱 웹사이트에 WebOTP API를 구현하기만 하면 되지만 특별한 방법은 필요하지 않습니다.

WebOTP API를 사용하여 데스크톱에서 전화번호 인증하기에서 자세한 내용을 알아보세요.

FAQ

올바른 형식의 메일을 보내도 대화상자가 나타나지 않습니다. 이유가 무엇일까요?

API를 테스트할 때는 몇 가지 주의사항이 있습니다.

  • 발신자의 전화번호가 수신자의 연락처 목록에 포함되어 있으면 기본 SMS User Consent API의 설계로 인해 이 API가 트리거되지 않습니다.
  • Android 기기에서 직장 프로필을 사용 중이며 WebOTP가 작동하지 않으면 대신 개인 프로필(즉, SMS 메시지를 수신하는 프로필)에 Chrome을 설치하고 사용해 보세요.

형식에서 SMS 형식이 올바른지 다시 확인하세요.

이 API는 여러 브라우저 간에 호환되나요?

Chromium과 WebKit은 SMS 문자 메시지 형식에 동의했으며 Apple은 iOS 14 및 macOS Big Sur부터 Safari의 지원을 발표했습니다. Safari는 WebOTP JavaScript API를 지원하지 않지만 input 요소에 autocomplete=["one-time-code"]를 주석으로 처리하여 SMS 메시지가 형식을 준수하면 기본 키보드에서 자동으로 OTP를 입력하도록 제안합니다.

인증 방법으로 SMS를 사용해도 안전한가요?

SMS OTP는 전화번호가 처음 제공될 때 전화번호를 인증하는 데 유용하지만, SMS를 통한 전화번호 인증은 이동통신사에서 전화번호를 도용하고 재활용할 수 있으므로 재인증을 위해 신중하게 사용해야 합니다. WebOTP는 편리한 재인증 및 복구 메커니즘이지만 서비스에서는 이를 지식 문제와 같은 추가 요소와 결합하거나 강력한 인증을 위해 웹 인증 API를 사용해야 합니다.

Chrome 구현의 버그는 어디에 신고해야 하나요?

Chrome 구현에서 버그를 발견하셨나요?

  • https://new.crbug.com에서 버그를 신고합니다. 최대한 많은 세부정보와 간단한 재현 안내를 포함하고 구성요소Blink>WebOTP로 설정합니다.

이 기능을 어떻게 도울 수 있나요?

WebOTP API를 사용할 계획이신가요? 공개 지원은 Google에서 기능의 우선순위를 정하는 데 도움이 되며 다른 브라우저 공급업체에 이러한 기능을 지원하는 것이 얼마나 중요한지 보여줍니다. 해시태그 #WebOTP를 사용하여 @ChromiumDev로 트윗을 보내고 사용 위치와 방법을 알려주세요.

자료