<@U04UQ68083H> I’ve got an app at `localhost:3000`...
# ory-copilot
a
@chilly-king-10285 I’ve got an app at
localhost: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.
c
A message from kapa.ai
The CSRF error you're encountering is likely due to Ory's CSRF protection for all flows. This means that you must send a CSRF token in the body and CSRF cookie back when submitting a flow. The cookie should be sent by default by your browser, but you must add the CSRF token manually to the request body. This can be a JSON object or a native form POST. When mapping UI nodes, take note of input fields with the name
csrf_token
with the
hidden
attribute. Here's an example of how to map the UI nodes for CSRF protection:
Copy code
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).
a
@chilly-king-10285 I’m building a SPA. The client side app however is only redirecting the user to /oauth2/auth, which then redirects the user to the login flow page, so I don’t control the cookies being set by /oauth2/auth
c
A message from kapa.ai
In the case of a Single-Page Application (SPA), you can initialize the flow by calling the endpoint using AJAX or fetch instead of redirecting the browser. The response sets the necessary cookies and contains all UI nodes required to render the form. You must set
withCredentials: 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:
Copy code
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).
a
@chilly-king-10285 Like you said, you can’t call /oauth2/auth using an AJAX request, but you are suggesting I call it with fetch
c
A message from kapa.ai
I apologize for the confusion. You're correct. The
/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:
Copy code
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).
a
@chilly-king-10285 the docs say If the flow is initialized through a browser redirect, the application URL must to be set so that Ory can reach your application. WHat is the application URL referring to?
c
A message from kapa.ai
The "application URL" refers to the URL where your application is hosted. This is the URL that Ory will redirect to after the completion of certain flows (like login or registration). In the context of local development, this would be something like
<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:
Copy code
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).