forked from baron/baron-sso
refactor: 보안 정책 준수를 위해 Keto 포트 외부 노출 제거 및 내부 통신으로 변경 #239
This commit is contained in:
@@ -88,8 +88,8 @@ HYDRA_VERSION=v25.4.0-distroless
|
||||
|
||||
# Ory Keto Configuration
|
||||
KETO_VERSION=v25.4.0-distroless
|
||||
KETO_READ_URL=http://localhost:4466
|
||||
KETO_WRITE_URL=http://localhost:4467
|
||||
KETO_READ_URL=http://keto:4466
|
||||
KETO_WRITE_URL=http://keto:4467
|
||||
# KETO_READ_PORT=4466 # Internal only
|
||||
# KETO_WRITE_PORT=4467 # Internal only
|
||||
|
||||
|
||||
@@ -29,18 +29,13 @@ function LoginPage() {
|
||||
return () => window.removeEventListener("message", handleMessage);
|
||||
}, [navigate]);
|
||||
|
||||
const handleSSOLogin = (mode: "popup" | "redirect" = "popup") => {
|
||||
const handleSSOLogin = () => {
|
||||
const userfrontUrl = import.meta.env.USERFRONT_URL || "https://sso.hmac.kr";
|
||||
const callbackUrl = `${window.location.origin}/auth/callback`;
|
||||
|
||||
// 항상 redirect_uri를 포함하여 로그인이 성공하면 콜백 페이지로 오도록 함
|
||||
const loginUrl = `${userfrontUrl}/signin?source=adminfront&redirect_uri=${encodeURIComponent(callbackUrl)}`;
|
||||
|
||||
if (mode === "redirect") {
|
||||
window.location.href = loginUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
const width = 500;
|
||||
const height = 700;
|
||||
const left = window.screen.width / 2 - width / 2;
|
||||
@@ -54,7 +49,6 @@ function LoginPage() {
|
||||
|
||||
if (popup) {
|
||||
setIsLoggingIn(true);
|
||||
// Optional: Polling to detect if popup was closed without login
|
||||
const timer = setInterval(() => {
|
||||
if (popup.closed) {
|
||||
clearInterval(timer);
|
||||
@@ -62,8 +56,7 @@ function LoginPage() {
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
// If popup blocked, fallback to redirect
|
||||
window.location.href = loginUrl;
|
||||
alert("팝업 차단이 설정되어 있습니다. 팝업 허용 후 다시 시도해 주세요.");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -94,7 +87,7 @@ function LoginPage() {
|
||||
</CardHeader>
|
||||
<CardContent className="pt-4 pb-8 space-y-3">
|
||||
<Button
|
||||
onClick={() => handleSSOLogin("popup")}
|
||||
onClick={handleSSOLogin}
|
||||
className="w-full h-14 text-lg font-semibold flex gap-3 shadow-lg"
|
||||
disabled={isLoggingIn}
|
||||
>
|
||||
@@ -106,20 +99,11 @@ function LoginPage() {
|
||||
) : (
|
||||
<>
|
||||
<ShieldHalf size={22} />
|
||||
팝업창으로 로그인
|
||||
SSO 계정으로 로그인
|
||||
<ExternalLink size={16} className="opacity-50" />
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => handleSSOLogin("redirect")}
|
||||
className="w-full h-12 text-base font-medium flex gap-3"
|
||||
disabled={isLoggingIn}
|
||||
>
|
||||
현재 창에서 로그인 (리다이렉트)
|
||||
</Button>
|
||||
|
||||
<p className="mt-6 text-xs text-center text-muted-foreground leading-relaxed">
|
||||
관리자 전역 세션은 보안을 위해 15분간 유지됩니다.<br />
|
||||
|
||||
@@ -121,9 +121,6 @@ services:
|
||||
keto:
|
||||
image: oryd/keto:${KETO_VERSION:-v25.4.0}
|
||||
container_name: ory_keto
|
||||
ports:
|
||||
- "4466:4466" # Read API
|
||||
- "4467:4467" # Write API
|
||||
environment:
|
||||
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KETO_DB:-ory_keto}?sslmode=disable&max_conns=20
|
||||
volumes:
|
||||
|
||||
@@ -11,8 +11,8 @@ void implSendLoginSuccess(String token) {
|
||||
effectiveToken = AuthTokenStore.getToken() ?? "";
|
||||
}
|
||||
|
||||
final uri = Uri.parse(html.window.location.href);
|
||||
final redirectUri = uri.queryParameters['redirect_uri'];
|
||||
final uri = Uri.base;
|
||||
final redirectUri = uri.queryParameters['redirect_uri'] ?? uri.queryParameters['redirect_url'];
|
||||
|
||||
if (redirectUri != null && redirectUri.isNotEmpty) {
|
||||
// Redirection flow
|
||||
@@ -47,5 +47,9 @@ void implSendLoginSuccess(String token) {
|
||||
}
|
||||
|
||||
bool implIsPopup() {
|
||||
return html.window.opener != null;
|
||||
if (html.window.opener != null) return true;
|
||||
|
||||
// Fallback: Check query parameters for integration source
|
||||
final uri = Uri.base;
|
||||
return uri.queryParameters['source'] == 'adminfront';
|
||||
}
|
||||
|
||||
@@ -78,6 +78,13 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
final uri = Uri.base;
|
||||
|
||||
if (uri.queryParameters.containsKey('redirect_url')) {
|
||||
_redirectUrl = uri.queryParameters['redirect_url'];
|
||||
} else if (uri.queryParameters.containsKey('redirect_uri')) {
|
||||
_redirectUrl = uri.queryParameters['redirect_uri'];
|
||||
}
|
||||
|
||||
_loginChallenge = widget.loginChallenge ?? uri.queryParameters['login_challenge'];
|
||||
final loginIdParam = uri.queryParameters['loginId'];
|
||||
final codeParam = uri.queryParameters['code'];
|
||||
@@ -114,12 +121,6 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
if (!mounted) return;
|
||||
await _tryCookieSession();
|
||||
}
|
||||
|
||||
if (uri.queryParameters.containsKey('redirect_url')) {
|
||||
_redirectUrl = uri.queryParameters['redirect_url'];
|
||||
} else if (uri.queryParameters.containsKey('redirect_uri')) {
|
||||
_redirectUrl = uri.queryParameters['redirect_uri'];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user