Skip to content

Commit e6bf381

Browse files
fomalhautbN2D4
andauthored
Disable OAuth in iframe (#701)
<!-- Make sure you've read the CONTRIBUTING.md guidelines: https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md --> <!-- ELLIPSIS_HIDDEN --> ---- > [!IMPORTANT] > Disable OAuth in iframes using `useInIframe` hook and update `SimpleTooltip` to support conditional disabling. > > - **Behavior**: > - Disable OAuth buttons in iframes by using `useInIframe` hook in `oauth-button.tsx`. > - Show tooltip "OAuth is disabled in iFrame" when OAuth buttons are disabled. > - **Components**: > - Add `useInIframe` hook in `use-in-iframe.tsx` to detect iframe context. > - Remove `IframePreventer` component and its usage in `stack-handler.tsx`. > - Update `SimpleTooltip` in `simple-tooltip.tsx` to accept `disabled` prop to conditionally disable tooltips. > - **Misc**: > - Remove unused `useTranslation` import in `auth-page.tsx`. > > <sup>This description was created by </sup>[<img alt="Ellipsis" src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=stack-auth%2Fstack-auth&utm_source=github&utm_medium=referral)<sup> for 35793e8. You can [customize](https://app.ellipsis.dev/stack-auth/settings/summaries) this summary. It will automatically update as commits are pushed.</sup> <!-- ELLIPSIS_HIDDEN --> --------- Co-authored-by: Konsti Wohlwend <n2d4xc@gmail.com>
1 parent 2d42f44 commit e6bf381

5 files changed

Lines changed: 34 additions & 39 deletions

File tree

packages/stack-ui/src/components/simple-tooltip.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export function SimpleTooltip(props: {
77
type?: 'info' | 'warning',
88
inline?: boolean,
99
className?: string,
10+
disabled?: boolean,
1011
}) {
1112
const iconClassName = cn("w-4 h-4 text-zinc-500", props.inline && "inline");
1213
const icon = props.type === 'warning' ?
@@ -21,7 +22,7 @@ export function SimpleTooltip(props: {
2122

2223
return (
2324
<TooltipProvider>
24-
<Tooltip>
25+
<Tooltip open={props.disabled ? false : undefined}>
2526
<TooltipTrigger asChild>
2627
{props.inline ? (
2728
<span className={cn(props.className)}>

packages/template/src/components-page/auth-page.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@ export function AuthPage(props: Props) {
4242
}
4343

4444
function Fallback(props: Props) {
45-
const { t } = useTranslation();
46-
4745
return (
4846
<MaybeFullPage fullPage={!!props.fullPage}>
4947
<div className='stack-scope flex flex-col items-stretch' style={{ maxWidth: '380px', flexBasis: '380px', padding: props.fullPage ? '1rem' : 0 }}>

packages/template/src/components-page/stack-handler.tsx

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { getRelativePart } from "@stackframe/stack-shared/dist/utils/urls";
44
import { RedirectType, notFound, redirect } from 'next/navigation'; // THIS_LINE_PLATFORM next
55
import { useMemo } from 'react';
66
import { SignIn, SignUp, StackServerApp } from "..";
7-
import { IframePreventer } from "../components/iframe-preventer";
87
import { MessageCard } from "../components/message-cards/message-card";
98
import { HandlerUrls, StackClientApp } from "../lib/stack-app";
109
import { AccountSettings } from "./account-settings";
@@ -249,9 +248,7 @@ async function NextStackHandler<HasTokenStore extends boolean>(props: BaseHandle
249248
{next15DeprecationWarning}. This warning will not be shown in production.
250249
</span>
251250
)}
252-
<IframePreventer>
253-
{result}
254-
</IframePreventer>
251+
{result}
255252
</>;
256253
}
257254

@@ -317,11 +314,7 @@ function ReactStackHandler<HasTokenStore extends boolean>(props: BaseHandlerProp
317314
return null;
318315
}
319316

320-
return (
321-
<IframePreventer>
322-
{result}
323-
</IframePreventer>
324-
);
317+
return result;
325318
}
326319

327320
// END_PLATFORM

packages/template/src/components/oauth-button.tsx

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
'use client';
22

3-
import { BrandIcons, Button } from '@stackframe/stack-ui';
3+
import { BrandIcons, Button, SimpleTooltip } from '@stackframe/stack-ui';
44
import Color from 'color';
55
import { useEffect, useId, useState } from 'react';
66
import { useStackApp } from '..';
77
import { useTranslation } from '../lib/translations';
8+
import { useInIframe } from './use-in-iframe';
89

910
const iconSize = 22;
1011

@@ -27,6 +28,7 @@ export function OAuthButton({
2728
const { t } = useTranslation();
2829
const stackApp = useStackApp();
2930
const styleId = useId().replaceAll(':', '-');
31+
const isIframe = useInIframe();
3032

3133
const [lastUsed, setLastUsed] = useState<string | null>(null);
3234
useEffect(() => {
@@ -167,28 +169,35 @@ export function OAuthButton({
167169
return (
168170
<>
169171
<style>{styleSheet}</style>
170-
<Button
171-
onClick={async () => {
172-
localStorage.setItem('_STACK_AUTH.lastUsed', provider);
173-
await stackApp.signInWithOAuth(provider);
174-
}}
175-
className={`stack-oauth-button-${styleId} stack-scope relative`}
172+
<SimpleTooltip
173+
disabled={!isIframe}
174+
tooltip={isIframe ? "This auth provider is not supported in an iframe for security reasons." : undefined}
175+
className='stack-scope w-full inline-flex'
176176
>
177-
{!isMock && lastUsed === provider && (
178-
<span className="absolute -top-2 -right-2 bg-blue-500 text-white text-xs px-2 py-1 rounded-md">
177+
<Button
178+
onClick={async () => {
179+
localStorage.setItem('_STACK_AUTH.lastUsed', provider);
180+
await stackApp.signInWithOAuth(provider);
181+
}}
182+
className={`stack-oauth-button-${styleId} stack-scope relative w-full`}
183+
disabled={isIframe}
184+
>
185+
{!isMock && lastUsed === provider && (
186+
<span className="absolute -top-2 -right-2 bg-blue-500 text-white text-xs px-2 py-1 rounded-md">
179187
last
180-
</span>
181-
)}
182-
<div className='flex items-center w-full gap-4'>
183-
{style.icon}
184-
<span className='flex-1'>
185-
{type === 'sign-up' ?
188+
</span>
189+
)}
190+
<div className='flex items-center w-full gap-4'>
191+
{style.icon}
192+
<span className='flex-1'>
193+
{type === 'sign-up' ?
186194
t('Sign up with {provider}', { provider: style.name }) :
187195
t('Sign in with {provider}', { provider: style.name })
188-
}
189-
</span>
190-
</div>
191-
</Button>
196+
}
197+
</span>
198+
</div>
199+
</Button>
200+
</SimpleTooltip>
192201
</>
193202
);
194203
}
Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
11
'use client';
22
import { useEffect, useState } from "react";
33

4-
export function IframePreventer({ children }: {
5-
children: React.ReactNode,
6-
}) {
4+
export function useInIframe() {
75
const [isIframe, setIsIframe] = useState(false);
86
useEffect(() => {
97
if (window.self !== window.top) {
108
setIsIframe(true);
119
}
1210
}, []);
1311

14-
if (isIframe) {
15-
return <div>Stack Auth components may not run in an {'<'}iframe{'>'}.</div>;
16-
}
17-
18-
return children;
12+
return isIframe;
1913
}

0 commit comments

Comments
 (0)