updated how grants are retrieved
This commit is contained in:
parent
c38554a9dd
commit
1ca6f0a324
|
@ -168,9 +168,12 @@
|
|||
}
|
||||
}
|
||||
, scope: {
|
||||
stringify: function (scope) {
|
||||
parse: function (scope) {
|
||||
return (scope||'').split(/[+, ]+/g);
|
||||
}
|
||||
, stringify: function (scope) {
|
||||
if (Array.isArray(scope)) {
|
||||
scope = scope.join(' ');
|
||||
scope = scope.join(',');
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
|
|
213
oauth3.issuer.js
213
oauth3.issuer.js
|
@ -3,39 +3,6 @@
|
|||
|
||||
var OAUTH3 = exports.OAUTH3 = exports.OAUTH3 || require('./oauth3.core.js').OAUTH3;
|
||||
|
||||
OAUTH3.query.parse = function (search) {
|
||||
// parse a query or a hash
|
||||
if (-1 !== ['#', '?'].indexOf(search[0])) {
|
||||
search = search.substring(1);
|
||||
}
|
||||
// Solve for case of search within hash
|
||||
// example: #/authorization_dialog/?state=...&redirect_uri=...
|
||||
var queryIndex = search.indexOf('?');
|
||||
if (-1 !== queryIndex) {
|
||||
search = search.substr(queryIndex + 1);
|
||||
}
|
||||
|
||||
var args = search.split('&');
|
||||
var argsParsed = {};
|
||||
var i, arg, kvp, key, value;
|
||||
|
||||
for (i = 0; i < args.length; i += 1) {
|
||||
arg = args[i];
|
||||
if (-1 === arg.indexOf('=')) {
|
||||
argsParsed[decodeURIComponent(arg).trim()] = true;
|
||||
}
|
||||
else {
|
||||
kvp = arg.split('=');
|
||||
key = decodeURIComponent(kvp[0]).trim();
|
||||
value = decodeURIComponent(kvp[1]).trim();
|
||||
argsParsed[key] = value;
|
||||
}
|
||||
}
|
||||
return argsParsed;
|
||||
};
|
||||
OAUTH3.scope.parse = function (scope) {
|
||||
return (scope||'').split(/[, ]/g);
|
||||
};
|
||||
OAUTH3.url.parse = function (url) {
|
||||
// TODO browser
|
||||
// Node should replace this
|
||||
|
@ -58,8 +25,16 @@ OAUTH3.url._isRedirectHostSafe = function (referrerUrl, redirectUrl) {
|
|||
};
|
||||
OAUTH3.url.checkRedirect = function (client, query) {
|
||||
console.warn("[security] URL path checking not yet implemented");
|
||||
if (!query) {
|
||||
query = client;
|
||||
client = query.client_uri;
|
||||
}
|
||||
client = client.url || client;
|
||||
|
||||
var clientUrl = OAUTH3.url.normalize(client.url);
|
||||
// it doesn't matter who the referrer is as long as the destination
|
||||
// is an authorized destination for the client in question
|
||||
// (though it may not hurt to pass the referrer's info on to the client)
|
||||
var clientUrl = OAUTH3.url.normalize(client);
|
||||
var redirectUrl = OAUTH3.url.normalize(query.redirect_uri);
|
||||
|
||||
// General rule:
|
||||
|
@ -72,6 +47,18 @@ OAUTH3.url.checkRedirect = function (client, query) {
|
|||
return true;
|
||||
}
|
||||
|
||||
var callbackUrl = 'https://oauth3.org/docs/errors#E_REDIRECT_ATTACK?'+OAUTH3.query.stringify({
|
||||
'redirect_uri': redirectUrl
|
||||
, 'allowed_urls': clientUrl
|
||||
, 'client_id': client
|
||||
, 'referrer_uri': OAUTH3.uri.normalize(window.document.referrer)
|
||||
});
|
||||
if (query.debug) {
|
||||
console.log('Redirect Attack');
|
||||
console.log(query);
|
||||
window.alert("DEBUG MODE checkRedirect error encountered. Check the console.");
|
||||
}
|
||||
location.href = callbackUrl;
|
||||
return false;
|
||||
};
|
||||
OAUTH3.url.redirect = function (clientParams, grants, tokenOrError) {
|
||||
|
@ -195,14 +182,12 @@ OAUTH3.urls.grants = function (directive, opts) {
|
|||
console.warn("You should supply options.referrer");
|
||||
}
|
||||
if (!opts.method) {
|
||||
console.warn("You must supply options.method as either 'GET', or 'POST'");
|
||||
console.warn("You should supply options.method as either 'GET', or 'POST'");
|
||||
opts.method = 'GET';
|
||||
}
|
||||
if ('POST' === opts.method) {
|
||||
if ('string' !== typeof opts.scope) {
|
||||
console.warn("You should supply options.scope as a space-delimited string of scopes");
|
||||
}
|
||||
if (-1 === ['token', 'code'].indexOf(opts.response_type)) {
|
||||
throw new Error("You must supply options.response_type as 'token' or 'code'");
|
||||
throw new Error("You must supply options.scope as a comma-delimited string of scopes");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,12 +199,10 @@ OAUTH3.urls.grants = function (directive, opts) {
|
|||
client_id: opts.client_id
|
||||
, client_uri: opts.client_uri
|
||||
, referrer: opts.referrer
|
||||
, response_type: opts.response_type
|
||||
, scope: opts.scope
|
||||
, tenant_id: opts.tenant_id
|
||||
};
|
||||
var body;
|
||||
|
||||
var body;
|
||||
if ('GET' === opts.method) {
|
||||
url += '?' + OAUTH3.query.stringify(data);
|
||||
}
|
||||
|
@ -290,14 +273,13 @@ OAUTH3.authn.resourceOwnerPassword = function (directive, opts) {
|
|||
|
||||
OAUTH3.authz = {};
|
||||
OAUTH3.authz.scopes = function (providerUri, session, clientParams) {
|
||||
// OAuth3.requests.grants(providerUri, {}); // return list of grants
|
||||
// OAuth3.checkGrants(providerUri, {}); //
|
||||
var clientUri = OAUTH3.uri.normalize(clientParams.client_uri || OAUTH3._browser.window.document.referrer);
|
||||
var scope = clientParams.scope || '';
|
||||
var clientObj = clientParams;
|
||||
|
||||
if (!scope) {
|
||||
scope = 'oauth3_authn';
|
||||
var scope = clientParams.scope || 'oauth3_authn';
|
||||
if ('oauth3_authn' === scope) {
|
||||
// implicit ppid grant is automatic
|
||||
console.warn('[security] fix scope checking on backend so that we can do automatic grants');
|
||||
// TODO check user preference if implicit ppid grant is allowed
|
||||
//return generateToken(session, clientObj);
|
||||
}
|
||||
|
||||
return OAUTH3.authz.grants(providerUri, {
|
||||
|
@ -305,74 +287,30 @@ OAUTH3.authz.scopes = function (providerUri, session, clientParams) {
|
|||
, client_id: clientUri
|
||||
, client_uri: clientUri
|
||||
, session: session
|
||||
}).then(function (grantResults) {
|
||||
var grants;
|
||||
var grantedScopes;
|
||||
var grantedScopesMap;
|
||||
var pendingScopes;
|
||||
var acceptedScopes;
|
||||
var scopes = scope.split(/[+, ]/g);
|
||||
var callbackUrl;
|
||||
|
||||
// it doesn't matter who the referrer is as long as the destination
|
||||
// is an authorized destination for the client in question
|
||||
// (though it may not hurt to pass the referrer's info on to the client)
|
||||
if (!OAUTH3.url.checkRedirect(grantResults.client, clientObj)) {
|
||||
callbackUrl = 'https://oauth3.org/docs/errors#E_REDIRECT_ATTACK'
|
||||
+ '?redirect_uri=' + clientObj.redirect_uri
|
||||
+ '&allowed_urls=' + grantResults.client.url
|
||||
+ '&client_id=' + clientUri
|
||||
+ '&referrer_uri=' + OAUTH3.uri.normalize(window.document.referrer)
|
||||
;
|
||||
if (clientParams.debug) {
|
||||
console.log('grantResults Redirect Attack');
|
||||
console.log(grantResults);
|
||||
console.log(clientObj);
|
||||
window.alert("DEBUG MODE checkRedirect error encountered. Check the console.");
|
||||
}
|
||||
location.href = callbackUrl;
|
||||
return;
|
||||
}).then(function (results) {
|
||||
return results.grants;
|
||||
}, function (err) {
|
||||
if (!/no .*grants .*found/i.test(err.message)) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
if ('oauth3_authn' === scope) {
|
||||
// implicit ppid grant is automatic
|
||||
console.warn('[security] fix scope checking on backend so that we can do automatic grants');
|
||||
// TODO check user preference if implicit ppid grant is allowed
|
||||
//return generateToken(session, clientObj);
|
||||
}
|
||||
|
||||
grants = (grantResults).grants.filter(function (grant) {
|
||||
if (clientUri === (grant.azp || grant.oauth_client_id || grant.oauthClientId)) {
|
||||
return true;
|
||||
return [];
|
||||
}).then(function (granted) {
|
||||
var requested = OAUTH3.scope.parse(scope);
|
||||
var accepted = [];
|
||||
var pending = [];
|
||||
requested.forEach(function (scp) {
|
||||
if (granted.indexOf(scp) < 0) {
|
||||
pending.push(scp);
|
||||
} else {
|
||||
accepted.push(scp);
|
||||
}
|
||||
});
|
||||
|
||||
grantedScopesMap = {};
|
||||
acceptedScopes = [];
|
||||
pendingScopes = scopes.filter(function (requestedScope) {
|
||||
return grants.every(function (grant) {
|
||||
if (!grant.scope) {
|
||||
grant.scope = 'oauth3_authn';
|
||||
}
|
||||
var gscopes = grant.scope.split(/[+, ]/g);
|
||||
gscopes.forEach(function (s) { grantedScopesMap[s] = true; });
|
||||
if (-1 !== gscopes.indexOf(requestedScope)) {
|
||||
// already accepted in the past
|
||||
acceptedScopes.push(requestedScope);
|
||||
}
|
||||
else {
|
||||
// true, is pending
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
grantedScopes = Object.keys(grantedScopesMap);
|
||||
|
||||
return {
|
||||
pending: pendingScopes // not yet accepted
|
||||
, granted: grantedScopes // all granted, ever
|
||||
, requested: scopes // all requested, now
|
||||
, accepted: acceptedScopes // granted (ever) and requested (now)
|
||||
requested: requested // all requested, now
|
||||
, granted: granted // all granted, ever
|
||||
, accepted: accepted // intersection of granted (ever) and requested (now)
|
||||
, pending: pending // not yet accepted
|
||||
};
|
||||
});
|
||||
};
|
||||
|
@ -381,34 +319,27 @@ OAUTH3.authz.grants = function (providerUri, opts) {
|
|||
client_id: providerUri
|
||||
, debug: opts.debug
|
||||
}).then(function (directive) {
|
||||
return OAUTH3.request(OAUTH3.urls.grants(directive, opts), opts);
|
||||
}).then(function (grantsResult) {
|
||||
var grants = grantsResult.originalData || grantsResult.data;
|
||||
if (grants.error) {
|
||||
return OAUTH3.PromiseA.reject(OAUTH3.error.parse(providerUri, grants));
|
||||
}
|
||||
if ('POST' === opts.method) {
|
||||
return grants;
|
||||
}
|
||||
|
||||
return OAUTH3.request(OAUTH3.urls.grants(directive, opts), opts).then(function (grantsResult) {
|
||||
if ('POST' === opts.method) {
|
||||
// TODO this is clientToken
|
||||
return grantsResult.originalData || grantsResult.data;
|
||||
}
|
||||
|
||||
var grants = grantsResult.originalData || grantsResult.data;
|
||||
// TODO
|
||||
if (grants.error) {
|
||||
return OAUTH3.PromiseA.reject(OAUTH3.error.parse(providerUri, grants));
|
||||
}
|
||||
|
||||
OAUTH3.hooks.grants.set(opts.client_id + '-client', grants.client);
|
||||
grants.grants.forEach(function (grant) {
|
||||
var clientId = grant.client_id || grant.oauth_client_id || grant.oauthClientId;
|
||||
// TODO should save as an array
|
||||
OAUTH3.hooks.grants.set(clientId, [ grant ]);
|
||||
});
|
||||
|
||||
return {
|
||||
client: OAUTH3.hooks.grants.get(opts.client_id + '-client')
|
||||
, grants: OAUTH3.hooks.grants.get(opts.client_id) || []
|
||||
};
|
||||
});
|
||||
OAUTH3.hooks.grants.set(grants.sub+'/'+grants.azp, grants.scope);
|
||||
return {
|
||||
client: grants.azp
|
||||
, grants: OAUTH3.scope.parse(grants.scope)
|
||||
};
|
||||
});
|
||||
};
|
||||
OAUTH3.authz.redirectWithToken = function (providerUri, session, clientParams, scopes) {
|
||||
if (!OAUTH3.url.checkRedirect(clientParams.client_uri, clientParams)) {
|
||||
return;
|
||||
}
|
||||
|
||||
scopes.new = scopes.new || [];
|
||||
|
||||
|
@ -427,15 +358,6 @@ OAUTH3.authz.redirectWithToken = function (providerUri, session, clientParams, s
|
|||
|
||||
// TODO limit refresh token to an expirable token
|
||||
// TODO inform client not to persist token
|
||||
/*
|
||||
if (clientParams.dnsTxt) {
|
||||
Object.keys(results).forEach(function (key) {
|
||||
if (/refresh/.test(key)) {
|
||||
results[key] = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
*/
|
||||
OAUTH3.url.redirect(clientParams, scopes, results);
|
||||
});
|
||||
}
|
||||
|
@ -447,6 +369,7 @@ OAUTH3.authz.redirectWithToken = function (providerUri, session, clientParams, s
|
|||
throw new Error("Authorization Code Redirect NOT IMPLEMENTED");
|
||||
}
|
||||
};
|
||||
|
||||
OAUTH3.requests = {};
|
||||
OAUTH3.requests.accounts = {};
|
||||
OAUTH3.requests.accounts.update = function (directive, session, opts) {
|
||||
|
|
Loading…
Reference in New Issue