| // Licensed to the Software Freedom Conservancy (SFC) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The SFC licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| 'use strict' |
| |
| /** |
| * Protocol for virtual authenticators |
| * @enum {string} |
| */ |
| const Protocol = { |
| CTAP2: 'ctap2', |
| U2F: 'ctap1/u2f', |
| } |
| |
| /** |
| * AuthenticatorTransport values |
| * @enum {string} |
| */ |
| const Transport = { |
| BLE: 'ble', |
| USB: 'usb', |
| NFC: 'nfc', |
| INTERNAL: 'internal', |
| } |
| |
| /** |
| * Options for the creation of virtual authenticators. |
| * @see http://w3c.github.io/webauthn/#sctn-automation |
| */ |
| class VirtualAuthenticatorOptions { |
| /** |
| * Constructor to initialise VirtualAuthenticatorOptions object. |
| */ |
| constructor() { |
| this._protocol = Protocol['CTAP2'] |
| this._transport = Transport['USB'] |
| this._hasResidentKey = false |
| this._hasUserVerification = false |
| this._isUserConsenting = true |
| this._isUserVerified = false |
| } |
| |
| getProtocol() { |
| return this._protocol |
| } |
| |
| setProtocol(protocol) { |
| this._protocol = protocol |
| } |
| |
| getTransport() { |
| return this._transport |
| } |
| |
| setTransport(transport) { |
| this._transport = transport |
| } |
| |
| getHasResidentKey() { |
| return this._hasResidentKey |
| } |
| |
| setHasResidentKey(value) { |
| this._hasResidentKey = value |
| } |
| |
| getHasUserVerification() { |
| return this._hasUserVerification |
| } |
| |
| setHasUserVerification(value) { |
| this._hasUserVerification = value |
| } |
| |
| getIsUserConsenting() { |
| return this._isUserConsenting |
| } |
| |
| setIsUserConsenting(value) { |
| this._isUserConsenting = value |
| } |
| |
| getIsUserVerified() { |
| return this._isUserVerified |
| } |
| |
| setIsUserVerified(value) { |
| this._isUserVerified = value |
| } |
| |
| toDict() { |
| return { |
| protocol: this.getProtocol(), |
| transport: this.getTransport(), |
| hasResidentKey: this.getHasResidentKey(), |
| hasUserVerification: this.getHasUserVerification(), |
| isUserConsenting: this.getIsUserConsenting(), |
| isUserVerified: this.getIsUserVerified(), |
| } |
| } |
| } |
| |
| /** |
| * A credential stored in a virtual authenticator. |
| * @see https://w3c.github.io/webauthn/#credential-parameters |
| */ |
| class Credential { |
| constructor(credentialId, isResidentCredential, rpId, userHandle, privateKey, signCount) { |
| this._id = credentialId |
| this._isResidentCredential = isResidentCredential |
| this._rpId = rpId |
| this._userHandle = userHandle |
| this._privateKey = privateKey |
| this._signCount = signCount |
| } |
| |
| static createResidentCredential(id, rpId, userHandle, privateKey, signCount) { |
| return new Credential(id, true, rpId, userHandle, privateKey, signCount) |
| } |
| |
| static createNonResidentCredential(id, rpId, privateKey, signCount) { |
| return new Credential(id, false, rpId, null, privateKey, signCount) |
| } |
| |
| id() { |
| return this._id |
| } |
| |
| isResidentCredential() { |
| return this._isResidentCredential |
| } |
| |
| rpId() { |
| return this._rpId |
| } |
| |
| userHandle() { |
| if (this._userHandle != null) { |
| return this._userHandle |
| } |
| return null |
| } |
| |
| privateKey() { |
| return this._privateKey |
| } |
| |
| signCount() { |
| return this._signCount |
| } |
| |
| /** |
| * Creates a resident (i.e. stateless) credential. |
| * @param id Unique base64 encoded string. |
| * @param rpId Relying party identifier. |
| * @param userHandle userHandle associated to the credential. Must be Base64 encoded string. |
| * @param privateKey Base64 encoded PKCS |
| * @param signCount initial value for a signature counter. |
| * @deprecated This method has been made static. Call it with class name. Example, Credential.createResidentCredential() |
| * @returns A resident credential |
| */ |
| createResidentCredential(id, rpId, userHandle, privateKey, signCount) { |
| return new Credential(id, true, rpId, userHandle, privateKey, signCount) |
| } |
| |
| /** |
| * Creates a non-resident (i.e. stateless) credential. |
| * @param id Unique base64 encoded string. |
| * @param rpId Relying party identifier. |
| * @param privateKey Base64 encoded PKCS |
| * @param signCount initial value for a signature counter. |
| * @deprecated This method has been made static. Call it with class name. Example, Credential.createNonResidentCredential() |
| * @returns A non-resident credential |
| */ |
| createNonResidentCredential(id, rpId, privateKey, signCount) { |
| return new Credential(id, false, rpId, null, privateKey, signCount) |
| } |
| |
| toDict() { |
| let credentialData = { |
| credentialId: Buffer.from(this._id).toString('base64url'), |
| isResidentCredential: this._isResidentCredential, |
| rpId: this._rpId, |
| privateKey: Buffer.from(this._privateKey, 'binary').toString('base64url'), |
| signCount: this._signCount, |
| } |
| |
| if (this.userHandle() != null) { |
| credentialData['userHandle'] = Buffer.from(this._userHandle).toString('base64url') |
| } |
| |
| return credentialData |
| } |
| |
| /** |
| * Creates a credential from a map. |
| */ |
| fromDict(data) { |
| let id = new Uint8Array(Buffer.from(data['credentialId'], 'base64url')) |
| let isResidentCredential = data['isResidentCredential'] |
| let rpId = data['rpId'] |
| let privateKey = Buffer.from(data['privateKey'], 'base64url').toString('binary') |
| let signCount = data['signCount'] |
| let userHandle |
| |
| if ('userHandle' in data) { |
| userHandle = new Uint8Array(Buffer.from(data['userHandle'], 'base64url')) |
| } else { |
| userHandle = null |
| } |
| return new Credential(id, isResidentCredential, rpId, userHandle, privateKey, signCount) |
| } |
| } |
| |
| // PUBLIC API |
| |
| module.exports = { |
| Credential, |
| VirtualAuthenticatorOptions, |
| Transport, |
| Protocol, |
| } |