full-notebook-65880
09/17/2024, 12:01 PMbrief-egg-61061
09/17/2024, 12:01 PMbrief-egg-61061
09/17/2024, 12:02 PMreturn_to
query parameter when initializing a flow. This parameter should be set to the URL of the page the user should be redirected to after they authenticate. For example, if you're creating a login flow, you can pass the return_to
parameter to the endpoint that initializes the flow. Here's an example of how you can do this: tsx frontend .createBrowserLoginFlow({ returnTo: returnTo || "/", // redirect to the root path after login // if the user has a session, refresh it refresh: true, // if the aal2 query parameter is set, we get the two factor login flow UI nodes aal: aal2 ? "aal2" : "aal1", }) .then(({ data: flow }) => { // set the flow data setFlow(flow) }) .catch((err) => { // Couldn't create login flow // handle the error })
(Source: [Ory Kratos Documentation](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-basic-integration#create-login-flow)) The return_to
URL is the redirect URL after the flow is completed. For example, with a login flow, the redirect happens after a successful login. Please note that the return_to
query parameter doesn't automatically persist across different flows and must be added to new flows. For example, if the user starts a login flow with return_to
URL set and then switches to a registration flow, the return_to
URL isn't used for the registration flow. In such a case, your application can re-use the same return_to
from the login flow by extracting the return_to
URL from the login flow's flow.return_to
and adding it to the registration flow. tsx sdk.getLoginFlow({ id: flow }).then(({ data: flow }) => { const returnTo = flow.return_to return sdk.createBrowserRegistrationFlow({ id: flow.id, return_to: returnTo, }) })
(Source: [Ory Kratos Documentation](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-advanced-integration#advanced-redirects))full-notebook-65880
09/17/2024, 12:23 PMsdk.getLoginFlow({ id: flow }).then(({ data: flow }) => {
const returnTo = flow.return_to
return sdk.createBrowserRegistrationFlow({
id: flow.id,
return_to: returnTo,
})
})
brief-egg-61061
09/17/2024, 12:23 PMbrief-egg-61061
09/17/2024, 12:24 PMreturn_to
URL that is retrieved from a login flow. This code should be placed in the component or function that handles the transition from the login flow to the registration flow in your application. In terms of file structure, this could be in a separate function that is called when a user decides to switch from logging in to registering. This function could be in a separate file or within login.tsx
or registration.tsx
, depending on how your application is structured. Here's a simplified example of how you might structure this in `login.tsx`: tsx // login.tsx import { useEffect } from "react" import { FrontendApi } from "@ory/client" const frontend = new FrontendApi(/* your configuration here */) export const Login = () => { // ... your other login code here ... const switchToRegistration = (flowId) => { frontend.getLoginFlow({ id: flowId }).then(({ data: flow }) => { const returnTo = flow.return_to return frontend.createBrowserRegistrationFlow({ id: flow.id, return_to: returnTo, }) }) } // Call switchToRegistration when the user decides to switch to registration // For example, you might call it in a button click handler }
Remember to replace FrontendApi
and other placeholders with your actual configuration and code. Also, ensure that error handling is in place for the promises. Please note that this is a simplified example and your actual implementation might need to be more complex depending on your application's requirements.full-notebook-65880
09/17/2024, 12:28 PMimport {LoginFlow, UpdateLoginFlowBody} from "@ory/client"
import {AxiosError} from "axios"
import type {NextPage} from "next"
import Link from "next/link"
import {useRouter} from "next/router"
import React, {useEffect, useState} from "react"
import {LogoutLink, Flow, Values} from "@/pkg"
import {handleGetFlowError, handleFlowError} from "@/pkg/errors"
import ory from "@/pkg/sdk"
import {Button} from "@ui/button";
import PageHead from "@ui/PageHead/PageHead";
import AuthBanner from "@components/AuthBanner/AuthBanner";
import LoginSkeleton from "@ui/Skeletons/PageSkeletons/AuthSkeleton/LoginSkeleton";
const Login: NextPage = () => {
const [flow, setFlow] = useState<LoginFlow>()
// Get ?flow=... from the URL
const router = useRouter()
const {
return_to: returnTo,
flow: flowId,
// Refresh means we want to refresh the session. This is needed, for example, when we want to update the password
// of a user.
refresh,
// AAL = Authorization Assurance Level. This implies that we want to upgrade the AAL, meaning that we want
// to perform two-factor authentication/verification.
aal,
} = router.query
// This might be confusing, but we want to show the user an option
// to sign out if they are performing two-factor authentication!
const onLogout = LogoutLink([aal, refresh])
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
.getLoginFlow({id: String(flowId)})
.then(({data}) => {
setFlow(data)
})
.catch(handleGetFlowError(router, "login", setFlow))
return
}
// Otherwise we initialize it
ory
.createBrowserLoginFlow({
refresh: Boolean(refresh),
aal: aal ? String(aal) : undefined,
returnTo: returnTo ? String(returnTo) : undefined,
})
.then(({data}) => {
setFlow(data)
})
.catch(handleFlowError(router, "login", setFlow))
}, [flowId, router, router.isReady, aal, refresh, returnTo, flow])
// const onSubmit = (values: UpdateLoginFlowBody) =>
const onSubmit = (values: Partial<Values>): Promise<void> =>
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(`/auth/login?flow=${flow?.id}`, undefined, {shallow: true})
.then(() =>
ory
.updateLoginFlow({
flow: String(flow?.id),
updateLoginFlowBody: values as UpdateLoginFlowBody,
})
// We logged in successfully! Let's bring the user home.
.then(() => {
if (flow?.return_to) {
window.location.href = flow?.return_to
return
}
router.push("/")
})
.then(() => {
})
.catch(handleFlowError(router, "login", setFlow))
.catch((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!
// @ts-ignore
setFlow(err.response?.data)
return
}
return Promise.reject(err)
}),
)
return (
<div className={"max-md:tw-h-screen tw-grid tw-grid-cols-5 lg:tw-grid-cols-12 lg:tw-gap-6 tw-bg-mvnGray-25"}>
<PageHead title={"Sign In"}/>
<div className="max-md:tw-hidden tw-col-span-7">
<AuthBanner/>
</div>
<div
className="tw-col-span-12 lg:tw-col-span-5 tw-px-4 tw-py-6 md:tw-pl-10 lg:tw-pr-[64px] tw-flex tw-items-center tw-justify-center">
{!flow ?
<LoginSkeleton/>
:
<div className={"tw-w-full tw-h-full"}>
<div>
<Link href={"/"}>
<figure className="tw-flex tw-items-center tw-justify-center">
<img src="/assets/globalAssets/moveOnLogo.svg" alt="moveon"/>
</figure>
</Link>
<div className="tw-text-center tw-py-8 tw-space-y-3">
<h2 className="tw-text-[30px] tw-font-bold">
{(() => {
if (flow?.refresh) {
return "Confirm Action"
} else if (flow?.requested_aal === "aal2") {
return "Two-Factor Authentication"
}
return "Sign In"
})()}
</h2>
<p className="tw-text-mvnBlack-100">Welcome back! Log in to your account </p>
</div>
<Flow onSubmit={onSubmit} flow={flow}/>
</div>
{aal || refresh ? (
<div>
<Button data-testid="logout-link" onClick={onLogout} className="tw-w-full">
Log out
</Button>
</div>
) : (
<>
<div className="tw-flex tw-items-center tw-justify-center tw-gap-4 tw-pt-1">
New here?
<Link href="/auth/registration" passHref
className="tw-font-bold tw-text-mvnGreen-800 hover:tw-no-underline hover:tw-text-mvnGreen-950">
Sign up
</Link>
</div>
</>
)}
</div>
}
</div>
</div>
)
}
export default Login
brief-egg-61061
09/17/2024, 12:28 PMbrief-egg-61061
09/17/2024, 12:28 PMfull-notebook-65880
09/17/2024, 12:38 PMconst switchToRegistration = (flowId: string) => {
ory.getLoginFlow({id: flowId}).then(({data: flow}) => {
const returnTo = flow.return_to
return ory.createBrowserRegistrationFlow({
id: flow.id,
return_to: returnTo,
})
})
}
from : return ory.createBrowserRegistrationFlow({
id: flow.id,
brief-egg-61061
09/17/2024, 12:38 PMbrief-egg-61061
09/17/2024, 12:39 PMcreateBrowserRegistrationFlow
method does not expect an id
property in its parameters. The FrontendApiCreateBrowserRegistrationFlowRequest
type does not have an id
property. The createBrowserRegistrationFlow
method is used to create a new registration flow, so it doesn't need an id
as input. Instead, it returns a new flow with a new id
. Here's how you can modify your code: tsx const switchToRegistration = (flowId: string) => { ory.getLoginFlow({id: flowId}).then(({data: flow}) => { const returnTo = flow.return_to return ory.createBrowserRegistrationFlow({ return_to: returnTo, }) }) }
In this code, createBrowserRegistrationFlow
is called with the return_to
URL from the login flow, but without an id
. The new registration flow that is created will have its own new id
. Please note that you should add error handling to your promises to handle any errors that might occur during the API calls.full-notebook-65880
10/30/2024, 9:30 AMbrief-egg-61061
10/30/2024, 9:30 AMbrief-egg-61061
10/30/2024, 9:30 AMrefresh=true
parameter in your React/Next.js app using the Ory SDK, you should add it when creating a login flow. This is typically done in the component or function that handles user authentication. Here's an example of how you can implement this in your React/Next.js app: tsx import { FrontendApi, Configuration } from "@ory/client" const frontend = new FrontendApi( new Configuration({ basePath: process.env.NEXT_PUBLIC_ORY_SDK_URL, baseOptions: { withCredentials: true, }, }) ) const refreshLogin = () => { frontend .createBrowserLoginFlow({ refresh: true, // This forces a session refresh returnTo: "/dashboard", // Redirect to dashboard after login }) .then(({ data: flow }) => { // Handle the flow data setFlow(flow) }) .catch((err) => { // Handle any errors console.error("Error creating login flow:", err) }) }
This code should be placed in the component or page where you want to trigger a session refresh. For example, you might call the refreshLogin
function: 1. When a user clicks a "Refresh Session" button 2. Before performing sensitive operations 3. After a period of inactivity Here are some key points about this implementation: 1. The refresh: true
parameter is added to the createBrowserLoginFlow
method call. This tells Ory to refresh the session [as described in the Ory Kratos documentation](https://www.ory.sh/docs/kratos/self-service/flows/user-login#refreshing-a-session). 2. The returnTo
parameter specifies where the user should be redirected after successfully refreshing their session. Adjust this URL as needed for your application. 3. This implementation assumes you're using the Ory SDK directly. If you're using the @ory/integrations
package in a Next.js app, you might need to adjust the SDK initialization as shown in the [Next.js integration guide](https://www.ory.sh/docs/getting-started/integrate-auth/nextjs#install-ory). Remember, session refreshing should be implemented thoughtfully to balance security with user experience. Use it in scenarios where you need to confirm the user's identity without fully logging them out.full-notebook-65880
01/06/2025, 9:16 AMbrief-egg-61061
01/06/2025, 9:16 AMbrief-egg-61061
01/06/2025, 9:16 AM{your-ory-backend-url}
with the actual URL of your self-hosted Ory backend: ory tunnel --dev <http://localhost:3000> {your-ory-backend-url}
This command will start the Ory Tunnel on port 4000 by default. The --dev
flag disables some security checks to make local development easier. 4. In your React application code, update the Ory SDK configuration to use the Tunnel URL: tsx import { Configuration, FrontendApi } from "@ory/client" const frontend = new FrontendApi( new Configuration({ basePath: "<http://localhost:4000>", baseOptions: { withCredentials: true, }, }) )
5. Now you can use the frontend
object to interact with your self-hosted Ory backend through the Tunnel. For example, to create a login flow: tsx frontend.createBrowserLoginFlow() .then(({ data: flow }) => { // Handle the flow data setFlow(flow) }) .catch((err) => { // Handle any errors console.error("Error creating login flow:", err) })
By using the Ory Tunnel, you ensure that the Ory APIs are exposed under the same top-level domain as your application, avoiding CORS issues. Remember to keep the Ory Tunnel running while developing your frontend. Also, make sure your React application is running on the port specified in the Tunnel command (in this case, http://localhost:3000). For more detailed information about using Ory Tunnel, you can refer to the [Ory CLI documentation on Proxy and Tunnel](https://www.ory.sh/docs/guides/cli/proxy-and-tunnel).full-notebook-65880
01/06/2025, 9:20 AMbrief-egg-61061
01/06/2025, 9:20 AMbrief-egg-61061
01/06/2025, 9:20 AMory tunnel
command is designed to work with Ory Network projects, not self-hosted Ory instances. Let me provide you with the correct approach for your self-hosted Ory setup. For a self-hosted Ory instance, you don't need to use the Ory Tunnel. Instead, you should configure your React application to directly communicate with your self-hosted Ory backend. Here's how you can do it: 1. Ensure your self-hosted Ory backend is running and accessible. 2. In your React application, configure the Ory SDK to point to your self-hosted Ory instance: typescript import { Configuration, FrontendApi } from "@ory/client" const ory = new FrontendApi( new Configuration({ basePath: "<https://admin.auth.service.staging.global.baharcart.com>", baseOptions: { withCredentials: true, }, }) )
3. Make sure your self-hosted Ory instance is configured to allow CORS requests from your React application's domain. You'll need to add the following to your Ory configuration file (e.g., kratos.yml
): yaml serve: public: cors: enabled: true allowed_origins: - <http://localhost:5173> allowed_methods: - POST - GET - PUT - PATCH - DELETE allowed_headers: - Authorization - Content-Type exposed_headers: - Content-Type allow_credentials: true debug: true
4. Restart your Ory instance to apply the CORS configuration. 5. Now you can use the ory
object in your React application to interact with your self-hosted Ory backend: typescript ory.createBrowserLoginFlow() .then(({ data: flow }) => { // Handle the flow data setFlow(flow) }) .catch((err) => { // Handle any errors console.error("Error creating login flow:", err) })
This approach allows your React application running on <http://localhost:5173>
to communicate directly with your self-hosted Ory instance at <https://admin.auth.service.staging.global.baharcart.com>
. Remember to adjust the CORS configuration and the basePath
in your React app if you deploy your frontend to a different URL in production. For more information on configuring CORS for self-hosted Ory, you can refer to the [Ory Kratos Configuration documentation](https://www.ory.sh/docs/kratos/reference/configuration).full-notebook-65880
01/12/2025, 5:06 AMbrief-egg-61061
01/12/2025, 5:06 AMbrief-egg-61061
01/12/2025, 5:06 AMyaml courier: channels: - id: sms type: http request_config: url: <https://api.your-sms-provider.com/send-sms> method: POST body: <base64://ZnVuY3Rpb24oY3R4KSB7CiAgVG86IGN0eC5yZWNpcGllbnQsCiAgQm9keTogY3R4LmJvZHksCn0>= headers: Content-Type: application/json auth: type: basic_auth config: user: your-username password: your-password
3. The body
field in the configuration is a base64 encoded Jsonnet template. When decoded, it looks like this: jsonnet function(ctx) { To: ctx.recipient, Body: ctx.body, }
You may need to adjust this template based on your SMS provider's API requirements. 4. Next, you need to enable the SMS one-time code in your configuration: yaml selfservice: methods: code: passwordless_enabled: true
5. Finally, make sure your identity schema includes a phone number trait that's configured for SMS verification: json { "properties": { "traits": { "type": "object", "properties": { "phone": { "type": "string", "format": "tel", "title": "Phone number", "<http://ory.sh/kratos|ory.sh/kratos>": { "credentials": { "code": { "identifier": true, "via": "sms" } }, "verification": { "via": "sms" } } } } } } }
Remember to replace the placeholder values (like <https://api.your-sms-provider.com/send-sms>
, your-username
, your-password
) with your actual SMS provider details. For more detailed information, you can refer to the following Ory documentation pages: - [SMS delivery configuration](https://www.ory.sh/docs/kratos/emails-sms/sending-sms) - [Enable SMS one-time-code (OTP)](https://www.ory.sh/docs/kratos/passwordless/one-time-code#enable-sms-one-time-code-otp) - [Custom identity schema](https://www.ory.sh/docs/kratos/passwordless/one-time-code#custom-identity-schema) Please note that SMS OTP is considered less secure than other methods due to vulnerabilities like SIM swapping and SMS interception. Consider using more secure methods like Passkeys if possible.