This repository has been archived by the owner on Feb 25, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(RPInitiatedLogoutRequest): First draft of RP Initiated Logout Re…
…quest handling
- Loading branch information
1 parent
6fa15ea
commit 4e1c115
Showing
5 changed files
with
207 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
'use strict' | ||
|
||
/** | ||
* Dependencies | ||
* @ignore | ||
*/ | ||
const qs = require('qs') | ||
const BaseRequest = require('./BaseRequest') | ||
|
||
class RPInitiatedLogoutRequest extends BaseRequest { | ||
/** | ||
* RP Initiated Logout Request Handler | ||
* | ||
* @see https://openid.net/specs/openid-connect-session-1_0.html#RPLogout | ||
* @see https://openid.net/specs/openid-connect-frontchannel-1_0.html#RPInitiated | ||
* @see https://openid.net/specs/openid-connect-backchannel-1_0.html#RPInitiated | ||
* | ||
* @param req {HTTPRequest} | ||
* @param res {HTTPResponse} | ||
* @param provider {Provider} | ||
* @returns {Promise} | ||
*/ | ||
static handle (req, res, provider) { | ||
let { host } = provider | ||
let request = new RPInitiatedLogoutRequest(req, res, provider) | ||
|
||
Promise | ||
.resolve(request) | ||
.then(request.validate) | ||
|
||
// From: https://openid.net/specs/openid-connect-session-1_0.html#RPLogout | ||
// At the logout endpoint, the OP SHOULD ask the End-User whether they want | ||
// to log out of the OP as well. If the End-User says "yes", then the OP | ||
// MUST log out the End-User. | ||
.then(host.logout) | ||
|
||
.then(request.redirectOrRespond) | ||
.catch(request.internalServerError) | ||
} | ||
|
||
/** | ||
* Constructor | ||
* | ||
* Session spec defines the following params to the RP Initiated Logout request: | ||
* - `id_token_hint` | ||
* - `post_logout_redirect_uri` | ||
* - `state` | ||
* | ||
* @param req {HTTPRequest} | ||
* @param res {HTTPResponse} | ||
* @param provider {Provider} | ||
*/ | ||
constructor (req, res, provider) { | ||
super(req, res, provider) | ||
this.params = RPInitiatedLogoutRequest.getParams(this) | ||
} | ||
|
||
/** | ||
* Validate | ||
* | ||
* @see https://openid.net/specs/openid-connect-session-1_0.html#RPLogout | ||
* | ||
* @param request {RPInitiatedLogoutRequest} | ||
*/ | ||
validate (request) { | ||
/** | ||
* `state` parameter - no validation need it. Will be passed back to the RP | ||
* in the `redirectToRP()` step. | ||
*/ | ||
|
||
/** | ||
* TODO: Validate `id_token_hint` (validate as ID Token *except* for `aud`) | ||
* | ||
* RECOMMENDED. Previously issued ID Token passed to the logout endpoint as | ||
* a hint about the End-User's current authenticated session with the Client. | ||
* This is used as an indication of the identity of the End-User that the RP | ||
* is requesting be logged out by the OP. The OP *need not* be listed as an | ||
* audience of the ID Token when it is used as an `id_token_hint` value. | ||
*/ | ||
|
||
/** | ||
* TODO: Validate that `post_logout_redirect_uri` has been registered | ||
* | ||
* The value MUST have been previously registered with the OP, either using | ||
* the `post_logout_redirect_uris` Registration parameter | ||
* or via another mechanism. | ||
* | ||
* Question: what's this about 'another mechanism'? | ||
*/ | ||
} | ||
|
||
/** | ||
* Redirect to RP or Respond | ||
* | ||
* In some cases, the RP will request that the End-User's User Agent to be | ||
* redirected back to the RP after a logout has been performed. Post-logout | ||
* redirection is only done when the logout is RP-initiated, in which case the | ||
* redirection target is the `post_logout_redirect_uri` query parameter value | ||
* used by the initiating RP; otherwise it is not done. | ||
* | ||
* @see https://openid.net/specs/openid-connect-session-1_0.html#RedirectionAfterLogout | ||
* | ||
* @param request {RPInitiatedLogoutRequest} | ||
* @returns {null} | ||
*/ | ||
redirectOrRespond () { | ||
let { params: { post_logout_redirect_uri: postLogoutRedirectUri } } = this | ||
|
||
if (postLogoutRedirectUri) { | ||
this.redirectToRP() | ||
} else { | ||
this.respond() | ||
} | ||
} | ||
|
||
/** | ||
* Redirect To RP | ||
* | ||
* Redirects the user-agent back to the RP, if requested (by the RP providing | ||
* a `post_logout_redirect_uri` parameter). Also passes through the `state` | ||
* parameter, if supplied by the RP. | ||
* | ||
* @returns {null} | ||
*/ | ||
redirectToRP () { | ||
let { res, params: { post_logout_redirect_uri: uri, state } } = this | ||
|
||
if (state) { | ||
let response = qs.stringify({ state }) | ||
uri = `${uri}?${response}` | ||
} | ||
|
||
res.redirect(uri) // 302 redirect | ||
} | ||
|
||
/** | ||
* Respond | ||
* | ||
* Responds to the RP Initiated Logout request with a 204 No Content, if the | ||
* RP did not supply a `post_logout_redirect_uri` parameter. | ||
* | ||
* @returns {null} | ||
*/ | ||
respond () { | ||
let { res } = this | ||
|
||
res.set({ | ||
'Cache-Control': 'no-store', | ||
'Pragma': 'no-cache' | ||
}) | ||
|
||
res.status(204).send() | ||
} | ||
} | ||
|
||
module.exports = RPInitiatedLogoutRequest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters