Implementing the Logout Endpoint & UI
note
Please read the Logout Flow Documentation first!
In this document, you will learn how to implement the Logout Endpoint using our Ory Hydra SDKs. The goal for this document is to have document this for multiple programming languages. If you are an expert in one of these languages, your help is highly appreciated in improving these docs!
Implementing the Logout HTML Form
note
The Logout HTML Form can't be only a Single Page App (Client-side browser application) or a Mobile App! There has to be a server-side component with access to Ory Hydra's Admin Endpoint!
- UI
- NodeJS
- HTML Example
note
Check out our reference implementation of this endpoint!
routes/logout.ts
// This example uses ExpressJS
import express from 'express'
import url from 'url'
import csrf from 'csurf'
import { AdminApi } from '@ory/hydra-client'
const hydraAdmin = new AdminApi(process.env.HYDRA_ADMIN_URL)
// Sets up csrf protection. Always do this when handling HTML forms!
const csrfProtection = csrf({ cookie: true })
const router = express.Router()
router.get('/', csrfProtection, (req, res, next) => {
// Parses the URL query
const query = url.parse(req.url, true).query
// The challenge is used to fetch information about the logout request from Ory Hydra.
const challenge = String(query.logout_challenge)
if (!challenge) {
next(new Error('Expected a logout challenge to be set but received none.'))
return
}
hydraAdmin
.getLogoutRequest(challenge)
// This will be called if the HTTP request was successful
.then(({ body }) => {
// Here we've access to response.subject, response.sid, ...
// The most secure way to perform a logout request is by asking the user if he/she really want to log out.
res.render('logout', {
csrfToken: req.csrfToken(),
challenge: challenge
})
})
// This will handle any error that happens when making HTTP calls to hydra
.catch(next)
})
<form action="/logout" method="POST">
<input type="hidden" name="_csrf" value="{{ .csrfToken }}" />
<input type="hidden" name="challenge" value="{{ .challenge }}" />
<input type="submit" id="accept" value="Yes" />
<input type="submit" id="reject" value="No" />
</form>
Accepting Logout
- NodeJS
note
Check out our reference implementation of this endpoint!
routes/logout.ts
// This is the endpoint the user ends up at once she/he inserts their password and username and hits "Log in".
router.post('/logout', csrfProtection, (req, res, next) => {
// The user agreed to log out, let's accept the logout request.
hydraAdmin
.acceptLogoutRequest(challenge)
.then(({ body }) => {
// All we need to do now is to redirect the user back to hydra!
res.redirect(String(body.redirectTo))
})
// This will handle any error that happens when making HTTP calls to hydra
.catch(next)
})
Rejecting Logout
- NodeJS
note
Check out our reference implementation of this endpoint!
routes/logout.ts
// This is the endpoint the user ends up at once she/he inserts their password and username and hits "Log in".
router.post('/logout', csrfProtection, (req, res, next) => {
return (
hydraAdmin
.rejectLogoutRequest(challenge)
.then(() => {
// The user didn't want to log out. Let's redirect him back somewhere or do something else.
res.redirect('https://www.ory.sh/')
})
// This will handle any error that happens when making HTTP calls to hydra
.catch(next)
)
})