I’m trying to implement a authentication flow at the moment and having some issues.
https://www.canva.dev/docs/apps/authenticating-users/ is some of the documentation.
Here’s a brief recap of the flow:
-
User is authenticated with Canva on client, gets state and token jwt
-
User clicks on a button or link that redirects them to your identity provider’s authorization endpoint (in this case, Auth0). This request includes several query parameters such as your application’s client ID, the requested scope, and a redirect URI.
-
The user logs in with Auth0, which then redirects the user to the redirect URI specified in step 1. This redirect includes an authorization code as a query parameter.
-
Your server (the callback cloud function in this case) receives the authorization code from step 2.
-
Your server sends a POST request to Auth0’s token endpoint to exchange the authorization code for an access token. This request includes your application’s client ID, client secret, the authorization code received in step 3, and the redirect URI.
-
Your server receives the access token from Auth0.
-
Now that your server has an access token, it can use this token to make authenticated requests on behalf of the user.
-
Lastly, your server redirects the user back to Canva with the original state parameter and a success indicator.
I’m having some issues with resolving this flow at the moment.
Using two google cloud functions
Redirects users to AUth0 from Canva after using canva react login stuff.
`const functions = require('@google-cloud/functions-framework');
const { URL } = require('url');
functions.http('authorize', (req, res) => {
const {
state,
redirect_uri,
nonce,
code_challenge,
code_challenge_method,
auth0Client,
canva_state
} = req.query;
res.set('Set-Cookie', `canva_state=${canva_state}; Max-Age=${24 * 60 * 60}; HttpOnly; Path=/`);
// dev-xxx.us.auth0.com
const url = new URL(`https://dev-xxx.us.auth0.com/authorize`);
url.searchParams.append('response_type', 'code');
url.searchParams.append('client_id', 'xxxx');
url.searchParams.append('redirect_uri', redirect_uri);
url.searchParams.append('state', state);
url.searchParams.append('scope', 'openid profile email');
url.searchParams.append('response_mode', 'query');
url.searchParams.append('nonce', nonce);
url.searchParams.append('code_challenge', code_challenge);
url.searchParams.append('code_challenge_method', code_challenge_method);
url.searchParams.append('auth0Client', auth0Client);
console.log("req: ",req)
res.redirect(url.toString());
// const url = new URL(`https://${process.env.AUTH0_DOMAIN}/authorize`);
// process.env.AUTH0_CLIENT_ID
// url.searchParams.append('redirect_uri', process.env.REDIRECT_URI);
// res.send(`Hello ${req.query.name || req.body.name || 'World'}!`);
});`
- Cloud function for re-directing back to canva
`const functions = require('@google-cloud/functions-framework');
const { URL } = require('url');
functions.http('redirect', (req, res) => {
try {
// Redirect back to Canva with the original state and success=true
const params = new URLSearchParams({
success: "true",
state: req.cookies.canva_state, // Use the state from the original request
});
const url = `https://www.canva.com/apps/configured?${params}`;
res.redirect(302, url);
} catch (error) {
console.error("Error exchanging authorization code for access token: ", error);
// Handle the error appropriately in your application
}
});
`
This, to try and re-direct back to canva.
This is the canva setup in the image below, and the auth0
Any ideas on how to approach this?
this is the current react setup.
`import { AppUiProvider } from "@canva/app-ui-kit";
import * as React from "react";
import { createRoot } from "react-dom/client";
import App from "./app";
import "@canva/app-ui-kit/styles.css";
import { Auth0Provider } from "@auth0/auth0-react";
const root = createRoot(document.getElementById("root")!);
function render() {
root.render(
<AppUiProvider>
<Auth0Provider
domain="https://us-central1-atomic-saga-xxx.cloudfunctions.net"
clientId="xxx"
authorizationParams={{
redirect_uri: window.location.origin,
response_type: "code",
}}
>
<App />
</Auth0Provider>
</AppUiProvider>
);
}
render();
if (module.hot) {
module.hot.accept("./app", render);
}`
`// App.tsx
import React, { useEffect, useState } from "react";
import LoginButton from "./components/auth/Login";
import AuthenticatedApp from "./AuthenticatedApp";
import { useAuth0 } from "@auth0/auth0-react";
import Wrapper from "./components/auth/Loading";
import { auth } from "@canva/user";
import styles from "styles/components.css";
import { Rows } from "@canva/app-ui-kit";
const App: React.FC = () => {
const [isCanvaAuthenticated, setIsCanvaAuthenticated] = useState(false);
const { isAuthenticated } = useAuth0();
useEffect(() => {
const checkAuthentication = async () => {
const token = await auth.getCanvaUserToken();
setIsCanvaAuthenticated(token ? true : false);
};
checkAuthentication();
}, []);
if (isCanvaAuthenticated) {
return (
<div className={styles.scrollContainer}>
<Rows spacing="2u">
<Wrapper>
User is authenticated with Canva.
{isAuthenticated ? <AuthenticatedApp /> : <LoginButton />}
</Wrapper>
</Rows>
</div>
);
} else {
return (
<div className={styles.scrollContainer}>
<Wrapper>Please authenticate with Canva first.</Wrapper>
</div>
);
}
};
export default App;`
// LoginButton.tsx
import React, { FC, useState } from "react";
import { useAuth0 } from "@auth0/auth0-react";
const LoginButton: FC = () => {
const [isAuthenticating, setIsAuthenticating] = useState(false);
const { loginWithRedirect } = useAuth0();
const initiateAuthenticationFlow = async () => {
console.log("initiateAuthenticationFlow");
setIsAuthenticating(true);
try {
await loginWithRedirect();
} catch (error) {
console.error(error);
setIsAuthenticating(false);
}
};
return (
<button onClick={initiateAuthenticationFlow} disabled={isAuthenticating}>
{isAuthenticating ? "Authenticating..." : "Log In"}
</button>
);
};
export default LoginButton;
THis is currently not working.
receiving,
Refused to frame ‘https://dev-w4zhjgbo6zvcc1xf.us.auth0.com/’ because an ancestor violates the following Content Security Policy directive: “frame-ancestors ‘none'”.
among other issues.
THanks!
Expected to see, login, and working state flow, but currently just lots of bugs.
