Comparing version 0.1.3 to 0.2.0
@@ -8,11 +8,20 @@ export declare type CancellablePromise<T> = Promise<T> & { | ||
export declare type SignResponse = any; | ||
export interface ErrorCodesEnum { | ||
CANCELED: number; | ||
BAD_REQUEST: number; | ||
CONFIGURATION_UNSUPPORTED: number; | ||
DEVICE_INELIGIBLE: number; | ||
OK: number; | ||
OTHER_ERROR: number; | ||
TIMEOUT: number; | ||
export declare enum ErrorCodesEnum { | ||
CANCELLED = -1, | ||
OK = 0, | ||
OTHER_ERROR = 1, | ||
BAD_REQUEST = 2, | ||
CONFIGURATION_UNSUPPORTED = 3, | ||
DEVICE_INELIGIBLE = 4, | ||
TIMEOUT = 5, | ||
} | ||
export declare const ErrorNames: { | ||
"-1": string; | ||
"0": string; | ||
"1": string; | ||
"2": string; | ||
"3": string; | ||
"4": string; | ||
"5": string; | ||
}; | ||
export interface API { | ||
@@ -19,0 +28,0 @@ isSupported: () => CancellablePromise<boolean>; |
@@ -5,8 +5,50 @@ 'use strict'; | ||
var hasNativeSupport = | ||
( typeof window.u2f !== 'undefined' ) && | ||
( typeof window.u2f.sign === 'function' ); | ||
var _u2f = hasNativeSupport ? window.u2f : null; | ||
var chromeApi = hasNativeSupport ? null : require( './google-u2f-api' ); | ||
var chromeApi = require( './google-u2f-api' ); | ||
var _backend = null; | ||
function getBackend( Promise ) | ||
{ | ||
if ( !_backend ) | ||
_backend = new Promise( function( resolve, reject ) | ||
{ | ||
var hasNativeSupport = | ||
( typeof window.u2f !== 'undefined' ) && | ||
( typeof window.u2f.sign === 'function' ); | ||
if ( hasNativeSupport ) | ||
resolve( { u2f: window.u2f, native: true } ); | ||
function notSupported( ) | ||
{ | ||
// Note; {native: true} means *not* using Google's hack | ||
resolve( { u2f: null, native: true } ); | ||
} | ||
var isSafari = navigator.userAgent.match( /Safari\// ) | ||
&& !navigator.userAgent.match( /Chrome\// ); | ||
var isEDGE = navigator.userAgent.match( /Edge\/12/ ); | ||
if ( isSafari || isEDGE ) | ||
// We don't want to check for Google's extension hack on these | ||
// platforms, as they will cause trouble (popups, etc) | ||
return notSupported( ); | ||
if ( location.protocol === 'http:' ) | ||
// U2F isn't supported over http, only https | ||
return notSupported( ); | ||
// Test for google extension support | ||
chromeApi.isSupported( function( ok ) | ||
{ | ||
if ( ok ) | ||
resolve( { u2f: chromeApi, native: false } ); | ||
else | ||
notSupported( ); | ||
} ); | ||
} ); | ||
return _backend; | ||
} | ||
function API( Promise ) | ||
@@ -19,3 +61,4 @@ { | ||
sign : sign.bind( Promise ), | ||
ErrorCodes : API.ErrorCodes | ||
ErrorCodes : API.ErrorCodes, | ||
ErrorNames : API.ErrorNames | ||
}; | ||
@@ -25,30 +68,24 @@ } | ||
API.ErrorCodes = { | ||
CANCELED: -1 | ||
CANCELLED: -1, | ||
OK: 0, | ||
OTHER_ERROR: 1, | ||
BAD_REQUEST: 2, | ||
CONFIGURATION_UNSUPPORTED: 3, | ||
DEVICE_INELIGIBLE: 4, | ||
TIMEOUT: 5 | ||
}; | ||
var errorMap = { | ||
'-1': 'CANCELED' | ||
API.ErrorNames = { | ||
"-1": "CANCELLED", | ||
"0": "OK", | ||
"1": "OTHER_ERROR", | ||
"2": "BAD_REQUEST", | ||
"3": "CONFIGURATION_UNSUPPORTED", | ||
"4": "DEVICE_INELIGIBLE", | ||
"5": "TIMEOUT" | ||
}; | ||
var backendErrorCodes = hasNativeSupport ? _u2f : chromeApi.ErrorCodes; | ||
( | ||
hasNativeSupport | ||
? [ | ||
'BAD_REQUEST', | ||
'CONFIGURATION_UNSUPPORTED', | ||
'DEVICE_INELIGIBLE', | ||
'OK', | ||
'OTHER_ERROR', | ||
'TIMEOUT', | ||
] | ||
: Object.keys( chromeApi.ErrorCodes ) | ||
) | ||
.forEach( function( key ) { | ||
API.ErrorCodes[ key ] = backendErrorCodes[ key ]; | ||
errorMap[ '' + backendErrorCodes[ key ] ] = key; | ||
} ); | ||
function makeError( msg, err ) | ||
{ | ||
var code = err != null ? err.errorCode : 1; // Default to OTHER_ERROR | ||
var type = errorMap[ '' + code ]; | ||
var type = API.ErrorNames[ '' + code ]; | ||
var error = new Error( msg ); | ||
@@ -62,3 +99,3 @@ error.metaData = { | ||
function defer( Promise, fun ) | ||
function deferPromise( Promise, promise ) | ||
{ | ||
@@ -69,10 +106,3 @@ var ret = { }; | ||
ret.reject = reject; | ||
try | ||
{ | ||
fun && fun( resolve, reject ); | ||
} | ||
catch ( err ) | ||
{ | ||
reject( err ); | ||
} | ||
promise.then( resolve, reject ); | ||
} ); | ||
@@ -86,6 +116,10 @@ /** | ||
{ | ||
if ( disconnect && !hasNativeSupport ) | ||
chromeApi.disconnect( ); | ||
getBackend( Promise ) | ||
.then( function( backend ) | ||
{ | ||
if ( disconnect && !backend.native ) | ||
backend.u2f.disconnect( ); | ||
ret.reject( makeError( msg, { errorCode: -1 } ) ); | ||
ret.reject( makeError( msg, { errorCode: -1 } ) ); | ||
} ); | ||
}; | ||
@@ -95,25 +129,36 @@ return ret; | ||
function isSupported( ignorePreconditions /* = false */ ) | ||
function defer( Promise, fun ) | ||
{ | ||
return deferPromise( Promise, new Promise( function( resolve, reject ) | ||
{ | ||
try | ||
{ | ||
fun && fun( resolve, reject ); | ||
} | ||
catch ( err ) | ||
{ | ||
reject( err ); | ||
} | ||
} ) ); | ||
} | ||
function isSupported( ) | ||
{ | ||
var Promise = this; | ||
if ( hasNativeSupport ) | ||
return Promise.resolve( true ); | ||
return getBackend( Promise ) | ||
.then( function( backend ) | ||
{ | ||
return !!backend.u2f; | ||
} ); | ||
} | ||
var isSafari = navigator.userAgent.match( /Safari\// ) | ||
&& !navigator.userAgent.match( /Chrome\// ); | ||
var isEDGE = navigator.userAgent.match( /Edge\/12/ ); | ||
if ( isSafari || isEDGE ) | ||
return Promise.resolve( false ); | ||
if ( !ignorePreconditions ) | ||
function _ensureSupport( backend ) | ||
{ | ||
if ( !backend.u2f ) | ||
{ | ||
if ( location.protocol === 'http:' ) | ||
// U2F isn't supported over http, only https | ||
return Promise.resolve( false ); | ||
throw new Error( "U2F isn't supported over http, only https" ); | ||
throw new Error( "U2F not supported" ); | ||
} | ||
return defer( Promise, chromeApi.isSupported ).promise; | ||
} | ||
@@ -125,11 +170,4 @@ | ||
return isSupported.call( Promise ) | ||
.then( function( value ) { | ||
if ( !value ) | ||
{ | ||
if ( location.protocol === 'http:' ) | ||
throw new Error( "U2F isn't supported over http, only https" ); | ||
throw new Error( "U2F not supported" ); | ||
} | ||
} ); | ||
return getBackend( Promise ) | ||
.then( _ensureSupport ); | ||
} | ||
@@ -153,35 +191,45 @@ | ||
return defer( Promise, function( resolve, reject ) | ||
return deferPromise( Promise, getBackend( Promise ) | ||
.then( function( backend ) | ||
{ | ||
if ( hasNativeSupport ) | ||
_ensureSupport( backend ); | ||
var native = backend.native; | ||
var u2f = backend.u2f; | ||
return new Promise( function( resolve, reject ) | ||
{ | ||
function cb( response ) | ||
if ( native ) | ||
{ | ||
if ( response.errorCode ) | ||
reject( makeError( "Registration failed", response ) ); | ||
else | ||
function cb( response ) | ||
{ | ||
delete response.errorCode; | ||
resolve( response ); | ||
if ( response.errorCode ) | ||
reject( makeError( "Registration failed", response ) ); | ||
else | ||
{ | ||
delete response.errorCode; | ||
resolve( response ); | ||
} | ||
} | ||
} | ||
var appId = registerRequests[ 0 ].appId; | ||
var appId = registerRequests[ 0 ].appId; | ||
_u2f.register( appId, registerRequests, signRequests, cb, timeout ); | ||
} | ||
else | ||
{ | ||
function cb( err, response ) | ||
u2f.register( | ||
appId, registerRequests, signRequests, cb, timeout ); | ||
} | ||
else | ||
{ | ||
if ( err ) | ||
reject( err ); | ||
else if ( response.errorCode ) | ||
reject( makeError( "Registration failed", response ) ); | ||
else | ||
resolve( response ); | ||
function cb( err, response ) | ||
{ | ||
if ( err ) | ||
reject( err ); | ||
else if ( response.errorCode ) | ||
reject( makeError( "Registration failed", response ) ); | ||
else | ||
resolve( response ); | ||
} | ||
u2f.register( registerRequests, signRequests, cb, timeout ); | ||
} | ||
chromeApi.register( registerRequests, signRequests, cb, timeout ); | ||
} | ||
} ).promise; | ||
} ); | ||
} ) ).promise; | ||
} | ||
@@ -196,37 +244,46 @@ | ||
return defer( Promise, function( resolve, reject ) | ||
return deferPromise( Promise, getBackend( Promise ) | ||
.then( function( backend ) | ||
{ | ||
if ( hasNativeSupport ) | ||
_ensureSupport( backend ); | ||
var native = backend.native; | ||
var u2f = backend.u2f; | ||
return new Promise( function( resolve, reject ) | ||
{ | ||
function cb( response ) | ||
if ( native ) | ||
{ | ||
if ( response.errorCode ) | ||
reject( makeError( "Sign failed", response ) ); | ||
else | ||
function cb( response ) | ||
{ | ||
delete response.errorCode; | ||
resolve( response ); | ||
if ( response.errorCode ) | ||
reject( makeError( "Sign failed", response ) ); | ||
else | ||
{ | ||
delete response.errorCode; | ||
resolve( response ); | ||
} | ||
} | ||
} | ||
var appId = signRequests[ 0 ].appId; | ||
var challenge = signRequests[ 0 ].challenge; | ||
var appId = signRequests[ 0 ].appId; | ||
var challenge = signRequests[ 0 ].challenge; | ||
_u2f.sign( appId, challenge, signRequests, cb, timeout ); | ||
} | ||
else | ||
{ | ||
function cb( err, response ) | ||
u2f.sign( appId, challenge, signRequests, cb, timeout ); | ||
} | ||
else | ||
{ | ||
if ( err ) | ||
reject( err ); | ||
else if ( response.errorCode ) | ||
reject( makeError( "Sign failed", response ) ); | ||
else | ||
resolve( response ); | ||
function cb( err, response ) | ||
{ | ||
if ( err ) | ||
reject( err ); | ||
else if ( response.errorCode ) | ||
reject( makeError( "Sign failed", response ) ); | ||
else | ||
resolve( response ); | ||
} | ||
u2f.sign( signRequests, cb, timeout ); | ||
} | ||
chromeApi.sign( signRequests, cb, timeout ); | ||
} | ||
} ).promise; | ||
} ); | ||
} ) ).promise; | ||
} | ||
@@ -233,0 +290,0 @@ |
@@ -5,3 +5,3 @@ { | ||
"license": "MIT", | ||
"version": "0.1.3", | ||
"version": "0.2.0", | ||
"author": "Gustaf Räntilä <g.rantila@gmail.com>", | ||
@@ -8,0 +8,0 @@ "repository": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
24095
656