본문 바로가기
WIKI 기술 지식 베이스

처음부터 OIDC 제공자

원문 보기 위키 갱신

처음부터 OIDC 제공자 (구 프론트엔드 시스템)

info

출처: 문서

본문

info

이 문서는 여전히 구 프론트엔드 시스템을 사용하는 Backstage 앱을 위한 것이에요. 앱이 새 프론트엔드 시스템을 사용한다면 현재 가이드 를 읽으세요.

이 섹션은 Backstage OIDC 제공자를 활성화하고 사용하는 방법을 보여줘요.

요약

OIDC는 수많은 구현을 가진 프로토콜이에요. 사용자 중 상당수가 OIDC 프로토콜이 무엇인지 모를 가능성이 높지만, 여러분의 OIDC 구현은 알아볼 거예요. Backstage는 범용적인 oidc 인가 전략을 제공해요. 이를 여러분의 OIDC 구현 이름과 브랜딩으로 다시 배지(re-badge)하여 사용자가 Backstage sign-in 페이지에서 알아볼 수 있게 해야 해요.

예를 들어 조직에서 Keycloak을 사용한다면 OIDC 제공자를 Keycloak으로 다시 배지하고 사용자에게 Sign In using Keycloak으로 로그인하라고 알려주면 돼요.

단계

Backstage OIDC 제공자는 기본적으로 활성화돼 있지 않아요. 제공자를 수동으로 활성화하고 어떤 OIDC 서버를 사용할지 알려줘야 해요.

Backstage OIDC 제공자를 활성화하려면:

  • 제공자를 식별하는 API 참조를 만들기.

  • 인증을 처리할 API 팩토리를 만들기.

  • 인증할 수 있도록 auth 제공자를 추가하거나 재사용.

  • 인증 결과를 처리할 resolver를 추가하거나 재사용.

  • 제3자 인증 솔루션에 접근하도록 제공자를 구성.

  • 제공자를 Backstage sign-in 페이지에 추가.

단순하게 하기 위해 Backstage 설치에 OIDC 제공자가 하나만 있다고 가정해요. (Backstage에 여러 OIDC 제공자가 필요하면 단계가 달라져요.)

다음에서 각 단계를 더 자세히 설명할 거예요.

API 참조

API 참조는 의존성 주입을 활성화하기 위해 존재해요. (자세한 설명은 Utility APIs를 참고하세요.)

이 예시에서는 API ref를 packages/app/src/apis.ts 파일에 직접 만들 거예요. ref를 이 파일에 둘 필요는 없어요. API 팩토리가 있는 곳에 import할 수 있고, 어떤 패키지와 플러그인도 필요할 때 API 인스턴스를 주입할 수 있도록 애플리케이션의 나머지 부분에서 쉽게 접근할 수 있는 어디든 괜찮아요.

export const keycloakAuthApiRef: ApiRef<  OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & SessionApi> = createApiRef({  id: 'auth.keycloak',});

API ref의 id는 다른 ref와 충돌하지 않는 한 원하는 무엇이든 될 수 있어요. Backstage는 커스텀 제공자를 참조하는 커스텀 이름을 사용할 것을 권장해요.

TypeScript 참고

이 API 참조와 TypeScript 타입을 내보내므로 앱 어디에서든 이 참조를 import할 수 있어야 합니다. 이 타입들은 API를 주입할 때 DI에서 어떤 인스턴스를 얻는지 TypeScript에 알려줍니다. 이 경우 인증용 API를 정의하고 있으므로 이 인스턴스가 4개의 API 인터페이스를 준수한다고 TS에 알려줍니다:

  • 인증을 처리할 OIDC API.

  • 해당 auth 제공자에서 사용자 프로필 정보를 요청하는 Profile API.

  • 사용자 프로필을 backstage identity와 처리하고 연관시키는 Backstage identity API.

  • 사용자가 sign-in되어 있는 동안 가질 세션을 처리하는 Session API.

API 팩토리 (및 auth 제공자)

