K
Kinde5mo ago
Sachin

Refused to frame 'https://website.kinde.com/' because an ancestor violates the CSP

We're currently experiencing an issue with embedding our application within another application. We've implemented a custom sign-in page, and after users are successfully redirected from Azure AD, we encounter the following error: Refused to frame 'https://canopyroofing.kinde.com/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'self'". I went through some of the discussions but could not figure out the solution. We will be embedding our app onto another app (We have a fixed domain.). Is there anything we can do at our app side or this need to if possible configured from Kinde side? Having this is a must requirement and we could go to a paid plan after this.
15 Replies
onderay
onderay5mo ago
Hey, thanks for detailing the error you are seeing. The error you're encountering is due to the Content Security Policy (CSP) settings that Kinde enforces to prevent clickjacking attacks. Specifically, the frame-ancestors 'self' directive means that the page can only be framed by pages from the same origin. If we were to relax this security policy, it would make your application vulnerable to attacks. Is one application iframed into the other application?
Sachin
Sachin5mo ago
Yes to be specific, Our application will be iframed into this app: https://app.gohighlevel.com/ So in CSP, we could just add this as allowed?
Daniel_Kinde
Daniel_Kinde5mo ago
Hi @Sachin, You cannot use kinde within an iFrame this is to protect your users.
iFrames are vulnerable to click hacking, XSS and CSRF. Could you explain your usecase and why you wish to embed in iframe?
Sachin
Sachin5mo ago
Hi @Daniel_Kinde One of our web app needs to be iframed into this app: https://app.gohighlevel.com/, and this is a must requirement. So for our app, we are using Kinde with Azure AD authentication and implemented a custom signin page for it. Once the user clicks the SignIn and gets redirected to Azure AD and after validating there, once it tries to redirected back to Kinde callback URL we get the above error. We know that this is a non recommended approach but most of our Users are using this: https://app.gohighlevel.com/ and for some custom features we need to iframed our newly developed app to the gohighlevel. Also skipping the authentication for specific route it not what we want to do.
onderay
onderay5mo ago
Hey @Sachin , our team has had a quick chat, and our security setup won't allow this to happen, and it would need a significant change on our side to get this to work for you. So it is unlikely we will be able to support your use case in the short term. Sorry!
Sachin
Sachin5mo ago
@Daniel_Kinde 1. Yesterday on call we talked about there could be some other flow that could give us the same result, Can you please post it here. 2. Did you got the chance to know about that intermediate screen that asks users to signup for the first signin? 3. Where should I ask to change the owner for our account?
Daniel_Kinde
Daniel_Kinde5mo ago
Hi @Sachin 1. Find below the steps - From your application open the login link in a new window to complete the flow - The callback will go back to your application then can redirect and you can trigger a window close. - The application which is running inside the iframe will 'poll' your backend to check for a cookie. - When cookie is found react accordingly, even if its a hard refresh to get the cookie instance. That way you have a secure auth flow outside of the iframe and also get the session inside the iframe. 2. I will get back t you on this. 3. Add the new owner to the account as a team member, then email us from the owners account to [email protected] requesting the change.
Oli - Kinde
Oli - Kinde5mo ago
Hey @Sachin, Nice to meet you. Regarding your Azure AD authentication, a custom record needs to exist in Kinde for the user to authenticate with the Azure AD connection. In SAML connections, there is a toggle that, when enabled, will create a user record in Kinde and allow them to authenticate if the user doesnt exist in Kinde but successfully authenticates with the identity provider. It sounds like you want to achieve the same thing but for a native Azure AD connection. Since you are using custom sign-in page, you can achieve the same thing with some logic on your end - something like: - If user doesnt exist in Kinde (and is a valid user), create them via API, then redirect to Kinde Azure AD connection - Else if user does exist in Kinde, redirect to Kinde Azure AD connection - Else: Show error message SCIM is on our roadmap, which will allow you to auto-provision and de-provision users in Kinde from an external identity provider. You subscribe here to be notified when this feature is live. Let me know if you have any other questions.
Integrate SCIM identity management
Integrate SCIM identity management
No description
Sachin
Sachin4mo ago
Hi @Oli - Kinde @Daniel_Kinde Thanks for the suggestion, we went with syncing ours users using Management API for now. But facing another issue not exactly sure what is happening here, I had one issue that is causing some confusion for me,  Let me provide you with some details, Its regarding not able to access the id_token value.The values are present when committing to sessionStorage from here, @kinde-oss/kinde-typescript-sdk/dist/sdk/utilities/token-utils.js
export var commitTokensToSession = function (sessionManager, tokens, validationDetails) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Promise.all([
commitTokenToSession(sessionManager, tokens.refresh_token, 'refresh_token', validationDetails),
commitTokenToSession(sessionManager, tokens.access_token, 'access_token', validationDetails),
commitTokenToSession(sessionManager, tokens.id_token, 'id_token', validationDetails),
])];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); };
export var commitTokensToSession = function (sessionManager, tokens, validationDetails) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Promise.all([
commitTokenToSession(sessionManager, tokens.refresh_token, 'refresh_token', validationDetails),
commitTokenToSession(sessionManager, tokens.access_token, 'access_token', validationDetails),
commitTokenToSession(sessionManager, tokens.id_token, 'id_token', validationDetails),
])];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); };
But when I try to access it on one of our API's id_token it's coming undefined but access_token is present there. I am trying to get the ext_provider claim, So was trying to access the ID token. I looked at the id_token by decoding and the values are perfectly fine but not being able to access after commiting to session manager. We are using "@nuxtjs/kinde": "^0.1.10",
console.log(await event.context.kinde.sessionManager.getSessionItem('access_token'))
console.log(await event.context.kinde.sessionManager.getSessionItem('id_token'))console.log(await event.context.kinde.getClaimValue('ext_provider', 'id_token'))
console.log(await event.context.kinde.sessionManager.getSessionItem('access_token'))
console.log(await event.context.kinde.sessionManager.getSessionItem('id_token'))console.log(await event.context.kinde.getClaimValue('ext_provider', 'id_token'))
Oli - Kinde
Oli - Kinde4mo ago
Hey @Sachin,
Thanks for the suggestion, we went with syncing ours users using Management API for now.
Great to hear. I discussed the create a user record in Kinde toggle not present in the Azure AD connections with my team and we agreed we need to add that toggle for Azure AD connections too. My team mate is currently building that. I can let you know when this is live. Regarding your issue not being able to access the id_token value, I am sorry but I am struggling to understand your issue. Are you able to elaborate more on what your issue is?
Sachin
Sachin4mo ago
Hi @Oli - Kinde I am trying to access the claim from id_token like mentioned here, I am using the "@nuxtjs/kinde": "^0.1.10" sdk. https://docs.kinde.com/developer-tools/sdks/backend/typescript-sdk/#getting-claims The below code is raising exception, because id_token value is not present on console.log(await event.context.kinde.getClaimValue('ext_provider', 'id_token')) I tried to to log the id_token from sessionManager and its also empty here, thus above exception. console.log(await event.context.kinde.sessionManager.getSessionItem('id_token')) The strange thing is When user log in, the id_token value is committed from here, @kinde-oss/kinde-typescript-sdk/dist/sdk/utilities/token-utils.js commitTokenToSession(sessionManager, tokens.id_token, 'id_token', validationDetails)
Kinde docs
TypeScript SDK
Our developer tools provide everything you need to get started with Kinde.
Sachin
Sachin4mo ago
Found the issue, So its seems the Kinde middleware for nuxt do not store the id_token to the cookies and that is why we can not get the id_token on subsequent requests.
import { defineEventHandler } from "h3";
import { getKindeClient } from "../utils/client.mjs";
import { getSession, updateSession, clearSession, useRuntimeConfig } from "#imports";
export default defineEventHandler(async (event) => {
const sessionManager = await createSessionManager(event);
const kindeContext = { sessionManager };
const kindeClient = getKindeClient();
for (const _key in kindeClient) {
const key = _key;
kindeContext[key] = kindeClient[key].bind(kindeClient, sessionManager);
}
event.context.kinde = kindeContext;
});
async function createSessionManager(event) {
const keysInCookie = ["refresh_token", "access_token", "ac-state-key"];
const memorySession = {};
const config = useRuntimeConfig(event);
const sessionConfig = {
name: "kinde",
cookie: config.kinde.cookie,
password: config.kinde.password
};
return {
async getSessionItem(itemKey) {
const session = await getSession(event, sessionConfig);
console.log(session.data)
console.log(memorySession)
return session.data[itemKey] || memorySession[itemKey];
},
async setSessionItem(itemKey, itemValue) {
if (keysInCookie.includes(itemKey)) {
await updateSession(event, sessionConfig, {
[itemKey]: itemValue
});
} else {
memorySession[itemKey] = itemValue;
}
},
async removeSessionItem(itemKey) {
if (keysInCookie.includes(itemKey)) {
await updateSession(event, sessionConfig, {
[itemKey]: void 0
});
} else {
delete memorySession[itemKey];
}
},
async destroySession() {
for (const key in memorySession) {
delete memorySession[key];
}
await clearSession(event, sessionConfig);
}
};
}
import { defineEventHandler } from "h3";
import { getKindeClient } from "../utils/client.mjs";
import { getSession, updateSession, clearSession, useRuntimeConfig } from "#imports";
export default defineEventHandler(async (event) => {
const sessionManager = await createSessionManager(event);
const kindeContext = { sessionManager };
const kindeClient = getKindeClient();
for (const _key in kindeClient) {
const key = _key;
kindeContext[key] = kindeClient[key].bind(kindeClient, sessionManager);
}
event.context.kinde = kindeContext;
});
async function createSessionManager(event) {
const keysInCookie = ["refresh_token", "access_token", "ac-state-key"];
const memorySession = {};
const config = useRuntimeConfig(event);
const sessionConfig = {
name: "kinde",
cookie: config.kinde.cookie,
password: config.kinde.password
};
return {
async getSessionItem(itemKey) {
const session = await getSession(event, sessionConfig);
console.log(session.data)
console.log(memorySession)
return session.data[itemKey] || memorySession[itemKey];
},
async setSessionItem(itemKey, itemValue) {
if (keysInCookie.includes(itemKey)) {
await updateSession(event, sessionConfig, {
[itemKey]: itemValue
});
} else {
memorySession[itemKey] = itemValue;
}
},
async removeSessionItem(itemKey) {
if (keysInCookie.includes(itemKey)) {
await updateSession(event, sessionConfig, {
[itemKey]: void 0
});
} else {
delete memorySession[itemKey];
}
},
async destroySession() {
for (const key in memorySession) {
delete memorySession[key];
}
await clearSession(event, sessionConfig);
}
};
}
Oli - Kinde
Oli - Kinde4mo ago
Hi @Sachin, Thanks for explaining more details about your issue, I can now follow exactly what your issue is. @Daniel_Kinde is our Nuxt expert and he is back from his leave on Tuesday. Can this issue wait until then? I will make sure Daniel looks at this issue as soon as he is back from leave
Daniel_Kinde
Daniel_Kinde4mo ago
Hi @Sachin , I will look into the idToken not being stores for Nuxt SDK. This actively blocking you right now?
Sachin
Sachin4mo ago
It's not a blocking issue for me right now.
Want results from more Discord servers?
Add your server