snow · 2026.5.27 13:45 · 조회 1

Logto 인가(Authorization) 설정

LogtoRBACIAM인가API리소스

인증(Authentication)이 "누구인가?"를 확인한다면, 인가(Authorization)는 "무엇을 할 수 있는가?"를 결정합니다. Logto는 OAuth 2.0 기반 API 리소스 보호와 RBAC(Role-Based Access Control)를 지원합니다.


5.1 API 리소스 등록

API 리소스는 보호할 백엔드 API의 식별자(Resource Indicator)입니다. 클라이언트가 Access Token을 요청할 때 어떤 API에 접근할지 명시하는 데 사용됩니다.

API 리소스 생성

Admin Console → API resourcesCreate API resource

이름: My Backend API API Identifier (Resource): https://api.yourapp.com Token expiration: 3600 (초)

API Identifier는 실제 호출 URL일 필요는 없지만, 관례적으로 API 기본 URL을 사용합니다.

API 퍼미션(Scope) 정의

API 리소스를 생성한 후, 해당 API에서 지원하는 권한(Scope)을 정의합니다.

예시 — 블로그 API:

Scope 이름설명
read:posts게시글 조회
write:posts게시글 생성/수정
delete:posts게시글 삭제
admin:all모든 관리 권한

클라이언트에서 Access Token 요청

1import { useLogto } from '@logto/react';2 3function useApiAccess() {4  const { getAccessToken } = useLogto();5 6  const callApi = async (path: string) => {7    const token = await getAccessToken('https://api.yourapp.com');8 9    return fetch(`https://api.yourapp.com${path}`, {10      headers: { Authorization: `Bearer ${token}` },11    });12  };13 14  return { callApi };15}

5.2 RBAC 설정

RBAC(역할 기반 접근 제어)는 권한(Scope)을 역할(Role)에 묶고, 역할을 사용자에게 할당하는 방식입니다.

역할(Role) 생성

Admin Console → RolesCreate role

예시 역할 구성:

역할 이름포함 Scope설명
viewerread:posts읽기 전용
editorread:posts, write:posts작성 가능
adminread:posts, write:posts, delete:posts, admin:all전체 권한

사용자에게 역할 할당

Admin Console에서 할당:

Users → 사용자 선택 → Roles → Assign roles → viewer / editor / admin 선택

Management API로 할당:

1await fetch(2  `https://your-tenant-id.logto.app/api/users/${userId}/roles`,3  {4    method: 'POST',5    headers: {6      Authorization: `Bearer ${managementToken}`,7      'Content-Type': 'application/json',8    },9    body: JSON.stringify({ roleIds: ['role-id-editor'] }),10  }11);

Access Token payload 예시

1{2  "sub": "user-id",3  "iss": "https://your-tenant-id.logto.app/oidc",4  "aud": "https://api.yourapp.com",5  "scope": "read:posts write:posts",6  "exp": 1234567890,7  "iat": 12345642908}

5.3 백엔드 API에서 토큰 검증

Node.js/Express 예시 (jose 라이브러리)

1npm install jose
1import { createRemoteJWKSet, jwtVerify } from 'jose';2import { Request, Response, NextFunction } from 'express';3 4const JWKS_URI = 'https://your-tenant-id.logto.app/oidc/jwks';5const ISSUER = 'https://your-tenant-id.logto.app/oidc';6const AUDIENCE = 'https://api.yourapp.com';7 8const jwks = createRemoteJWKSet(new URL(JWKS_URI));9 10export async function requireAuth(req: Request, res: Response, next: NextFunction) {11  const authHeader = req.headers.authorization;12 13  if (!authHeader?.startsWith('Bearer ')) {14    return res.status(401).json({ error: 'Missing token' });15  }16 17  try {18    const { payload } = await jwtVerify(authHeader.slice(7), jwks, {19      issuer: ISSUER,20      audience: AUDIENCE,21    });22 23    req.user = {24      id: payload.sub!,25      scopes: (payload.scope as string ?? '').split(' '),26    };27 28    next();29  } catch (err) {30    res.status(401).json({ error: 'Invalid token' });31  }32}33 34export function requireScope(scope: string) {35  return (req: Request, res: Response, next: NextFunction) => {36    if (!req.user?.scopes.includes(scope)) {37      return res.status(403).json({ error: 'Insufficient permissions' });38    }39    next();40  };41}

라우터에 미들웨어 적용

1router.get('/posts', requireAuth, requireScope('read:posts'), async (req, res) => {2  res.json(await PostService.findAll());3});4 5router.post('/posts', requireAuth, requireScope('write:posts'), async (req, res) => {6  res.status(201).json(await PostService.create(req.body, req.user!.id));7});8 9router.delete('/posts/:id', requireAuth, requireScope('delete:posts'), async (req, res) => {10  await PostService.delete(req.params.id);11  res.status(204).send();12});

Python/FastAPI 예시

1from fastapi import Depends, HTTPException, status2from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials3from jose import jwt4import httpx5 6JWKS_URI = "https://your-tenant-id.logto.app/oidc/jwks"7ISSUER = "https://your-tenant-id.logto.app/oidc"8AUDIENCE = "https://api.yourapp.com"9 10security = HTTPBearer()11 12async def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)):13    async with httpx.AsyncClient() as client:14        jwks = (await client.get(JWKS_URI)).json()15    16    try:17        return jwt.decode(credentials.credentials, jwks, algorithms=["RS256"],18                          audience=AUDIENCE, issuer=ISSUER)19    except Exception:20        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token")21 22def require_scope(required_scope: str):23    async def checker(user = Depends(get_current_user)):24        if required_scope not in user.get("scope", "").split():25            raise HTTPException(status_code=403, detail="Insufficient scope")26        return user27    return checker

다음 단계

API 보호와 RBAC 설정이 완료되었습니다. 여러 조직을 지원하는 멀티 테넌트 구조를 알아보십시오.

다음: Logto 멀티 테넌트 (Organizations) — 조직 개념, 멤버 관리, 조직별 RBAC


참고: Logto Authorization — https://docs.logto.io/authorization

댓글

아직 댓글이 없습니다.

댓글을 작성하려면 로그인이 필요합니다.