본문으로 건너뛰기

Caffeine.Identity API

Caffeine Framework의 인증·인가·멀티 테넌시 모듈 API 레퍼런스입니다.

개요

Caffeine.Identity는 ASP.NET Core Identity를 기반으로 JWT 인증, RBAC 권한 관리, 멀티 테넌트 지원을 제공합니다. Blazor Server 대시보드(Cookie 인증)와 REST/gRPC API(JWT Bearer 인증)를 단일 모듈에서 통합 관리합니다.

네임스페이스: Caffeine.Identity 어셈블리: Caffeine.Identity.dll NuGet: dotnet add package NEXCODE.Caffeine.Identity .NET 버전: .NET 10.0


DI 등록

AddCaffeineIdentity()

SQLite 기반 ASP.NET Core Identity를 등록합니다. Blazor Server 프로덕션 환경에 사용합니다.

네임스페이스: Caffeine.Identity

public static IServiceCollection AddCaffeineIdentity(
this IServiceCollection services,
IConfiguration configuration)

동작:

  • ApplicationDbContext (SQLite) 등록
  • ApplicationUser / ApplicationRole Identity 스택 등록
  • Cookie 인증 (Blazor 기본) + JWT Bearer 인증 (API 전용) 이중 등록
  • IJwtTokenService, ITenantResolver Scoped 등록

사용 예시:

// Program.cs (Caffeine.Admin — Blazor Server)
builder.Services.AddCaffeineIdentity(builder.Configuration);

// appsettings.json
{
"ConnectionStrings": {
"IdentityConnection": "Data Source=identity.db"
},
"JWT": {
"ValidAudience": "https://myapp.example.com",
"ValidIssuer": "https://myapp.example.com",
"Secret": "your-256-bit-secret-key-here"
}
}

AddCaffeineIdentityInMemory()

InMemory 저장소 기반 Identity를 등록합니다. 테스트·MVP·개발 환경에 사용합니다.

public static IServiceCollection AddCaffeineIdentityInMemory(
this IServiceCollection services,
IConfiguration configuration,
IEnumerable<InMemoryUser> users)

동작:

  • SQLite 없이 InMemory UserStore/RoleStore 사용
  • JWT Bearer를 기본 인증 스킴으로 등록 (Cookie 없음)
  • 초기 사용자 시딩 (InMemoryUserSeedService 백그라운드 서비스)

사용 예시:

// Program.cs (Engine — 경량 인증)
var seedUsers = new[]
{
new InMemoryUser("admin", "Caffeine@2026!", CaffeineRoles.Administrator),
new InMemoryUser("operator", "Op@2026!", CaffeineRoles.Operator)
};

builder.Services.AddCaffeineIdentityInMemory(builder.Configuration, seedUsers);

AddCaffeineJwtAuthentication()

JWT Bearer 인증만 등록하는 경량 메서드입니다. UserManager/RoleManager/SQLite 없이 순수 JWT 검증만 구성합니다.

public static IServiceCollection AddCaffeineJwtAuthentication(
this IServiceCollection services,
IConfiguration configuration)

적합한 사용 시나리오: Engine이 외부 Identity 서버의 JWT를 검증만 할 때

// Program.cs (Caffeine.Engine)
builder.Services.AddCaffeineJwtAuthentication(builder.Configuration);

REST API 엔드포인트

AuthController (/api/auth)

JWT 토큰 발급 전용 컨트롤러입니다. JWT Bearer 스킴을 명시하여 Blazor Cookie 인증과 분리됩니다.

POST /api/auth/login

사용자 인증 후 JWT 액세스 토큰과 리프레시 토큰을 발급합니다.

인증: 불필요 ([AllowAnonymous])

요청:

{
"username": "admin",
"password": "Caffeine@2026!"
}
필드타입필수설명
usernamestring사용자 이름
passwordstring비밀번호

응답 (200 OK):

{
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"username": "admin",
"refreshToken": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4...",
"refreshTokenExpiry": "2026-03-09T09:00:00Z"
}

응답 (401 Unauthorized):

{
"success": false,
"message": "Invalid username or password"
}

POST /api/auth/refresh

