안녕하세요. 이전시간에는 PublicKeyCredentialCreationOptions에 대해서 알아보았는데요. 오늘은 navigator.credentials.create을 위해서 서버로부터 받은 publicKeyCredentialCreationOption을 디코딩하고 navigator.credentials.create메소드를 통해 publicKeyCredentail을 만드는 과정을 보겠습니다.
먼저 제가 발급한 publicKeyCredentialCreationOption입니다.

이후 이 publicKeyCredentialCreationOption이 어떻게 decode되는지 보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
WebAuthn.prototype.register = function(publicKey, callback) {
console.log(publicKey);
let publicKeyCredential = Object.assign({}, publicKey);
console.log(publicKeyCredential.user.id);
publicKeyCredential.user.id = this._bufferDecode(publicKey.user.id);
console.log(publicKeyCredential.user.id);
publicKeyCredential.challenge = this._bufferDecode(this._base64Decode(publicKey.challenge));
if (publicKey.excludeCredentials) {
publicKeyCredential.excludeCredentials = this._credentialDecode(publicKey.excludeCredentials);
}
var self = this;
console.log(publicKeyCredential);
navigator.credentials.create({
publicKey: publicKeyCredential
}).then((data) => {
self._registerCallback(data, callback);
}, (error) => {
self._notify(error.name, error.message, false);
});
}
|
cs |
this._bufferDecode 메소드와 this._base64Decode 메소드는 아래에 있습니다.
this._bufferDecode
1
2
3
4
5
|
WebAuthn.prototype._bufferDecode = function(value) {
var t = window.atob(value)
return Uint8Array.from(t, c => c.charCodeAt(0));
}
|
cs |
this._base64Decode
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
WebAuthn.prototype._base64Decode = function(input) {
// Replace non-url compatible chars with base64 standard chars
input = input.replace(/-/g, '+').replace(/_/g, '/');
// Pad out with standard base64 required padding characters
const pad = input.length % 4;
if (pad) {
if (pad === 1) {
throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding');
}
input += new Array(5-pad).join('=');
}
return input;
}
|
cs |
이후 다음과 같이 변합니다.

이후에 이 publicKeyCredential를 이용해서 navigator.credentials.create()에 인자값으로 넣어주세요 ㅎㅎ 원하시는 Option을 제대로 넣었다면 다음과 같은 화면이 나타납니다.

navigator.credentials.create()의 실행 결과인 PublicKeyCredential은 다음과 같습니다. 이 중에서 ClientDataJson과 AttensionObject가 중요한데요. ClientDataJson에는 challenge와 type 등 유효성 검사용 데이터가 들어있고 AttestationObject에는 추후 이용할 인증 정보가 들어 있습니다. 이후 서버에서는 이 두 데이터를 파싱한 후 처리를 할 예정입니다. 자세한 사항은 아래 Spec으로 확인해보세요 ㅎㅎ

이후에 서버에서는 이 데이터를 파싱(디코딩)한 후에 (1)유효한 요청인지 검사하고 (2)인증 정보를 저장합니다. 이것은 다음 포스트에서 함께 해보겠습니다. 또한 보시다시피 데이터들이 encoding, decoding 되는 과정이 꽤나 복잡하기 때문에 추후 정리해보겠습니다. ( 아래 참고로 dependencies 링크를 첨부했습니다, 아래 나오는 것들만 사용된다고 보심 될 것 같습니다 ㅎㅎ,, )