Skip to main content

Implementing the login endpoint

note

Please read the Login Flow Documentation first!

In this document, you will learn how to implement the Login 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 login HTML form

note

The Login 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!

OAuth2 Login UI Screen

Accepting the login request

note

Check out our reference implementation of this endpoint!

routes/login.ts
// This is the endpoint the users end up at once they insert their password and username and hit "Log in".
router.post("/login", csrfProtection, (req, res, next) => {
// The challenge is now a hidden input field, so let's take it from the request body instead
const challenge = req.body.challenge

// Let's check if the user provided valid credentials. Of course, you'd use a database or some third-party service
// for this! Alternatively, you can also use Ory Identities:
//
// https://www.ory.sh/kratos
if (!(req.body.email === "foo@bar.com" && req.body.password === "foobar")) {
// Looks like the user provided invalid credentials, let's show the ui again...

res.render("login", {
csrfToken: req.csrfToken(),
challenge: challenge,
error: "The username / password combination isn't correct",
})
return
}

// Seems like the user authenticated! Let's tell hydra...
hydraAdmin
.acceptLoginRequest(challenge, {
// Subject is an alias for user ID. A subject can be a random string, a UUID, an email address, ....
subject: "foo@bar.com",

// This tells hydra to remember the browser and automatically authenticate the user in future requests. This will
// set the "skip" parameter in the other route to true on subsequent requests!
remember: Boolean(req.body.remember),

// When the session expires, in seconds. Set this to 0 so it will never expire.
remember_for: 3600,

// Sets which "level" (for example 2-factor authentication) of authentication the user has. The value is really arbitrary
// and optional. In the context of OpenID Connect, a value of 0 indicates the lowest authorization level.
// acr: '0',
})
.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 the login request

// You can deny the login request at any point - for example if the system is undergoing maintenance
// or the user has been banned, isn't allowed to use OAuth2 flows, and so on:
hydraAdmin
.rejectLoginRequest(challenge, {
error: "user_banned",
errorDescription: "You aren't allowed to log in!",
})
.then(({ body }) => {
// All we need to do now is to redirect the browser back to hydra!
res.redirect(String(body.redirectTo))
})