import { SettingsFlow, UpdateSettingsFlowBody } from "@ory/client"
import { CardTitle, H3, P } from "@ory/themes"
import { AxiosError } from "axios"
import type { NextPage } from "next"
import Head from "next/head"
import Link from "next/link"
import { useRouter } from "next/router"
import { ReactNode, useEffect, useState } from "react"
import { ActionCard, CenterLink, Flow, Messages, Methods } from "../pkg"
import { handleFlowError } from "../pkg/errors"
import ory from "../pkg/sdk"
interface Props {
flow?: SettingsFlow
only?: Methods
}
function SettingsCard({
flow,
only,
children,
}: Props & { children: ReactNode }) {
if (!flow) {
return null
}
const nodes = only
? flow.ui.nodes.filter(({ group }) => group === only)
: flow.ui.nodes
if (nodes.length === 0) {
return null
}
return {children}
}
const Settings: NextPage = () => {
const [flow, setFlow] = useState()
// Get ?flow=... from the URL
const router = useRouter()
const { flow: flowId, return_to: returnTo } = router.query
useEffect(() => {
// If the router is not ready yet, or we already have a flow, do nothing.
if (!router.isReady || flow) {
return
}
// If ?flow=.. was in the URL, we fetch it
if (flowId) {
ory
.getSettingsFlow({ id: String(flowId) })
.then(({ data }) => {
setFlow(data)
})
.catch(handleFlowError(router, "settings", setFlow))
return
}
// Otherwise we initialize it
ory
.createBrowserSettingsFlow({
returnTo: String(returnTo || ""),
})
.then(({ data }) => {
setFlow(data)
})
.catch(handleFlowError(router, "settings", setFlow))
}, [flowId, router, router.isReady, returnTo, flow])
const onSubmit = (values: UpdateSettingsFlowBody) =>
router
// On submission, add the flow ID to the URL but do not navigate. This prevents the user loosing
// his data when she/he reloads the page.
.push(`/settings?flow=${flow?.id}`, undefined, { shallow: true })
.then(() =>
ory
.updateSettingsFlow({
flow: String(flow?.id),
updateSettingsFlowBody: values,
})
.then(({ data }) => {
// The settings have been saved and the flow was updated. Let's show it to the user!
setFlow(data)
// continue_with is a list of actions that the user might need to take before the settings update is complete.
// It could, for example, contain a link to the verification form.
if (data.continue_with) {
for (const item of data.continue_with) {
switch (item.action) {
case "show_verification_ui":
router.push("/verification?flow=" + item.flow.id)
return
}
}
}
if (data.return_to) {
window.location.href = data.return_to
return
}
})
.catch(handleFlowError(router, "settings", setFlow))
.catch(async (err: AxiosError) => {
// If the previous handler did not catch the error it's most likely a form validation error
if (err.response?.status === 400) {
// Yup, it is!
setFlow(err.response?.data)
return
}
return Promise.reject(err)
}),
)
return (
<>
Profile Management and Security Settings - Ory NextJS Integration
Example
Profile Management and Security Settings
Profile Settings
Change Password
Manage Social Sign In
Manage 2FA Backup Recovery Codes
Recovery codes can be used in panic situations where you have lost
access to your 2FA device.
Manage 2FA TOTP Authenticator App
Add a TOTP Authenticator App to your account to improve your account
security. Popular Authenticator Apps are{" "}
LastPass
{" "}
and Google Authenticator (
iOS
,{" "}
Android
).
Manage Hardware Tokens and Biometrics
Use Hardware Tokens (e.g. YubiKey) or Biometrics (e.g. FaceID,
TouchID) to enhance your account security.