Backstage API 팩토리는 Backstage 의존성 주입 시스템의 일부예요. 팩토리 함수는 Backstage 앱의 어떤 것이 그것이 제공하는 API의 인스턴스를 처음 사용하려 할 때 한 번 실행돼요. 그런 다음 인스턴스는 후속 조회를 위해 DI 시스템이 캐시해요.

packages/app/src/apis.ts 파일의 apis 배열에 새 API 팩토리를 추가해 보아요. 내부적으로 OIDC auth 제공자를 사용하도록 지시할 거예요.

packages/app/src/apis.ts

import { OAuth2 } from '@backstage/core-app-api';export const apis: AnyApiFactory[] = [  createApiFactory({    api: keycloakAuthApiRef,    deps: {      discoveryApi: discoveryApiRef,      oauthRequestApi: oauthRequestApiRef,      configApi: configApiRef,    },    factory: ({ discoveryApi, oauthRequestApi, configApi }) =>      // delegate auth to the OAuth2 strategy      OAuth2.create({        configApi,        discoveryApi,        oauthRequestApi,        provider: {          // this value MUST be 'oidc'          // it maps our Keycloak-branded sign-in provider onto Backstage's generic OIDC auth strategy          id: 'oidc',          title: 'Keycloak',          icon: () => null,        },        environment: configApi.getOptionalString('auth.environment'),        defaultScopes: ['openid', 'profile', 'email'],        popupOptions: {          // optional, used to customize sign-in window size          size: {            fullscreen: true,          },          /**           * or specify popup width and height           * size: {              width: 1000,              height: 1000,            }           */        },      }),  }),];

Resolver

Resolver는 제3자(이 경우 Keycloak)의 사용자 ID를 Backstage 사용자 ID로 매핑하기 위해 존재해요.

기본 OIDC 제공자에는 선택할 수 있는 내장 resolver가 있으며, 구성 방법은 다음과 같아요:

app-config.yaml

auth:  environment: development  providers:    oidc:      development:        # ...        signIn:          resolvers:            - resolver: emailMatchingUserEntityProfileEmail

내장 resolver 중 어느 것도 적합하지 않으면 대안으로 커스텀 resolver를 작성할 수 있어요.

먼저 OIDC 제공자 모듈을 설치하세요:

yarn --cwd packages/backend add @backstage/plugin-auth-backend-module-oidc-provider

그런 다음 아래와 같이 커스텀 resolver를 만드세요:

in packages/backend/src/index.ts

import { createBackendModule } from '@backstage/backend-plugin-api';import {  authProvidersExtensionPoint,  createOAuthProviderFactory,} from '@backstage/plugin-auth-node';import { oidcAuthenticator } from '@backstage/plugin-auth-backend-module-oidc-provider';import {  stringifyEntityRef,  DEFAULT_NAMESPACE,} from '@backstage/catalog-model';const myAuthProviderModule = createBackendModule({  // This ID must be exactly "auth" because that's the plugin it targets  pluginId: 'auth',  // This ID must be unique, but can be anything  moduleId: 'keycloak-auth-provider',  register(reg) {    reg.registerInit({      deps: { providers: authProvidersExtensionPoint },      async init({ providers }) {        providers.registerProvider({          // This ID must match the actual provider config, e.g. addressing          // auth.providers.keycloak means that this must be "keycloak".          providerId: 'keycloak',          // Use createProxyAuthProviderFactory instead if it's one of the proxy          // based providers rather than an OAuth based one          factory: createOAuthProviderFactory({            // For more info about authenticators please see https://backstage.io/docs/auth/add-auth-provider/#adding-an-oauth-based-provider            authenticator: oidcAuthenticator,            async signInResolver(info, ctx) {              const userRef = stringifyEntityRef({                kind: 'User',                name: info.result.fullProfile.userinfo.sub,                namespace: DEFAULT_NAMESPACE,              });              return ctx.issueToken({                claims: {                  sub: userRef, // The user's own identity                  ent: [userRef], // A list of identities that the user claims ownership through                },              });            },          }),        });      },    });  },});//...backend.add(import('@backstage/plugin-auth-backend'));backend.add(myAuthProviderModule);//...

resolver에 대한 더 자세한 설명은 Identity Resolver 페이지를 확인하세요.

구성

이제 Keycloak 서버와 통신할 수 있도록 Backstage에서 Keycloak 브랜딩 OIDC Auth 제공자를 구성하겠어요.

첫 번째 단계는 Keycloak 서버에 Backstage용 OIDC 클라이언트 앱을 등록하는 것이에요.

그런 다음 제공자를 구성해야 해요. plugins/auth-backend/src/providers/oidc/provider.ts의 제공자 코드를 기반으로 app-config.yaml에 다음 매개변수가 필요해요:

app-config.yaml

auth:  environment: development  session:    secret: ${AUTH_SESSION_SECRET}  providers:    oidc:      development:        metadataUrl: https://example.com/.well-known/openid-configuration        clientId: ${AUTH_OIDC_CLIENT_ID}        clientSecret: ${AUTH_OIDC_CLIENT_SECRET}

${}로 둘러싸인 것은 YAML에서 직접 대체하거나 환경 변수로 제공할 수 있어요.

필수 매개변수

이 매개변수는 항상 설정해야 해요.

  • clientId: Overview 페이지에서 가져오세요.

  • clientSecret: 시크릿을 만들 때만 볼 수 있어요. 잃어버리면 새 시크릿이 필요해요.

  • metadataUrl: Overview > Endpoints 탭에서 OpenID Connect metadata document URL을 가져오세요.

OIDC 제공자는 auth.session.secret이 설정되는 것도 요구해요.

선택 매개변수

이 매개변수에는 암시적 기본값이 있어요. 무엇을 하고 있는지 알지 못하면 재정의하지 마세요.

  • authorizationUrl과 tokenUrl: 브라우저에서 metadataUrl을 열면 그 json에 이 2개의 URL이 어딘가 들어 있어요.

  • tokenEndpointAuthMethod

  • tokenSignedResponseAlg

  • scope: 제공자의 팩토리에서 defaultScopes를 지정하지 않은 경우에만 사용되며, 기본적으로 같은 것.

  • prompt: 사용자에게 활성 세션이 없으면 브라우저가 IDP에 sign-in을 요청하도록 auto를 사용하는 것이 권장됨.

  • sessionDuration: 사용자 세션의 수명.

  • startUrlSearchParams: OIDC 인가 시작 URL을 위한 검색(쿼리) 매개변수 사전. ID 공급자의 동작을 바꾸고 싶지 않으면 정의하지 마세요. (예를 들어 조직이 선호하는 특정 sign-in 옵션으로 사용자를 안내하도록 organization 매개변수를 설정할 수 있어요.) 참고: 시작 URL은 브라우저가 제어하므로 이 기능은 Backstage 사용자 경험을 개선하기 위한 것뿐이에요.

Config Reloading

Backstage는 아직 auth 제공자 구성의 핫 리로딩을 지원하지 않아요. 이 YAML 파일의 변경 사항은 Backstage를 다시 시작해야 합니다.

Sign-In 페이지

마지막 단계는 사용자가 새 제공자로 sign-in할 수 있도록 제공자를 sign-in 페이지에 추가하는 것이에요.

표준 Backstage SignInPage 컴포넌트를 사용한다면 다음과 같이 providers 배열에 추가할 수 있어요:

in packages/app/src/identityProviders.ts

export const providers = [  // other providers...  {    id: 'keycloak-auth-provider',    title: 'Keycloak',    message: 'Sign In using Keycloak',    apiRef: keycloakAuthApiRef,  },];

참고

이 단계는 대부분의 auth 제공자에 적용됩니다. 제공자 간의 주요 차이는 API 팩토리의 내용, Auth Provider Factory의 코드, resolver, 그리고 각 제공자가 YAML 구성이나 환경 변수에서 필요로 하는 서로 다른 변수들입니다.

더 알아보기 (Learn more)