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/ApplicationRoleIdentity 스택 등록- Cookie 인증 (Blazor 기본) + JWT Bearer 인증 (API 전용) 이중 등록
IJwtTokenService,ITenantResolverScoped 등록
사용 예시:
// 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!"
}
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
username | string | ✅ | 사용자 이름 |
password | string | ✅ | 비밀번호 |
응답 (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
| 속성 | 타입 | 설명 |
|---|---|---|
FullName | string? | 사용자 전체 이름 |
CreatedAt | DateTime | 계정 생성 시각 (UTC, 자동 설정) |
IsActive | bool | 계정 활성화 여부 (기본: true) |
TenantId | string? | 소속 테넌트 ID (null = 슈퍼 관리자/싱글 테넌트) |
RefreshToken | string? | 현재 유효한 Refresh Token |
RefreshTokenExpiryTime | DateTime? | Refresh Token 만료 시각 (UTC) |
ApplicationUser는IMultiTenantEntity를 구현하여 멀티 테넌트 필터링을 지원합니다.
ApplicationRole
ASP.NET Core IdentityRole을 확장한 역할 엔티티입니다.
| 속성 | 타입 | 설명 |
|---|---|---|
Name | string | 역할 이름 |
NormalizedName | string | 정규화된 역할 이름 (대문자) |
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
| 정책 이름 | 상수 | 접근 조건 |
|---|---|---|
RequireAdministrator | CaffeineAuthorizationPolicies.RequireAdministrator | Administrator 역할 |
RequireOperatorOrAbove | CaffeineAuthorizationPolicies.RequireOperatorOrAbove | Administrator 또는 Operator |
RequireAuthenticated | CaffeineAuthorizationPolicies.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>
참고 항목
- 멀티 테넌시 API — 테넌트 인식 데이터 격리
- 아키텍처 가이드 — 인증 흐름 다이어그램
- 보안 모범 사례 — JWT 비밀 키 관리
네임스페이스: Caffeine.Identity
어셈블리: Caffeine.Identity.dll (v2.0.6)
.NET 플랫폼: .NET 10.0