생성된 관리자 SDK 사용

Firebase SQL Connect Admin SDK를 사용하면 Cloud Functions, 커스텀 백엔드 또는 자체 워크스테이션과 같은 신뢰할 수 있는 환경에서 쿼리 및 변형을 호출할 수 있습니다. 클라이언트 앱용 SDK를 생성하는 것과 마찬가지로 SQL Connect 서비스에 배포하는 스키마, 쿼리 변형을 설계할 때 커스텀 Admin SDK를 동시에 생성할 수 있습니다.SQL Connect 그런 다음 이 SDK의 메서드를 백엔드 로직 또는 관리 스크립트에 통합합니다.

다른 곳에서 언급했듯이 SQL Connect 쿼리 및 변형은 요청 시 클라이언트에서 제출되지 않습니다. 대신 배포되면 SQL Connect 작업이 Cloud Functions와 같이 서버에 저장됩니다. 즉, 쿼리 및 변형에 변경사항을 배포할 때마다 Admin SDK를 다시 생성하고 이에 의존하는 서비스를 다시 배포해야 합니다.

시작하기 전에

  • SQL Connect 스키마, 쿼리, 변형 설계에 대해 알아봅니다. 일반적인 워크플로에서는 Admin SDK를 사용하는 서비스를 포함하여 애플리케이션 코드와 동시에 개발합니다.
  • Firebase CLI 설치.

    Cloud Shell
  • 생성된 Admin SDK를 호출하려는 모든 위치에 Admin SDK for Node.js를 종속 항목으로 포함합니다.

Admin SDK 생성

SQL Connect 스키마, 쿼리, 변형을 만든 후에는 해당하는 Admin SDK를 생성할 수 있습니다.

  1. connector.yaml 파일을 열거나 만들고 adminNodeSdk 정의를 추가합니다.

    connectorId: default
    generate:
      adminNodeSdk:
        outputDir: ../../dataconnect-generated/admin-generated
        package: "@dataconnect/admin-generated"
        packageJsonDir: ../..
    

    connector.yaml 파일은 일반적으로 쿼리 및 변형 정의가 포함된 GraphQL (.gql) 파일과 같은 디렉터리에 있습니다. 클라이언트 SDK를 이미 생성한 경우 이 파일이 이미 생성되어 있습니다.

  2. SDK를 생성합니다.

    SQL Connect VS Code 확장 프로그램을 설치한 경우 생성된 SDK가 항상 최신 상태로 유지됩니다.

    그렇지 않으면 Firebase CLI를 사용합니다.

    firebase dataconnect:sdk:generate

    또는 gql 파일을 업데이트할 때 SDK를 자동으로 다시 생성하려면 다음을 실행합니다.

    firebase dataconnect:sdk:generate --watch

Admin SDK에서 작업 실행

생성된 Admin SDK에는 gql 정의에 해당하는 인터페이스와 함수가 포함되어 있으며, 이를 사용하여 데이터베이스에서 작업을 실행할 수 있습니다. 예를 들어 쿼리 getSongs와 함께 노래 데이터베이스용 SDK를 생성했다고 가정해 보겠습니다.

import { initializeApp } from "firebase-admin/app";
import { getSongs } from "@dataconnect/admin-generated";

const adminApp = initializeApp();

const songs = await getSongs(
  { limit: 4 },
  { impersonate: { unauthenticated: true } }
);

또는 커넥터 구성을 지정하려면 다음을 실행합니다.

import { initializeApp } from "firebase-admin/app";
import { getDataConnect } from "firebase-admin/data-connect";
import {
  connectorConfig,
  getSongs,
} from "@dataconnect/admin-generated";

const adminApp = initializeApp();
const adminDc = getDataConnect(connectorConfig);

const songs = await getSongs(
  adminDc,
  { limit: 4 },
  { impersonate: { unauthenticated: true } }
);

인증되지 않은 사용자 가장

Admin SDK는 신뢰할 수 있는 환경에서 실행되도록 설계되었으므로 데이터베이스에 무제한으로 액세스할 수 있습니다.

