Skip to content

Auth0 인증 통합

App Shell에서 Auth0 SaaS를 활용한 인증 시스템을 구축하고, 마이크로앱 전체에 인증 컨텍스트를 전파하는 구조를 학습한다.

학습 목표

  1. Auth0의 역할과 SPA 인증 흐름(Authorization Code + PKCE)을 이해한다.
  2. App Shell 레벨에서 @auth0/auth0-react 프로바이더를 구성한다.
  3. 마이크로앱에서 인증 정보(사용자, 토큰)에 접근하는 방법을 구현한다.
  4. 로그인/로그아웃 플로우와 비인증 사용자 차단 로직을 완성한다.
  5. 액세스 토큰 관리와 API 호출 시 인증 헤더 주입 전략을 익힌다.

본문

1. 마이크로프론트엔드에서 인증의 위치

마이크로프론트엔드 환경에서 인증은 App Shell이 중앙에서 관장하는 것이 일반적이다. 각 마이크로앱이 독립적으로 인증을 처리하면 로그인 상태 불일치, 토큰 중복 관리, UX 파편화가 발생한다.

2. Auth0 설정

2-1. Auth0 대시보드 설정

Auth0에서 SPA(Single Page Application) 타입의 애플리케이션을 생성하고 다음 값을 설정한다.

설정 항목설명
Application TypeSingle Page ApplicationSPA용 PKCE 흐름 활성화
Allowed Callback URLshttp://localhost:3000로그인 후 리다이렉트 대상
Allowed Logout URLshttp://localhost:3000로그아웃 후 리다이렉트 대상
Allowed Web Originshttp://localhost:3000CORS 허용 및 Silent Auth 지원

대시보드에서 확인하는 DomainClient ID가 프론트엔드 설정에 필요하다.

2-2. 환경 변수 구성

민감한 설정값은 .env 파일로 관리한다. Webpack 환경에서는 dotenv-webpack 플러그인으로 런타임에 주입한다.

bash
# apps/shell/.env
REACT_APP_AUTH0_DOMAIN=your-tenant.auth0.com
REACT_APP_AUTH0_CLIENT_ID=your_client_id_here
REACT_APP_AUTH0_CALLBACK_URL=http://localhost:3000
js
// apps/shell/webpack.config.js
const Dotenv = require("dotenv-webpack");

module.exports = {
  plugins: [
    new Dotenv(),
    // ...기존 플러그인
  ],
};

3. Auth0Provider 구성

@auth0/auth0-react 패키지의 Auth0Provider를 React Router의 내부에 배치해야 useNavigate 훅을 사용할 수 있다. 이를 위해 별도의 래퍼 컴포넌트를 만든다.

tsx
// apps/shell/src/components/Auth0ProviderWithNavigator.tsx
import React from "react";
import { useNavigate } from "react-router-dom";
import { Auth0Provider } from "@auth0/auth0-react";
import type { AppState } from "@auth0/auth0-react";

const Auth0ProviderWithNavigator: React.FC<React.PropsWithChildren> = ({
  children,
}) => {
  const navigate = useNavigate();

  const domain = process.env.REACT_APP_AUTH0_DOMAIN;
  const clientId = process.env.REACT_APP_AUTH0_CLIENT_ID;
  const redirectUri = process.env.REACT_APP_AUTH0_CALLBACK_URL;

  if (!domain || !clientId || !redirectUri) {
    throw new Error("Auth0 환경 변수가 설정되지 않았습니다.");
  }

  const onRedirectCallback = (appState?: AppState) => {
    navigate(appState?.returnTo || window.location.pathname);
  };

  return (
    <Auth0Provider
      domain={domain}
      clientId={clientId}
      authorizationParams=&#123;&#123; redirect_uri: redirectUri &#125;&#125;
      onRedirectCallback={onRedirectCallback}
    >
      {children}
    </Auth0Provider>
  );
};

export default Auth0ProviderWithNavigator;

이 컴포넌트를 Layout 컴포넌트에서 감싸 적용한다.

tsx
// apps/shell/src/components/Layout.tsx
import Auth0ProviderWithNavigator from "./Auth0ProviderWithNavigator";

export default function Layout() {
  return (
    <Auth0ProviderWithNavigator>
      {/* Header, Navigation, Outlet 등 */}
    </Auth0ProviderWithNavigator>
  );
}

4. 로그인/로그아웃 플로우

로그인/로그아웃 핸들러 구현

useAuth0() 훅에서 loginWithRedirect, logout, isAuthenticated, user를 꺼내 사용한다.

  • 로그인: await loginWithRedirect({ appState: { returnTo: "/" } }) -- Auth0 로그인 페이지로 리다이렉트
  • 로그아웃: await logout({ logoutParams: { returnTo: window.location.origin } }) -- 세션 종료 후 메인 페이지로 복귀

