changed how grants are saved and how tokens are created for other clients
This commit is contained in:
parent
1ca6f0a324
commit
28dbf9ab23
|
@ -78,7 +78,7 @@
|
||||||
, uri: {
|
, uri: {
|
||||||
normalize: function (uri) {
|
normalize: function (uri) {
|
||||||
if ('string' !== typeof uri) {
|
if ('string' !== typeof uri) {
|
||||||
console.error((new Error('stack')).stack);
|
throw new Error("attempted to normalize non-string URI: "+JSON.stringify(uri));
|
||||||
}
|
}
|
||||||
// tested with
|
// tested with
|
||||||
// example.com
|
// example.com
|
||||||
|
@ -94,7 +94,7 @@
|
||||||
, url: {
|
, url: {
|
||||||
normalize: function (url) {
|
normalize: function (url) {
|
||||||
if ('string' !== typeof url) {
|
if ('string' !== typeof url) {
|
||||||
console.error((new Error('stack')).stack);
|
throw new Error("attempted to normalize non-string URL: "+JSON.stringify(url));
|
||||||
}
|
}
|
||||||
// tested with
|
// tested with
|
||||||
// example.com
|
// example.com
|
||||||
|
|
141
oauth3.issuer.js
141
oauth3.issuer.js
|
@ -102,8 +102,6 @@ OAUTH3.urls.resourceOwnerPassword = function (directive, opts) {
|
||||||
// , "username": "<<username>>", "password": "password" }
|
// , "username": "<<username>>", "password": "password" }
|
||||||
//
|
//
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
var type = 'access_token';
|
|
||||||
var grantType = 'password';
|
|
||||||
|
|
||||||
if (!opts.password) {
|
if (!opts.password) {
|
||||||
if (opts.otp) {
|
if (opts.otp) {
|
||||||
|
@ -112,16 +110,13 @@ OAUTH3.urls.resourceOwnerPassword = function (directive, opts) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var scope = opts.scope || directive.authn_scope;
|
var args = directive.access_token;
|
||||||
var clientAgreeTos = 'oauth3.org/tos/draft'; // opts.clientAgreeTos || opts.client_agree_tos;
|
|
||||||
var clientUri = opts.client_uri;
|
|
||||||
var args = directive[type];
|
|
||||||
var otpCode = opts.otp || opts.otpCode || opts.otp_code || opts.otpToken || opts.otp_token || undefined;
|
var otpCode = opts.otp || opts.otpCode || opts.otp_code || opts.otpToken || opts.otp_token || undefined;
|
||||||
// TODO require user agent
|
// TODO require user agent
|
||||||
var params = {
|
var params = {
|
||||||
client_id: opts.client_id || opts.client_uri
|
client_id: opts.client_id || opts.client_uri
|
||||||
, client_uri: opts.client_uri
|
, client_uri: opts.client_uri
|
||||||
, grant_type: grantType
|
, grant_type: 'password'
|
||||||
, username: opts.username
|
, username: opts.username
|
||||||
, password: opts.password || otpCode || undefined
|
, password: opts.password || otpCode || undefined
|
||||||
, totp: opts.totp || opts.totpToken || opts.totp_token || undefined
|
, totp: opts.totp || opts.totpToken || opts.totp_token || undefined
|
||||||
|
@ -136,23 +131,21 @@ OAUTH3.urls.resourceOwnerPassword = function (directive, opts) {
|
||||||
//, "jwt": opts.jwt // TODO sign a proof with a previously loaded public_key
|
//, "jwt": opts.jwt // TODO sign a proof with a previously loaded public_key
|
||||||
, debug: opts.debug || undefined
|
, debug: opts.debug || undefined
|
||||||
};
|
};
|
||||||
var uri = args.url;
|
|
||||||
var body;
|
|
||||||
if (opts.totp) {
|
|
||||||
params.totp = opts.totp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clientUri) {
|
if (opts.client_uri) {
|
||||||
params.clientAgreeTos = clientAgreeTos;
|
params.clientAgreeTos = 'oauth3.org/tos/draft'; // opts.clientAgreeTos || opts.client_agree_tos;
|
||||||
if (!clientAgreeTos) {
|
if (!params.clientAgreeTos) {
|
||||||
throw new Error('Developer Error: missing clientAgreeTos uri');
|
throw new Error('Developer Error: missing clientAgreeTos uri');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var scope = opts.scope || directive.authn_scope;
|
||||||
if (scope) {
|
if (scope) {
|
||||||
params.scope = OAUTH3.scope.stringify(scope);
|
params.scope = OAUTH3.scope.stringify(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var uri = args.url;
|
||||||
|
var body;
|
||||||
if ('GET' === args.method.toUpperCase()) {
|
if ('GET' === args.method.toUpperCase()) {
|
||||||
uri += '?' + OAUTH3.query.stringify(params);
|
uri += '?' + OAUTH3.query.stringify(params);
|
||||||
} else {
|
} else {
|
||||||
|
@ -168,6 +161,10 @@ OAUTH3.urls.resourceOwnerPassword = function (directive, opts) {
|
||||||
OAUTH3.urls.grants = function (directive, opts) {
|
OAUTH3.urls.grants = function (directive, opts) {
|
||||||
// directive = { issuer, authorization_decision }
|
// directive = { issuer, authorization_decision }
|
||||||
// opts = { response_type, scopes{ granted, requested, pending, accepted } }
|
// opts = { response_type, scopes{ granted, requested, pending, accepted } }
|
||||||
|
var grantsDir = directive.grants;
|
||||||
|
if (!grantsDir) {
|
||||||
|
throw new Error("provider doesn't support grants");
|
||||||
|
}
|
||||||
|
|
||||||
if (!opts) {
|
if (!opts) {
|
||||||
throw new Error("You must supply a directive and an options object.");
|
throw new Error("You must supply a directive and an options object.");
|
||||||
|
@ -183,15 +180,18 @@ OAUTH3.urls.grants = function (directive, opts) {
|
||||||
}
|
}
|
||||||
if (!opts.method) {
|
if (!opts.method) {
|
||||||
console.warn("You should supply options.method as either 'GET', or 'POST'");
|
console.warn("You should supply options.method as either 'GET', or 'POST'");
|
||||||
opts.method = 'GET';
|
opts.method = grantsDir.method || 'GET';
|
||||||
}
|
}
|
||||||
if ('POST' === opts.method) {
|
if ('POST' === opts.method) {
|
||||||
if ('string' !== typeof opts.scope) {
|
if ('string' !== typeof opts.scope) {
|
||||||
throw new Error("You must supply options.scope as a comma-delimited string of scopes");
|
throw new Error("You must supply options.scope as a comma-delimited string of scopes");
|
||||||
}
|
}
|
||||||
|
if ('string' !== typeof opts.sub) {
|
||||||
|
console.log("provide 'sub' to urls.grants to specify the PPID for the client");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = OAUTH3.url.resolve(directive.api, directive.grants.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(/(: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')
|
||||||
;
|
;
|
||||||
|
@ -200,13 +200,13 @@ OAUTH3.urls.grants = function (directive, opts) {
|
||||||
, client_uri: opts.client_uri
|
, client_uri: opts.client_uri
|
||||||
, referrer: opts.referrer
|
, referrer: opts.referrer
|
||||||
, scope: opts.scope
|
, scope: opts.scope
|
||||||
|
, sub: opts.sub
|
||||||
};
|
};
|
||||||
|
|
||||||
var body;
|
var body;
|
||||||
if ('GET' === opts.method) {
|
if ('GET' === opts.method) {
|
||||||
url += '?' + OAUTH3.query.stringify(data);
|
url += '?' + OAUTH3.query.stringify(data);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
body = data;
|
body = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +217,50 @@ OAUTH3.urls.grants = function (directive, opts) {
|
||||||
, session: opts.session
|
, session: opts.session
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
OAUTH3.urls.clientToken = function (directive, opts) {
|
||||||
|
var tokenDir = directive.access_token;
|
||||||
|
if (!tokenDir) {
|
||||||
|
throw new Error("provider doesn't support getting access tokens");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opts) {
|
||||||
|
throw new Error("You must supply a directive and an options object.");
|
||||||
|
}
|
||||||
|
if (!(opts.azp || opts.client_id)) {
|
||||||
|
throw new Error("You must supply options.client_id.");
|
||||||
|
}
|
||||||
|
if (!opts.session) {
|
||||||
|
throw new Error("You must supply options.session.");
|
||||||
|
}
|
||||||
|
if (!opts.method) {
|
||||||
|
opts.method = tokenDir.method || 'POST';
|
||||||
|
}
|
||||||
|
|
||||||
|
var params = {
|
||||||
|
grant_type: 'issuer_token'
|
||||||
|
, client_id: opts.azp || opts.client_id
|
||||||
|
, azp: opts.azp || opts.client_id
|
||||||
|
, aud: opts.aud
|
||||||
|
, exp: opts.exp
|
||||||
|
, refresh_token: opts.refresh_token
|
||||||
|
, refresh_exp: opts.refresh_exp
|
||||||
|
};
|
||||||
|
|
||||||
|
var url = OAUTH3.url.resolve(directive.api, tokenDir.url);
|
||||||
|
var body;
|
||||||
|
if ('GET' === opts.method) {
|
||||||
|
url += '?' + OAUTH3.query.stringify(params);
|
||||||
|
} else {
|
||||||
|
body = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
method: opts.method
|
||||||
|
, url: url
|
||||||
|
, data: body
|
||||||
|
, session: opts.session
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
OAUTH3.authn = {};
|
OAUTH3.authn = {};
|
||||||
OAUTH3.authn.loginMeta = function (directive, opts) {
|
OAUTH3.authn.loginMeta = function (directive, opts) {
|
||||||
|
@ -340,34 +384,51 @@ OAUTH3.authz.redirectWithToken = function (providerUri, session, clientParams, s
|
||||||
if (!OAUTH3.url.checkRedirect(clientParams.client_uri, clientParams)) {
|
if (!OAUTH3.url.checkRedirect(clientParams.client_uri, clientParams)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if ('token' !== clientParams.response_type) {
|
||||||
|
var message;
|
||||||
|
if ('code' === clientParams.response_type) {
|
||||||
|
message = "Authorization Code Redirect NOT IMPLEMENTED";
|
||||||
|
} else {
|
||||||
|
message = "Authorization response type '"+clientParams.response_type+"' not supported";
|
||||||
|
}
|
||||||
|
window.alert(message);
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
|
||||||
scopes.new = scopes.new || [];
|
var prom;
|
||||||
|
if (scopes.new) {
|
||||||
if ('token' === clientParams.response_type) {
|
prom = OAUTH3.authz.grants(providerUri, {
|
||||||
// get token and redirect client-side
|
session: session
|
||||||
return OAUTH3.authz.grants(providerUri, {
|
, method: 'POST'
|
||||||
method: 'POST'
|
|
||||||
, client_id: clientParams.client_uri
|
, client_id: clientParams.client_uri
|
||||||
, client_uri: clientParams.client_uri
|
|
||||||
, scope: scopes.granted.concat(scopes.new).join(',')
|
|
||||||
, response_type: clientParams.response_type
|
|
||||||
, referrer: clientParams.referrer
|
, referrer: clientParams.referrer
|
||||||
, session: session
|
, scope: scopes.accepted.concat(scopes.new).join(',')
|
||||||
, debug: clientParams.debug
|
});
|
||||||
}).then(function (results) {
|
} else {
|
||||||
|
prom = OAUTH3.PromiseA.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return prom.then(function () {
|
||||||
|
return OAUTH3.discover(providerUri, { client_id: providerUri, debug: clientParams.debug });
|
||||||
|
}).then(function (directive) {
|
||||||
|
return OAUTH3.request(OAUTH3.urls.clientToken(directive, {
|
||||||
|
method: 'POST'
|
||||||
|
, session: session
|
||||||
|
, referrer: clientParams.referrer
|
||||||
|
, response_type: clientParams.response_type
|
||||||
|
, client_id: clientParams.client_uri
|
||||||
|
, azp: clientParams.client_uri
|
||||||
|
, aud: clientParams.aud
|
||||||
|
, exp: clientParams.exp
|
||||||
|
, refresh_token: clientParams.refresh_token
|
||||||
|
, refresh_exp: clientParams.refresh_exp
|
||||||
|
, debug: clientParams.debug
|
||||||
|
}));
|
||||||
|
}).then(function (results) {
|
||||||
// TODO limit refresh token to an expirable token
|
// TODO limit refresh token to an expirable token
|
||||||
// TODO inform client not to persist token
|
// TODO inform client not to persist token
|
||||||
OAUTH3.url.redirect(clientParams, scopes, results);
|
OAUTH3.url.redirect(clientParams, scopes, results.originalData || results.data);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
else if ('code' === clientParams.response_type) {
|
|
||||||
// get token and redirect server-side
|
|
||||||
// (requires insecure form post as per spec)
|
|
||||||
//OAUTH3.requests.authorizationDecision();
|
|
||||||
window.alert("Authorization Code Redirect NOT IMPLEMENTED");
|
|
||||||
throw new Error("Authorization Code Redirect NOT IMPLEMENTED");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
OAUTH3.requests = {};
|
OAUTH3.requests = {};
|
||||||
|
|
Loading…
Reference in New Issue