astonishing-appointment-3757
02/14/2024, 6:24 PMlocalhost:3000
setup that redirects the user to localhost:4000/oauth2/auth?${queryParams}
to login/signup and get an OAuth token (where localhost:4000
is the Ory tunnel and the custom UI URLs have been set to localhost:4455
) however I always get a Toast error about CSRF that A security violation was detected, please fill out the form again.
Would love pointers on how to resolve this and build custom UIs for an OAuth provider.chilly-king-10285
02/14/2024, 6:24 PMchilly-king-10285
02/14/2024, 6:25 PMcsrf_token
with the hidden
attribute. Here's an example of how to map the UI nodes for CSRF protection: javascript import { Configuration, FrontendApi, LoginFlow, UiNodeInputAttributes, } from "@ory/client" import { filterNodesByGroups, isUiNodeInputAttributes, } from "@ory/integrations/ui" import { useEffect, useState } from "react" const frontend = new FrontendApi( new Configuration({ basePath: "<http://localhost:4000>", // Use your local Ory Tunnel URL baseOptions: { withCredentials: true, }, }), ) function CsrfMapping() { const [flow, setFlow] = useState<LoginFlow>() useEffect(() => { frontend.createBrowserLoginFlow().then(({ data: flow }) => setFlow(flow)) }, []) return flow ? ( <form action={flow.ui.action} method={flow.ui.method}> {filterNodesByGroups({ nodes: flow.ui.nodes, // we will also map default fields here but not oidc and password fields groups: ["default"], attributes: ["hidden"], // only want hidden fields }).map((node) => { if ( isUiNodeInputAttributes(node.attributes) && (node.attributes as UiNodeInputAttributes).type === "hidden" && (node.attributes as UiNodeInputAttributes).name === "csrf_token" ) { return ( <input type={node.attributes.type} name={node.attributes.name} value={node.attributes.value} /> ) } })} </form> ) : ( <div>Loading...</div> ) } export default CsrfMapping
This code creates a CSRF mapping function that fetches the login flow and maps the UI nodes to include the CSRF token in the request body. If you're building a Single-Page App (SPA) and want the application to access the Ory Identities Public API, you need to configure your AJAX request to include cookies, because AJAX doesn't send cookies by default. For example, when using the browser's fetch
function, you need to set credentials: 'include'
. For more information, you can refer to the [Ory documentation on CSRF errors](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-basic-integration#csrf-errors) and [Accessing APIs from client-side JavaScript / AJAX](https://www.ory.sh/docs/troubleshooting/csrf#accessing-apis-from-client-side-javascript--ajax).astonishing-appointment-3757
02/14/2024, 6:30 PMchilly-king-10285
02/14/2024, 6:30 PMchilly-king-10285
02/14/2024, 6:30 PMwithCredentials: true
in axios or credentials: "include"
in fetch for AJAX and fetch requests to properly set cookies. Here's an example of how you can do this: javascript fetch('<http://localhost:4000/oauth2/auth>', { credentials: 'include' }) .then(response => response.json()) .then(data => console.log(data));
This will ensure that the necessary cookies are set correctly. If the flow is initialized through a browser redirect, the [application URL](https://www.ory.sh/docs/kratos/bring-your-own-ui/configure-ory-to-use-your-ui) must be set so that Ory can reach your application. Remember, you can't call /oauth2/auth
using an AJAX request. This endpoint can only be accessed using a normal browser request by clicking a link or redirecting the end-user's browser to that endpoint. For more information, you can refer to the [Ory documentation on creating a flow for SPAs](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-basic-integration#single-page-application-spa).astonishing-appointment-3757
02/14/2024, 6:32 PMchilly-king-10285
02/14/2024, 6:32 PMchilly-king-10285
02/14/2024, 6:32 PM/oauth2/auth
endpoint should not be called using AJAX or fetch. It should be accessed using a normal browser request by clicking a link or redirecting the end-user's browser to that endpoint. The AJAX or fetch request with credentials: 'include'
is used when your application needs to access the Ory Identities Public API, not the /oauth2/auth
endpoint. For the OAuth2 flow, the user's browser should be redirected to the /oauth2/auth
endpoint. If a session cookie is set, Ory OAuth2 and OpenID Connect will know the user of the request. If not, it will redirect the browser to the "login endpoint" established in your config. Here's an example of how you can redirect the user to the /oauth2/auth
endpoint: javascript window.location.href = '<http://localhost:4000/oauth2/auth?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=openid>';
Replace YOUR_CLIENT_ID
and YOUR_REDIRECT_URI
with your actual client ID and redirect URI. For more information, you can refer to the [Ory documentation on the OAuth2 flow](https://www.ory.sh/docs/oauth2-oidc/custom-login-consent/flow#login).astonishing-appointment-3757
02/14/2024, 6:34 PMchilly-king-10285
02/14/2024, 6:34 PMchilly-king-10285
02/14/2024, 6:34 PM<http://localhost:3000>
if your application is running on port 3000 on your local machine. You can set this URL in your Ory configuration. For example, in the Ory Kratos configuration file, you might have something like this: yaml selfservice: flows: settings: ui_url: <http://localhost:3000/settings> recovery: ui_url: <http://localhost:3000/recovery> verification: ui_url: <http://localhost:3000/verification> login: ui_url: <http://localhost:3000/login> registration: ui_url: <http://localhost:3000/registration>
In this example, different paths on the same domain are used for different flows. For more information, you can refer to the [Ory documentation on configuring Ory to use your UI](https://www.ory.sh/docs/kratos/bring-your-own-ui/configure-ory-to-use-your-ui).