UIKit의 Button 컴포넌트와 결합하여 isAuthenticated 상태에 따라 로그인/로그아웃 버튼을 조건부 렌더한다.

인증 가드

Layout에서 OutletisAuthenticated로 감싸 비인증 사용자의 마이크로앱 접근을 차단한다. isLoading 상태를 반드시 먼저 처리해야 한다. Auth0 SDK 초기화 시 토큰 유효성을 확인하는데, 이 과정 완료 전에는 isAuthenticatedfalse로 나타나 깜빡임이 발생할 수 있다.

tsx
{isLoading ? <div>인증 확인 중...</div>
  : isAuthenticated ? <Outlet />
  : <div>로그인이 필요합니다.</div>}

5. 마이크로앱에서 인증 정보 접근

App Shell의 Auth0Provider 내부에 렌더되는 마이크로앱은 useAuth0() 훅으로 인증 정보에 접근할 수 있다. 단, Module Federation 환경에서는 @auth0/auth0-reactshared 싱글톤으로 설정해야 동일한 컨텍스트를 공유한다.

js
// webpack.config.js (마이크로앱)
shared: {
  "@auth0/auth0-react": { singleton: true, requiredVersion: "^2.0.0" },
  react: { singleton: true },
  "react-dom": { singleton: true },
}

마이크로앱 내부에서는 getAccessTokenSilently()로 토큰을 획득하고, fetch 호출 시 Authorization: Bearer {token} 헤더를 주입하여 API 서버와 통신한다.

6. 토큰 관리 전략

Auth0 React SDK는 기본적으로 토큰을 메모리에 저장한다. getAccessTokenSilently()를 호출하면 다음 순서로 동작한다.

  1. 캐시 확인: 메모리에 유효한 토큰이 있으면 즉시 반환
  2. Silent Auth: 토큰이 만료됐으면 hidden iframe으로 Auth0에 새 토큰 요청
  3. 실패 시: 사용자에게 재로그인 요청

토큰 저장 방식별 보안 수준은 다음과 같다.

저장 방식XSS 방어CSRF 방어탭 간 공유권장 여부
메모리 (기본)강함해당 없음불가권장
localStorage취약해당 없음가능비권장
HttpOnly Cookie강함토큰 필요가능가장 안전 (BFF 필요)

Axios 인터셉터로 토큰 자동 주입

매번 getAccessTokenSilently()를 호출하는 대신 Axios 인터셉터에 토큰 획득 함수를 등록하여 자동화할 수 있다. setTokenGetter(getAccessTokenSilently)를 앱 초기화 시 한 번 호출하면, 이후 모든 API 요청에 Authorization: Bearer {token} 헤더가 자동으로 주입된다.

7. 마이크로앱 간 인증 공유 방식 비교

방식장점단점적합한 경우
Auth0 SDK 싱글톤 공유설정 간단. 컨텍스트 직접 공유Module Federation shared 필수동일 프레임워크 (React)
CustomEvent 전파프레임워크 무관토큰 직접 전달 시 보안 위험다중 프레임워크
마이크로앱별 Auth0 클라이언트완전 독립. Shell 장애 영향 없음SSO Session 의존. 초기 지연고도의 독립성 요구

커리어 플랫폼에서는 모든 앱이 React를 사용하므로 Auth0 SDK 싱글톤 공유 방식을 기본으로 채택하되, 높은 보안이 필요한 경우 마이크로앱별 Auth0 클라이언트를 사용하여 Shell에 의존하지 않는 토큰 획득 경로를 확보한다.


핵심 정리

항목내용
인증 위치App Shell에서 중앙 관리. Auth0Provider로 컨텍스트 전파
인증 흐름Authorization Code + PKCE. loginWithRedirect 기반
프로바이더 배치React Router 내부에 위치 (useNavigate 사용을 위해)
인증 가드isAuthenticated로 Outlet 조건부 렌더링
토큰 저장메모리 (기본). XSS 방어에 가장 안전
토큰 갱신getAccessTokenSilently() -> Silent Auth (hidden iframe)
API 호출Authorization: Bearer {token} 헤더 주입
마이크로앱 공유Module Federation shared 싱글톤으로 Auth0 SDK 공유

다음 단계

다음 문서 ../12-마이크로앱-구현/01-API-서버-구축.md에서는 마이크로앱이 실제로 통신할 API 서버를 구축한다. Auth0에서 발급한 토큰을 서버 측에서 검증하고, 각 마이크로앱의 API 엔드포인트를 설계하는 과정을 다룬다.