Admin SDK로 공개 작업을 실행할 때는 최소 권한 원칙에 따라 전체 관리자 권한으로 작업을 실행하지 않아야 합니다. 대신 가장된 사용자(다음 섹션 참고) 또는 가장된 인증되지 않은 사용자로 작업을 실행해야 합니다. 인증되지 않은 사용자는 PUBLIC으로 표시된 작업만 실행할 수 있습니다.

위의 예에서 getSongs 쿼리는 인증되지 않은 사용자로 실행됩니다.

사용자 가장

`impersonate` 옵션에서 `Firebase Authentication` 토큰의 일부 또는 전부를 전달하여 특정 사용자를 대신하여 작업을 실행할 수도 있습니다. 최소한 하위 클레임에서 사용자의 사용자 ID를 지정해야 합니다. (이는 auth.uid 서버 값 을(를) GraphQL 작업에서 참조할 수 있는 값과 동일합니다.)SQL Connect

사용자를 가장할 때 제공한 사용자 데이터가 GraphQL 정의에 지정된 인증 검사를 통과하는 경우에만 작업이 성공합니다.

공개적으로 액세스할 수 있는 엔드포인트에서 생성된 SDK를 호출하는 경우 엔드포인트에 인증이 필요하고 사용자를 가장하는 데 사용하기 전에 인증 토큰의 무결성을 검증하는 것이 중요합니다.

호출 가능한 Cloud Functions를 사용하는 경우 인증 토큰이 자동으로 확인되며 다음 예와 같이 사용할 수 있습니다.

import { HttpsError, onCall } from "firebase-functions/https";

export const callableExample = onCall(async (req) => {
    const authClaims = req.auth?.token;
    if (!authClaims) {
        throw new HttpsError("unauthenticated", "Unauthorized");
    }

    const favoriteSongs = await getMyFavoriteSongs(
        undefined,
        { impersonate: { authClaims } }
    );

    // ...
});

그렇지 않으면 Admin SDKverifyIdToken 메서드를 사용하여 인증 토큰을 검증하고 디코딩합니다. 예를 들어 엔드포인트가 일반 HTTP 함수로 구현되고 표준과 같이 authorization 헤더를 사용하여 Firebase Authentication 토큰 을 엔드포인트에 전달했다고 가정해 보겠습니다.

import { getAuth } from "firebase-admin/auth";
import { onRequest } from "firebase-functions/https";

const auth = getAuth();

export const httpExample = onRequest(async (req, res) => {
    const token = req.header("authorization")?.replace(/^bearer\s+/i, "");
    if (!token) {
        res.sendStatus(401);
        return;
    }
    let authClaims;
    try {
        authClaims = await auth.verifyIdToken(token);
    } catch {
        res.sendStatus(401);
        return;
    }

    const favoriteSongs = await getMyFavoriteSongs(
        undefined,
        { impersonate: { authClaims } }
    );

    // ...
});

보안되고 공개적으로 액세스할 수 없는 환경에서 데이터 이전과 같은 실제 관리 작업을 수행할 때만 검증 가능한 소스에서 발생하지 않은 사용자 ID를 지정해야 합니다.

// Never do this if end users can initiate execution of the code!
const favoriteSongs = await getMyFavoriteSongs(
  undefined,
  { impersonate: { authClaims } }
);

무제한 액세스 권한으로 실행

관리자 수준 권한이 필요한 작업을 실행하는 경우 호출에서 가장 매개변수를 생략합니다.

await upsertSong(adminDc, {
  title: songTitle_one,
  instrumentsUsed: [Instrument.VOCAL],
});

이러한 방식으로 호출된 작업은 데이터베이스에 대한 전체 액세스 권한을 갖습니다. 관리 목적으로만 사용하려는 쿼리 또는 변형이 있는 경우 @auth(level: NO_ACCESS) 지시어를 사용하여 정의해야 합니다. 이렇게 하면 관리자 수준 호출자만 이러한 작업을 실행할 수 있습니다.