'use client' import type { FC } from 'react' import type { ApprovalContext } from '@/service/device-flow' import { Avatar } from '@langgenius/dify-ui/avatar' import { Button } from '@langgenius/dify-ui/button' import { useEffect, useState } from 'react' import { approveExternal, fetchApprovalContext } from '@/service/device-flow' import { approveErrorCopy } from '../utils/error-copy' type Props = { onApproved: () => void onError: (message: string) => void } /** * AuthorizeSSO is the external-SSO branch authorize screen. On mount it * fetches /openapi/v1/oauth/device/approval-context to learn subject_email, * issuer, user_code, and csrf_token from the device_approval_grant cookie. * On Approve click, posts /openapi/v1/oauth/device/approve-external with * the CSRF header. * * The user_code in state is bound to the cookie by server; we do not accept * one from the URL because the SSO branch deliberately detaches from the * pre-SSO ?user_code=... query param. */ const AuthorizeSSO: FC = ({ onApproved, onError }) => { const [ctx, setCtx] = useState(null) const [busy, setBusy] = useState(false) const [loadErr, setLoadErr] = useState(null) useEffect(() => { let cancelled = false fetchApprovalContext() .then((c) => { if (!cancelled) setCtx(c) }) .catch((e) => { if (!cancelled) setLoadErr(approveErrorCopy(e)) }) return () => { cancelled = true } }, []) const approve = async () => { if (!ctx) return setBusy(true) try { await approveExternal(ctx, ctx.user_code) onApproved() } catch (e) { onError(approveErrorCopy(e)) } finally { setBusy(false) } } // loadErr and loading states render without the icon-circle pattern intentionally — // they occur before the SSO identity is established, so there is no terminal // state to decorate. The page.tsx error_* states cover post-lookup failures. if (loadErr) { return (

This session is no longer valid

Run {' '} difyctl auth login {' '} again to start a new sign-in.

) } if (!ctx) { return
Loading session…
} return (

Authorize Dify CLI

difyctl is requesting access via SSO. If you didn't start this from your terminal, close this tab.

{ctx.subject_email}

via SSO

{ctx.subject_issuer && (
Identity provider: {' '} {ctx.subject_issuer}
)}
) } export default AuthorizeSSO