만료된 액세스 토큰을 리프레시 토큰으로 갱신합니다.

인증: 불필요 ([AllowAnonymous])

요청:

{
"token": "만료된_액세스_토큰",
"refreshToken": "유효한_리프레시_토큰"
}

응답 (200 OK): 새 액세스 토큰 + 새 리프레시 토큰 (AuthResponse 구조 동일)

응답 (401 Unauthorized):

{
"success": false,
"message": "Invalid or expired refresh token"
}

POST /api/auth/register

새 사용자를 등록합니다. 기본 역할 Viewer가 자동 할당됩니다.

인증: 불필요 ([AllowAnonymous])

요청:

{
"username": "newuser",
"email": "newuser@example.com",
"password": "SecureP@ss1!",
"fullName": "신규 사용자"
}

응답 (200 OK):

{
"success": true,
"message": "User created successfully!"
}

응답 (409 Conflict): 이미 존재하는 사용자명


RolesController (/api/roles)

역할 관리 API입니다. Administrator 역할 보유자만 접근 가능합니다.

GET /api/roles

전체 역할 목록을 반환합니다.

인증: JWT Bearer, Administrator 역할 필요

응답 예시:

[
{ "id": "...", "name": "Administrator" },
{ "id": "...", "name": "Operator" },
{ "id": "...", "name": "Viewer" }
]

POST /api/roles

새 역할을 생성합니다.

요청 본문: "CustomRole" (문자열)


POST /api/roles/assign

사용자에게 역할을 부여합니다.

요청:

{
"username": "operator1",
"roleName": "Operator"
}

IJwtTokenService 인터페이스

JWT 토큰 생성·검증 서비스 인터페이스입니다.

네임스페이스: Caffeine.Identity.Interfaces

public interface IJwtTokenService
{
// ApplicationUser 기반 토큰 생성
string GenerateToken(ApplicationUser user, IList<string> roles);

// 경량 오버로드 — 단일 역할
string GenerateToken(string username, string role);

// 경량 오버로드 — 복수 역할
string GenerateToken(string username, IList<string> roles);

// Refresh Token 생성 (암호학적 난수 Base64)
string GenerateRefreshToken();

// 유효한 토큰 검증 → ClaimsPrincipal 반환
ClaimsPrincipal? ValidateToken(string token);

// 만료된 토큰에서 ClaimsPrincipal 추출 (갱신 시 사용)
ClaimsPrincipal? GetPrincipalFromExpiredToken(string token);
}
메서드설명
GenerateToken(user, roles)사용자 엔티티와 역할 목록으로 JWT 생성
GenerateToken(username, role)사용자명·단일 역할로 경량 JWT 생성
GenerateToken(username, roles)사용자명·복수 역할로 JWT 생성
GenerateRefreshToken()암호학적 난수 기반 Refresh Token 생성
ValidateToken(token)JWT 서명·만료 검증 → ClaimsPrincipal
GetPrincipalFromExpiredToken(token)만료 토큰에서 Principal 추출 (갱신 흐름용)

엔티티

ApplicationUser

ASP.NET Core IdentityUser를 확장한 Caffeine 사용자 엔티티입니다.

네임스페이스: Caffeine.Identity.Entities

속성타입설명
FullNamestring?사용자 전체 이름
CreatedAtDateTime계정 생성 시각 (UTC, 자동 설정)
IsActivebool계정 활성화 여부 (기본: true)
TenantIdstring?소속 테넌트 ID (null = 슈퍼 관리자/싱글 테넌트)
RefreshTokenstring?현재 유효한 Refresh Token
RefreshTokenExpiryTimeDateTime?Refresh Token 만료 시각 (UTC)

ApplicationUserIMultiTenantEntity를 구현하여 멀티 테넌트 필터링을 지원합니다.


ApplicationRole

ASP.NET Core IdentityRole을 확장한 역할 엔티티입니다.

속성타입설명
Namestring역할 이름
NormalizedNamestring정규화된 역할 이름 (대문자)

RBAC 상수 및 정책

CaffeineRoles

표준 역할 이름 상수입니다. Identity, Engine, UI 전 레이어에서 공통 참조합니다.

