Skip to main content

Implementing Authentication Flows

This guide shows how to implement user registration and login flows in your application using Ory's browser-based authentication.

Registration Flow

The registration flow lets new users create accounts in your application. Here's how to implement it:

  1. Initialize a registration flow

    Redirect the user to the registration page or create a registration flow programmatically

  2. Render the registration form

    Fetch and display the registration UI with all necessary fields

  3. Submit the form

    Handle form submission and process the response

Create Registration Flow

const { Configuration, FrontendApi } = require("@ory/client")

// Initialize the SDK
const ory = new FrontendApi(
new Configuration({
basePath: "https://$PROJECT_SLUG.projects.oryapis.com",
baseOptions: {
withCredentials: true,
},
}),
)

// Create a new registration flow
async function createRegistrationFlow(req, res) {
try {
// Initialize the registration flow
const { data: flow } = await ory.createBrowserRegistrationFlow({
returnTo: "/welcome", // Optional return URL after successful registration
})

// Render the form or return the flow data
res.render("registration", { flow })
} catch (err) {
console.error("Error creating registration flow:", err)
res.status(500).json({ error: "Could not create registration flow" })
}
}

// Submit registration data
async function submitRegistration(req, res) {
const flowId = req.body.flow // The flow ID from the form

try {
// Submit the form data
const { data } = await ory.submitSelfServiceRegistrationFlow(flowId, {
method: "password",
password: req.body.password,
traits: {
email: req.body.email,
name: req.body.name,
},
})

// Successful registration, redirect user
res.redirect(data.return_to || "/welcome")
} catch (err) {
// Handle errors
console.error("Registration error:", err.response?.data)

// Update the flow with the error and render the form again
res.render("registration", {
flow: err.response?.data,
error: err.response?.data?.ui.messages,
})
}
}

Login Flow

The login flow authenticates existing users. Here's how to implement it:

  1. Initialize a login flow

    Redirect the user to the login page or create a login flow programmatically

  2. Render the login form

    Fetch and display the login UI with fields for credentials

  3. Submit the form

    Handle form submission and process the response

Create Login Flow

const { Configuration, FrontendApi } = require("@ory/client")

// Initialize the SDK
const ory = new FrontendApi(
new Configuration({
basePath: "https://$PROJECT_SLUG.projects.oryapis.com",
baseOptions: {
withCredentials: true,
},
}),
)

// Create a new login flow
async function createLoginFlow(req, res) {
try {
// Initialize the login flow
const { data: flow } = await ory.createBrowserLoginFlow({
returnTo: "/dashboard", // Optional return URL after successful login
refresh: false, // Set to true to refresh an existing login session
})

// Render the form or return the flow data
res.render("login", { flow })
} catch (err) {
console.error("Error creating login flow:", err)
res.status(500).json({ error: "Could not create login flow" })
}
}

// Submit login data
async function submitLogin(req, res) {
const flowId = req.body.flow // The flow ID from the form

try {
// Submit the form data
const { data } = await ory.submitSelfServiceLoginFlow(flowId, {
method: "password",
identifier: req.body.identifier, // Username or email
password: req.body.password,
})

// Successful login, redirect user
res.redirect(data.return_to || "/dashboard")
} catch (err) {
// Handle errors
console.error("Login error:", err.response?.data)

// Update the flow with the error and render the form again
res.render("login", {
flow: err.response?.data,
error: err.response?.data?.ui.messages,
})
}
}

Session Management

After a successful login, Ory sets a session cookie. You can check if a user is authenticated and access their information:

// Check if a user is authenticated
const requireAuth = async (req, res, next) => {
try {
// This verifies the session and throws an error if not authenticated
const { data: session } = await ory.toSession({
cookie: req.header("cookie"),
})

// Make session available to the route handler
req.session = session
next()
} catch (err) {
// Not authenticated, redirect to login
res.redirect("/login")
}
}

// Use the middleware for protected routes
app.get("/dashboard", requireAuth, (req, res) => {
// Access user data
const userId = req.session.identity.id
const email = req.session.identity.traits.email

res.render("dashboard", { user: req.session.identity })
})

Logout Flow

To log users out, use the logout flow:

// Create logout route
app.get("/logout", async (req, res) => {
try {
// Create a logout flow
const { data: logoutFlow } = await ory.createBrowserLogoutFlow({
cookie: req.header("cookie"),
})

// Redirect to logout URL
res.redirect(logoutFlow.logout_url)
} catch (err) {
console.error("Logout error:", err)
// Already logged out or error, redirect to login
res.redirect("/login")
}
})

Error Handling

Handle authentication errors gracefully by checking for specific error types and displaying appropriate messages:

async function login(req, res) {
try {
// ... login code ...
} catch (err) {
if (err.response?.status === 400) {
// Validation errors (wrong password, etc.)
const errorMessages = err.response.data.ui.messages || []
res.render("login", {
flow: err.response.data,
error: errorMessages.map((msg) => msg.text).join(", "),
})
} else if (err.response?.status === 410) {
// Flow expired
res.redirect("/login") // Create a new flow
} else if (err.response?.status === 401) {
// Unauthorized
res.redirect("/login?error=invalid_credentials")
} else {
// Server error
console.error("Unexpected error:", err)
res
.status(500)
.render("error", { message: "An unexpected error occurred" })
}
}
}

Next Steps

Now that you have implemented basic authentication flows in your application, you can:

  1. Customize the user interface
  2. Add multi-factor authentication
  3. Configure session lifespans
  4. Implement account recovery

In the next section, we'll cover session management in more detail, including checking session status, refreshing sessions, and handling logouts.