Merge branch 'v1.2'
This commit is contained in:
commit
e6fa1d5314
|
@ -706,7 +706,7 @@
|
||||||
*/
|
*/
|
||||||
return OAUTH3._browser.request(preq, opts);
|
return OAUTH3._browser.request(preq, opts);
|
||||||
}
|
}
|
||||||
, implicitGrant: function(directives, opts) {
|
, implicitGrant: function (directives, opts) {
|
||||||
var promise;
|
var promise;
|
||||||
var providerUri = directives.azp || directives.issuer || directives;
|
var providerUri = directives.azp || directives.issuer || directives;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
OAUTH3.crypto.core = require('./oauth3.node.crypto');
|
OAUTH3.crypto.core = require('./oauth3.node.crypto');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
OAUTH3.crypto.core = {};
|
OAUTH3.crypto.core = {};
|
||||||
|
OAUTH3.crypto.core.ready = false;
|
||||||
|
var finishBeforeReady = [];
|
||||||
|
var deferedCalls = [];
|
||||||
|
|
||||||
// We don't currently have a fallback method for this function, so we assign
|
// We don't currently have a fallback method for this function, so we assign
|
||||||
// it directly to the core object instead of the webCrypto object.
|
// it directly to the core object instead of the webCrypto object.
|
||||||
|
@ -17,10 +20,31 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
var webCrypto = {};
|
var webCrypto = {};
|
||||||
|
|
||||||
|
var deferCryptoCall = function(name) {
|
||||||
|
return function() {
|
||||||
|
var args = arguments;
|
||||||
|
return new OAUTH3.PromiseA(function(resolve, reject) {
|
||||||
|
deferedCalls.push(function(){
|
||||||
|
try {
|
||||||
|
webCrypto[name].apply(webCrypto, args)
|
||||||
|
.then(function(result){
|
||||||
|
resolve(result);
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
OAUTH3.crypto.core.sha256 = deferCryptoCall("sha256");
|
||||||
webCrypto.sha256 = function (buf) {
|
webCrypto.sha256 = function (buf) {
|
||||||
return OAUTH3._browser.window.crypto.subtle.digest({name: 'SHA-256'}, buf);
|
return OAUTH3._browser.window.crypto.subtle.digest({name: 'SHA-256'}, buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
OAUTH3.crypto.core.pbkdf2 = deferCryptoCall("pbkdf2");
|
||||||
webCrypto.pbkdf2 = function (password, salt) {
|
webCrypto.pbkdf2 = function (password, salt) {
|
||||||
return OAUTH3._browser.window.crypto.subtle.importKey('raw', OAUTH3._binStr.binStrToBuffer(password), {name: 'PBKDF2'}, false, ['deriveKey'])
|
return OAUTH3._browser.window.crypto.subtle.importKey('raw', OAUTH3._binStr.binStrToBuffer(password), {name: 'PBKDF2'}, false, ['deriveKey'])
|
||||||
.then(function (key) {
|
.then(function (key) {
|
||||||
|
@ -32,12 +56,15 @@
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
OAUTH3.crypto.core.encrypt = deferCryptoCall("encrypt");
|
||||||
webCrypto.encrypt = function (rawKey, iv, data) {
|
webCrypto.encrypt = function (rawKey, iv, data) {
|
||||||
return OAUTH3._browser.window.crypto.subtle.importKey('raw', rawKey, {name: 'AES-GCM'}, false, ['encrypt'])
|
return OAUTH3._browser.window.crypto.subtle.importKey('raw', rawKey, {name: 'AES-GCM'}, false, ['encrypt'])
|
||||||
.then(function (key) {
|
.then(function (key) {
|
||||||
return OAUTH3._browser.window.crypto.subtle.encrypt({name: 'AES-GCM', iv: iv}, key, data);
|
return OAUTH3._browser.window.crypto.subtle.encrypt({name: 'AES-GCM', iv: iv}, key, data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
OAUTH3.crypto.core.decrypt = deferCryptoCall("decrypt");
|
||||||
webCrypto.decrypt = function (rawKey, iv, data) {
|
webCrypto.decrypt = function (rawKey, iv, data) {
|
||||||
return OAUTH3._browser.window.crypto.subtle.importKey('raw', rawKey, {name: 'AES-GCM'}, false, ['decrypt'])
|
return OAUTH3._browser.window.crypto.subtle.importKey('raw', rawKey, {name: 'AES-GCM'}, false, ['decrypt'])
|
||||||
.then(function (key) {
|
.then(function (key) {
|
||||||
|
@ -45,6 +72,7 @@
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
OAUTH3.crypto.core.genEcdsaKeyPair = deferCryptoCall("genEcdsaKeyPair");
|
||||||
webCrypto.genEcdsaKeyPair = function () {
|
webCrypto.genEcdsaKeyPair = function () {
|
||||||
return OAUTH3._browser.window.crypto.subtle.generateKey({name: 'ECDSA', namedCurve: 'P-256'}, true, ['sign', 'verify'])
|
return OAUTH3._browser.window.crypto.subtle.generateKey({name: 'ECDSA', namedCurve: 'P-256'}, true, ['sign', 'verify'])
|
||||||
.then(function (keyPair) {
|
.then(function (keyPair) {
|
||||||
|
@ -57,6 +85,7 @@
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
OAUTH3.crypto.core.sign = deferCryptoCall("sign");
|
||||||
webCrypto.sign = function (jwk, msg) {
|
webCrypto.sign = function (jwk, msg) {
|
||||||
return OAUTH3._browser.window.crypto.subtle.importKey('jwk', jwk, {name: 'ECDSA', namedCurve: jwk.crv}, false, ['sign'])
|
return OAUTH3._browser.window.crypto.subtle.importKey('jwk', jwk, {name: 'ECDSA', namedCurve: jwk.crv}, false, ['sign'])
|
||||||
.then(function (key) {
|
.then(function (key) {
|
||||||
|
@ -66,6 +95,8 @@
|
||||||
return new Uint8Array(sig);
|
return new Uint8Array(sig);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
OAUTH3.crypto.core.verify = deferCryptoCall("verify");
|
||||||
webCrypto.verify = function (jwk, msg, signature) {
|
webCrypto.verify = function (jwk, msg, signature) {
|
||||||
// If the JWK has properties that should only exist on the private key or is missing
|
// If the JWK has properties that should only exist on the private key or is missing
|
||||||
// "verify" in the key_ops, importing in as a public key won't work.
|
// "verify" in the key_ops, importing in as a public key won't work.
|
||||||
|
@ -103,18 +134,19 @@
|
||||||
return prom;
|
return prom;
|
||||||
};
|
};
|
||||||
function checkException(name, func) {
|
function checkException(name, func) {
|
||||||
OAUTH3.PromiseA.resolve().then(func)
|
return OAUTH3.PromiseA.resolve().then(func)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
OAUTH3.crypto.core[name] = webCrypto[name];
|
OAUTH3.crypto.core[name] = webCrypto[name];
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
console.warn('error with WebCrypto', name, '- using fallback', err);
|
console.warn('error with WebCrypto', name, '- using fallback', err);
|
||||||
loadFallback().then(function () {
|
return loadFallback().then(function () {
|
||||||
OAUTH3.crypto.core[name] = OAUTH3_crypto_fallback[name];
|
OAUTH3.crypto.core[name] = OAUTH3_crypto_fallback[name];
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function checkResult(name, expected, func) {
|
function checkResult(name, expected, func) {
|
||||||
checkException(name, function () {
|
|
||||||
|
finishBeforeReady.push(checkException(name, function () {
|
||||||
return func()
|
return func()
|
||||||
.then(function (result) {
|
.then(function (result) {
|
||||||
if (typeof expected === typeof result) {
|
if (typeof expected === typeof result) {
|
||||||
|
@ -127,7 +159,7 @@
|
||||||
throw new Error("result ("+result+") doesn't match expectation ("+expected+")");
|
throw new Error("result ("+result+") doesn't match expectation ("+expected+")");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
var zeroBuf = new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);
|
var zeroBuf = new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);
|
||||||
|
@ -159,12 +191,20 @@
|
||||||
return webCrypto.verify(jwk, dataBuf, sig);
|
return webCrypto.verify(jwk, dataBuf, sig);
|
||||||
});
|
});
|
||||||
// The results of these functions are less predictable, so we can't check their return value.
|
// The results of these functions are less predictable, so we can't check their return value.
|
||||||
checkException('genEcdsaKeyPair', function () {
|
finishBeforeReady.push(checkException('genEcdsaKeyPair', function () {
|
||||||
return webCrypto.genEcdsaKeyPair();
|
return webCrypto.genEcdsaKeyPair();
|
||||||
});
|
}));
|
||||||
checkException('sign', function () {
|
finishBeforeReady.push(checkException('sign', function () {
|
||||||
return webCrypto.sign(jwk, dataBuf);
|
return webCrypto.sign(jwk, dataBuf);
|
||||||
});
|
}));
|
||||||
|
|
||||||
|
OAUTH3.PromiseA.all(finishBeforeReady)
|
||||||
|
.then(function(results) {
|
||||||
|
OAUTH3.crypto.core.ready = true;
|
||||||
|
deferedCalls.forEach(function(request) {
|
||||||
|
request();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
checkWebCrypto();
|
checkWebCrypto();
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,8 +192,9 @@ OAUTH3.urls.grants = function (directive, opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = OAUTH3.url.resolve(directive.api, grantsDir.url)
|
var url = OAUTH3.url.resolve(directive.api, grantsDir.url)
|
||||||
.replace(/(:azp|:client_id)/g, OAUTH3.uri.normalize(opts.client_id || opts.client_uri))
|
|
||||||
.replace(/(:sub|:account_id)/g, opts.session.token.sub || 'ISSUER:GRANT:TOKEN_SUB:UNDEFINED')
|
.replace(/(:sub|:account_id)/g, opts.session.token.sub || 'ISSUER:GRANT:TOKEN_SUB:UNDEFINED')
|
||||||
|
.replace(/(:azp|:client_id)/g, !opts.all && OAUTH3.uri.normalize(opts.client_id || opts.client_uri) || '')
|
||||||
|
.replace(/\/\/$/, '/') // if there's a double slash due to the sub not existing
|
||||||
;
|
;
|
||||||
var data = {
|
var data = {
|
||||||
client_id: opts.client_id
|
client_id: opts.client_id
|
||||||
|
@ -287,21 +288,25 @@ OAUTH3.urls.publishKey = function (directive, opts) {
|
||||||
, session: opts.session
|
, session: opts.session
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
OAUTH3.urls.credentialMeta = function (directive, opts) {
|
||||||
|
return OAUTH3.url.resolve(directive.api, directive.credential_meta.url)
|
||||||
|
.replace(':type', 'email')
|
||||||
|
.replace(':id', opts.email)
|
||||||
|
};
|
||||||
|
|
||||||
OAUTH3.authn = {};
|
OAUTH3.authn = {};
|
||||||
OAUTH3.authn.loginMeta = function (directive, opts) {
|
OAUTH3.authn.loginMeta = function (directive, opts) {
|
||||||
|
var url = OAUTH3.urls.credentialMeta(directive, opts);
|
||||||
return OAUTH3.request({
|
return OAUTH3.request({
|
||||||
method: directive.credential_meta.method || 'GET'
|
method: directive.credential_meta.method || 'GET'
|
||||||
// TODO lint urls
|
// TODO lint urls
|
||||||
// TODO client_uri
|
// TODO client_uri
|
||||||
, url: OAUTH3.url.resolve(directive.api, directive.credential_meta.url)
|
, url: url
|
||||||
.replace(':type', 'email')
|
|
||||||
.replace(':id', opts.email)
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
OAUTH3.authn.otp = function (directive, opts) {
|
OAUTH3.urls.otp = function (directive, opts) {
|
||||||
// TODO client_uri
|
// TODO client_uri
|
||||||
var preq = {
|
return {
|
||||||
method: directive.credential_otp.method || 'POST'
|
method: directive.credential_otp.method || 'POST'
|
||||||
, url: OAUTH3.url.resolve(directive.api, directive.credential_otp.url)
|
, url: OAUTH3.url.resolve(directive.api, directive.credential_otp.url)
|
||||||
, data: {
|
, data: {
|
||||||
|
@ -314,6 +319,9 @@ OAUTH3.authn.otp = function (directive, opts) {
|
||||||
, username: opts.email
|
, username: opts.email
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
OAUTH3.authn.otp = function (directive, opts) {
|
||||||
|
var preq = OAUTH3.urls.otp(directive, opts);
|
||||||
|
|
||||||
return OAUTH3.request(preq);
|
return OAUTH3.request(preq);
|
||||||
};
|
};
|
||||||
|
@ -425,7 +433,7 @@ OAUTH3.authz.grants = function (providerUri, opts) {
|
||||||
}
|
}
|
||||||
// the responses for GET and POST requests are now the same, so we should alway be able to
|
// the responses for GET and POST requests are now the same, so we should alway be able to
|
||||||
// use the response and save it the same way.
|
// use the response and save it the same way.
|
||||||
if ('GET' !== opts.method && 'POST' !== opts.method) {
|
if (opts.all || ('GET' !== opts.method && 'POST' !== opts.method)) {
|
||||||
return grants;
|
return grants;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue