본문으로 건너뛰기

Hasura 애플리케이션에 인증 (Authentication)을 추가하세요

Hasura는 데이터에 맞는 GraphQL 및 REST API 를 빠르게 제공할 수 있는 도구입니다. 데이터 보안을 고려하여, Hasura 는 각기 다른 API 에 대한 접근 제어를 세밀하게 조정할 수 있는 기능도 제공합니다.

보통 Hasura 사용자들은 Logto 와 같은 다른 아이덴티티 관리 및 인증 서비스를 활용합니다. Logto 는 그 중에서도 매우 인기 있는 서비스입니다.

이 블로그 게시물에서는 이미 Hasura 서비스를 사용하고 있다고 가정하고, Hasura 와 Logto 를 통합하여 데이터의 보안을 극대화하는 방법을 소개하겠습니다. Logto 계정이 없다면, 지금 가입하고 사용을 시작하세요!

배경

Hasura 는 역할 기반 접근 관리를 사용하며, Logto 는 표준 역할 기반 접근 제어 (RBAC)를 사용합니다.

Logto 의 모델과 RBAC 에 대한 모범 사례에서, 우리는 사용자가 scope를 사용하여 권한의 가장 세밀한 단위를 대응시키고, role을 여러 scope의 묶음으로 사용하여 편리한 일괄 작업을 수행하며, 궁극적으로 scope를 확인하여 (보통 리소스 제공자의 측면에서) 사용자가 특정 작업을 수행할 수 있는지를 검증할 것을 권장합니다.

Hasura 에서는 role이 권한의 가장 세밀한 단위에 해당하며, 권한 검사는 role에 대해 수행됩니다. 따라서 Logto 를 구성할 때, 하나의 role을 정확히 하나의 scope에 매핑하는 것을 권장합니다. 이 접근 방식은 Logto 와 Hasura 의 권한을 연결하여 혼동과 오용을 방지할 수 있습니다.

Hasura 는 Webhook 또는 JWT 를 사용하여 접근 제어를 지원할 수 있습니다. 이전 블로그 게시물에서는 Webhook 을 사용하는 방법을 소개했으며, 다음 섹션에서는 Hasura 의 JWT 모드 접근 제어를 활용하는 방법을 설명하겠습니다.

시작하기

간단한 예제로 시작해 보겠습니다. 사용자가 이미 Hasura 에서 GET /userPATCH /user라는 두 개의 API 를 가지고 있으며, 각각 user:readeruser:maintainer라는 두 개의 역할에 해당한다고 가정합니다.

1. Logto 에서 Hasura API 리소스를 생성하세요

Logto 에서 Hasura API 리소스를 생성하세요.

Hasura API

2. Logto 에서 Hasura 설정에 따라 역할을 생성하세요

1단계에서 언급한 Hasura API 리소스에 대해 두 개의 scope를 생성해야 합니다. 즉, read:usermaintain:user이며, 그런 다음 두 개의 역할을 생성합니다: user:reader ( read:user 스코프 포함)와 user:maintainer ( maintain:user 스코프 포함)로 Hasura 의 역할과 일대일로 대응합니다. 그리고 필요에 따라 이러한 역할을 Logto 사용자에게 할당합니다.

Hasura API with scopes User reader role User maintainer role

3. Hasura 환경 변수 HASURA_GRAPHQL_JWT_SECRET을 구성하여 JWT 모드를 활성화하세요

Hasura JWT 구성 옵션을 살펴보면, JWT 를 사용하여 접근 제어를 하기 전에 환경 변수 HASURA_GRAPHQL_JWT_SECRET을 추가하고 구성해야 합니다.

구성할 수 있는 다양한 옵션이 있지만, 여기서는 가장 간단한 경우를 소개합니다: jwk_url만 구성하면 됩니다. 이 값은 Logto 의 OpenID 구성 엔드포인트 (https://your.logto.domain/oidc/.well-known/openid-configuration)에서 얻을 수 있습니다.

Hasura JWT config

4. 사용자 액세스 토큰의 추가 클레임을 사용자 정의하세요

Logto 의 사용자 정의 토큰 클레임 기능을 사용하여 사용자 액세스 토큰에 추가 클레임을 추가하는 로직을 사용자 정의하세요.

User access token script

getCustomJwtClaims 메서드를 사용자 정의하여 Hasura 가 접근 제어를 구현하는 데 의존하는 JWT 에 데이터를 추가하세요. 여기에는 해당 인스턴스 동안 인가된 사용자와 관련된 데이터, 그들이 소유한 role 등이 포함될 수 있으며, 이는 context를 통해 접근할 수 있습니다.

또한 하드코딩을 피하기 위해 환경 변수 USER_DEFAULT_ROLE_NAMES를 정의했습니다.

5. Logto SDK 를 통합하세요

Logto 와 Hasura 를 구성한 후, 애플리케이션을 Logto SDK 와 통합하세요. 여기서는 사용자가 로그인한 후 Logto 에서 발급한 사용자 액세스 토큰을 미리보기 위해 React 예제를 사용합니다.

User with roles

먼저, 이전에 생성한 user:readeruser:maintainer 역할을 사용자에게 할당한 후, 해당 사용자로 로그인합니다.

const config: LogtoConfig = {
endpoint: 'http://localhost:3001',
appId: '<your-application-id>',
appSecret: '<your-application-secret>',
scopes: [
...// 기존 스코프
'read:user',
'maintain:user',
],
resources: [
...// 기존 리소스
'https://*.hasura.app/api',
],
};

사용자 액세스 토큰을 얻고 Hasura API 를 요청하세요:

const accessToken = await logto.getAccessToken('https://*.hasura.app/api');

// Hasura 에 요청을 보내기 전에
request.headers.set('Authorization', `Bearer ${accessToken}`);
request.headers.set('x-Hasura-Role', '<required-role-for-the-endpoint>');

결론

이 기사에서는 Hasura 가 지원하는 Webhook 이외의 또 다른 JWT 기반 접근 제어 방법을 제공했습니다.

Hasura 의 WebhookJWT 접근 제어 과정을 비교해 보면, Webhook 접근 방식은 모든 Hasura 요청마다 Logto 에 Webhook 을 보내고 응답을 기다리는 반면, JWT 기반 접근 방식은 JWT 가 만료될 때까지 계속 사용할 수 있습니다.

JWT 접근 방식은 네트워크 부하를 줄이고 Webhook 이 가져오는 네트워크 지연을 제거할 수 있으며, Webhook 접근 방식은 사용자 권한의 변경 사항을 실시간으로 동기화할 수 있습니다.

사용자는 이러한 결론을 바탕으로 실제 비즈니스 요구와 결합하여 적절한 접근 방식을 선택할 수 있습니다.