네임스페이스: Caffeine.Core.Constants

public static class CaffeineRoles
{
public const string Administrator = "Administrator"; // 모든 권한
public const string Operator = "Operator"; // 장비 제어·운영
public const string Viewer = "Viewer"; // 조회 전용
}
역할권한
Administrator모든 기능 접근, 역할 관리, 시스템 설정
Operator장비 제어, 설정 변경, 데이터 조회
Viewer데이터 조회 전용 (쓰기 불가)

CaffeineAuthorizationPolicies

네임스페이스: Caffeine.Identity.Authorization

정책 이름상수접근 조건
RequireAdministratorCaffeineAuthorizationPolicies.RequireAdministratorAdministrator 역할
RequireOperatorOrAboveCaffeineAuthorizationPolicies.RequireOperatorOrAboveAdministrator 또는 Operator
RequireAuthenticatedCaffeineAuthorizationPolicies.RequireAuthenticated인증된 사용자 (역할 무관)
FallbackPolicy(자동 적용)인증되지 않은 요청 전체 차단

등록 예시:

builder.Services.AddAuthorization(options =>
options.AddCaffeinePolicies());

사용 예시:

[Authorize(Policy = CaffeineAuthorizationPolicies.RequireAdministrator)]
public class AdminPage : ComponentBase { }

[Authorize(Policy = CaffeineAuthorizationPolicies.RequireOperatorOrAbove)]
public class ControlPanel : ComponentBase { }

멀티 테넌시

JwtTenantResolver

JWT 클레임에서 테넌트 ID를 해석하는 구현체입니다.

네임스페이스: Caffeine.Identity.MultiTenancy 인터페이스: ITenantResolver (Caffeine.Core.Abstractions.MultiTenancy)

// JWT 페이로드에서 테넌트 추출
// claim: "tenant_id" → TenantId

AddCaffeineIdentity() 호출 시 자동 등록됩니다. ITenantResolver를 DI로 주입하여 현재 요청의 테넌트를 확인할 수 있습니다.

public class MyService
{
private readonly ITenantResolver _tenantResolver;

public MyService(ITenantResolver tenantResolver)
=> _tenantResolver = tenantResolver;

public async Task DoWorkAsync(HttpContext context)
{
var tenantId = await _tenantResolver.ResolveAsync(context);
// tenantId == null → 슈퍼 관리자 또는 싱글 테넌트
}
}

사용 예시

curl — 로그인 및 토큰 갱신

# 1. 로그인
curl -X POST https://localhost:5001/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"Caffeine@2026!"}' \
| jq '.token'

# 2. 인증된 요청
curl https://localhost:5001/api/v1/tags \
-H "Authorization: Bearer $TOKEN"

# 3. 토큰 갱신
curl -X POST https://localhost:5001/api/auth/refresh \
-H "Content-Type: application/json" \
-d "{\"token\":\"$EXPIRED_TOKEN\",\"refreshToken\":\"$REFRESH_TOKEN\"}"

C# HttpClient — 토큰 발급 및 사용

using System.Net.Http.Json;

var httpClient = new HttpClient { BaseAddress = new Uri("https://localhost:5001") };

// 로그인
var response = await httpClient.PostAsJsonAsync("/api/auth/login", new
{
username = "admin",
password = "Caffeine@2026!"
});

var auth = await response.Content.ReadFromJsonAsync<AuthResponse>();
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", auth!.Token);

// 인증된 API 호출
var tags = await httpClient.GetFromJsonAsync<TagListResponse>("/api/v1/tags");

Blazor — 페이지 보호

@page "/admin"
@attribute [Authorize(Policy = CaffeineAuthorizationPolicies.RequireAdministrator)]

<h1>관리자 페이지</h1>

<AuthorizeView Roles="@CaffeineRoles.Administrator">
<Authorized>
<p>관리자 전용 콘텐츠</p>
</Authorized>
<NotAuthorized>
<p>접근 권한이 없습니다.</p>
</NotAuthorized>
</AuthorizeView>

참고 항목


네임스페이스: Caffeine.Identity 어셈블리: Caffeine.Identity.dll (v2.0.6) .NET 플랫폼: .NET 10.0