Skip to content

Commit e7b71ea

Browse files
Update lib/ with logout request pr
1 parent e982648 commit e7b71ea

1 file changed

Lines changed: 105 additions & 0 deletions

File tree

lib/RelyingParty.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ var AuthenticationRequest = require('./AuthenticationRequest');
2929
var AuthenticationResponse = require('./AuthenticationResponse');
3030
var RelyingPartySchema = require('./RelyingPartySchema');
3131
var onHttpError = require('./onHttpError');
32+
var FormUrlEncoded = require('./FormUrlEncoded');
3233

3334
/**
3435
* RelyingParty
@@ -263,9 +264,113 @@ var RelyingParty = function (_JSONDocument) {
263264
}
264265
}
265266

267+
/**
268+
* logoutRequest
269+
*
270+
* Composes and returns the logout request URI, based on the OP's
271+
* `end_session_endpoint`, with appropriate parameters.
272+
*
273+
* Note: Calling client code has the responsibility to clear the local
274+
* session state (for example, by calling `rp.clearSession()`). In addition,
275+
* some IdPs (such as Google) may not provide an `end_session_endpoint`,
276+
* in which case, this method will return null.
277+
*
278+
* @see https://openid.net/specs/openid-connect-session-1_0.html#RPLogout
279+
*
280+
* @throws {Error} If provider config is not initialized
281+
*
282+
* @throws {Error} If `post_logout_redirect_uri` was provided without a
283+
* corresponding `id_token_hint`
284+
*
285+
* @param [options={}] {object}
286+
*
287+
* @param [options.id_token_hint] {string} RECOMMENDED.
288+
* Previously issued ID Token passed to the logout endpoint as
289+
* a hint about the End-User's current authenticated session with the
290+
* Client. This is used as an indication of the identity of the End-User
291+
* that the RP is requesting be logged out by the OP. The OP *need not* be
292+
* listed as an audience of the ID Token when it is used as an
293+
* `id_token_hint` value.
294+
*
295+
* @param [options.post_logout_redirect_uri] {string} OPTIONAL. URL to which
296+
* the RP is requesting that the End-User's User Agent be redirected after
297+
* a logout has been performed. The value MUST have been previously
298+
* registered with the OP, either using the `post_logout_redirect_uris`
299+
* Registration parameter or via another mechanism. If supplied, the OP
300+
* SHOULD honor this request following the logout.
301+
*
302+
* Note: The requirement to validate the uri for previous registration means
303+
* that, in practice, the `id_token_hint` is REQUIRED if
304+
* `post_logout_redirect_uri` is used. Otherwise, the OP has no way to get
305+
* the `client_id` to load the saved client registration, to validate the
306+
* uri. The only way it can get it is by decoding the `id_token_hint`.
307+
*
308+
* @param [options.state] {string} OPTIONAL. Opaque value used by the RP to
309+
* maintain state between the logout request and the callback to the
310+
* endpoint specified by the `post_logout_redirect_uri` query parameter. If
311+
* included in the logout request, the OP passes this value back to the RP
312+
* using the `state` query parameter when redirecting the User Agent back to
313+
* the RP.
314+
*
315+
* TODO: In the future, consider adding `response_mode` param, for the OP to
316+
* determine how to return the `state` back the RP.
317+
* @see http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#ResponseModes
318+
*
319+
* TODO: Handle special cases for popular providers (Google, MSFT)
320+
*
321+
* @returns {string|null} Logout uri (or null if no end_session_endpoint was
322+
* provided in the IdP config)
323+
*/
324+
325+
}, {
326+
key: 'logoutRequest',
327+
value: function logoutRequest() {
328+
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
329+
var id_token_hint = options.id_token_hint,
330+
post_logout_redirect_uri = options.post_logout_redirect_uri,
331+
state = options.state;
332+
333+
var configuration = void 0;
334+
335+
assert(this.provider, 'OpenID Configuration is not initialized');
336+
configuration = this.provider.configuration;
337+
assert(configuration, 'OpenID Configuration is not initialized');
338+
339+
if (!configuration.end_session_endpoint) {
340+
console.log('OpenId Configuration for ' + (configuration.issuer + ' is missing end_session_endpoint'));
341+
return null;
342+
}
343+
344+
if (post_logout_redirect_uri && !id_token_hint) {
345+
throw new Error('id_token_hint is required when using post_logout_redirect_uri');
346+
}
347+
348+
var params = {};
349+
350+
if (id_token_hint) {
351+
params.id_token_hint = id_token_hint;
352+
}
353+
if (post_logout_redirect_uri) {
354+
params.post_logout_redirect_uri = post_logout_redirect_uri;
355+
}
356+
if (state) {
357+
params.state = state;
358+
}
359+
360+
var url = new URL(configuration.end_session_endpoint);
361+
url.search = FormUrlEncoded.encode(params);
362+
363+
return url.href;
364+
}
365+
266366
/**
267367
* Logout
268368
*
369+
* @deprecated
370+
*
371+
* TODO: Add deprecation warnings, then remove. Client code should
372+
* use `logoutRequest()` instead
373+
*
269374
* @returns {Promise}
270375
*/
271376

0 commit comments

Comments
 (0)