@point3/logto-module 1.0.11 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +106 -47
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -125,96 +125,155 @@ export class AuthService {
125
125
 
126
126
  ### 4. stateless 네임스페이스 활용 예시
127
127
 
128
- #### 4-1. Express/Fastify 미들웨어로 토큰 인증
128
+ > ⚠️ **중요한 주의사항**
129
+ > `requiredScopes`와 `requiredRoles`에 사용되는 모든 스코프와 역할은 **반드시 Logto 관리 콘솔에서 먼저 정의되어야 합니다**.
130
+ >
131
+ > - **스코프(Scopes)**: Logto 콘솔의 API Resources → 해당 리소스 → Scopes에서 정의
132
+ > - **역할(Roles)**: Logto 콘솔의 User Management → Roles에서 정의
133
+ > - **역할-스코프 연결**: 각 역할에 필요한 스코프들을 Logto 콘솔에서 할당
134
+ >
135
+ > 코드에서 사용하는 스코프/역할 이름이 Logto에 정의되지 않았다면 토큰 검증이 실패합니다.
136
+
137
+ #### 4-1. LogtoProtected 데코레이터를 사용한 라우트 보호
129
138
 
130
139
  ```ts
131
- // main.ts
140
+ // user.controller.ts
141
+ import { Controller, Get } from '@nestjs/common';
132
142
  import { stateless } from '@point3/logto-module';
133
- import { NestFactory } from '@nestjs/core';
134
- import { AppModule } from './app.module';
135
143
 
136
- async function bootstrap() {
137
- const app = await NestFactory.create(AppModule);
138
- // JWT Bearer 토큰 인증 미들웨어 (stateless)
139
- app.use(stateless.createTokenAuthMiddleware({
140
- requiredScopes: ['admin'],
141
- requiredRoles: ['superuser'],
142
- }));
143
- await app.listen(3000);
144
- }
145
- bootstrap();
146
- ```
144
+ @Controller('users')
145
+ export class UserController {
146
+ // 기본 토큰 인증만 필요한 경우
147
+ @Get('profile')
148
+ @stateless.LogtoProtected()
149
+ getProfile() {
150
+ return { message: '인증된 사용자만 접근 가능' };
151
+ }
147
152
 
148
- #### 4-2. 커스텀 가드/핸들러에서 stateless 유틸리티 활용
153
+ // 특정 스코프가 필요한 경우
154
+ @Get('admin')
155
+ @stateless.LogtoProtected({
156
+ requiredScopes: ['admin', 'user:read']
157
+ })
158
+ getAdminData() {
159
+ return { message: '관리자 스코프가 필요한 데이터' };
160
+ }
149
161
 
150
- ```ts
151
- // custom.guard.ts
152
- import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
153
- import { stateless } from '@point3/logto-module';
162
+ // 특정 역할이 필요한 경우
163
+ @Get('management')
164
+ @stateless.LogtoProtected({
165
+ requiredRoles: ['superuser', 'management-point3']
166
+ })
167
+ getManagementData() {
168
+ return { message: '관리자 역할이 필요한 데이터' };
169
+ }
154
170
 
155
- @Injectable()
156
- export class MyStatelessGuard implements CanActivate {
157
- async canActivate(context: ExecutionContext): Promise<boolean> {
158
- const req = context.switchToHttp().getRequest();
159
- // stateless 토큰 검증 및 권한 체크
160
- const payload = await stateless.verifyRequestToken(req, {
161
- requiredScopes: ['user'],
162
- });
163
- // payload에 따라 추가 로직 가능
164
- return !!payload;
171
+ // 스코프와 역할을 모두 요구하는 경우
172
+ @Get('secure')
173
+ @stateless.LogtoProtected({
174
+ requiredScopes: ['admin'],
175
+ requiredRoles: ['superuser']
176
+ })
177
+ getSecureData() {
178
+ return { message: '고급 권한이 필요한 데이터' };
165
179
  }
166
180
  }
167
181
  ```
168
182
 
169
- #### 4-3. 커스텀 데코레이터로 유저 정보 추출
183
+ #### 4-2. 커스텀 데코레이터로 유저 정보 추출
170
184
 
171
185
  ```ts
172
186
  // user.decorator.ts
173
187
  import { createParamDecorator, ExecutionContext } from '@nestjs/common';
174
- import { stateless } from '@point3/logto-module';
175
188
 
176
189
  export const CurrentUser = createParamDecorator(
177
- async (data, ctx: ExecutionContext) => {
178
- const req = ctx.switchToHttp().getRequest();
179
- const payload = await stateless.verifyRequestToken(req);
180
- return payload;
190
+ (data: unknown, ctx: ExecutionContext) => {
191
+ const request = ctx.switchToHttp().getRequest();
192
+ // LogtoTokenGuard가 request.user에 설정한 사용자 정보 반환
193
+ return request.user;
181
194
  },
182
195
  );
183
196
 
184
197
  // 컨트롤러에서 사용
185
- @Get('me')
186
- getMe(@CurrentUser() user) {
187
- return user;
198
+ @Controller('me')
199
+ export class MeController {
200
+ @Get()
201
+ @stateless.LogtoProtected()
202
+ getMe(@CurrentUser() user: any) {
203
+ return {
204
+ userId: user.userId,
205
+ managerId: user.managerId,
206
+ clientId: user.clientId
207
+ };
208
+ }
188
209
  }
189
210
  ```
190
211
 
191
- #### 4-4. NestJS Provider로 stateless 가드 등록
212
+ #### 4-3. 전역 가드로 LogtoTokenGuard 등록
192
213
 
193
214
  ```ts
194
215
  // app.module.ts
195
216
  import { Module } from '@nestjs/common';
217
+ import { APP_GUARD } from '@nestjs/core';
196
218
  import { stateless } from '@point3/logto-module';
197
219
 
198
220
  @Module({
199
221
  providers: [
200
222
  {
201
- provide: 'STATLESS_GUARD',
202
- useClass: stateless.StatelessTokenGuard,
223
+ provide: APP_GUARD,
224
+ useClass: stateless.LogtoTokenGuard,
203
225
  },
204
226
  ],
205
227
  })
206
228
  export class AppModule {}
207
229
  ```
208
230
 
209
- #### 4-5. 직접 토큰 검증/유저 정보 추출 (서비스/핸들러 등)
231
+ #### 4-4. 커스텀 가드에서 LogtoTokenGuard 확장
210
232
 
211
233
  ```ts
234
+ // custom.guard.ts
235
+ import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
212
236
  import { stateless } from '@point3/logto-module';
213
237
 
214
- async function handleRequest(req) {
215
- const payload = await stateless.verifyRequestToken(req);
216
- if (!payload) throw new Error('인증 실패');
217
- // payload.sub, payload.userRoles 활용
238
+ @Injectable()
239
+ export class CustomLogtoGuard extends stateless.LogtoTokenGuard {
240
+ async canActivate(context: ExecutionContext): Promise<boolean> {
241
+ // 기본 토큰 검증 수행
242
+ const isValid = await super.canActivate(context);
243
+
244
+ if (!isValid) return false;
245
+
246
+ // 추가 커스텀 로직
247
+ const request = context.switchToHttp().getRequest();
248
+ const user = request.user;
249
+
250
+ // 예: 특정 시간대에만 접근 허용
251
+ const currentHour = new Date().getHours();
252
+ if (currentHour < 9 || currentHour > 18) {
253
+ return false;
254
+ }
255
+
256
+ return true;
257
+ }
258
+ }
259
+ ```
260
+
261
+ #### 4-5. 타입 안전성을 위한 역할 타입 정의
262
+
263
+ ```ts
264
+ // types/roles.ts
265
+ export type UserRole = 'admin' | 'user' | 'moderator';
266
+
267
+ // 컨트롤러에서 타입 안전하게 사용
268
+ @Controller('typed')
269
+ export class TypedController {
270
+ @Get('admin-only')
271
+ @stateless.LogtoProtected<UserRole>({
272
+ requiredRoles: ['admin'] // 타입 체크됨
273
+ })
274
+ getAdminData() {
275
+ return { message: '타입 안전한 역할 기반 접근 제어' };
276
+ }
218
277
  }
219
278
  ```
220
279
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@point3/logto-module",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "description": "포인트3 내부 logto Authentication 모듈입니다",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",