Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions eeos/docs/auth_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,85 @@ Slack OAuth2 로그인 후 추가 정보(성함, 기수, 활동상태)를 제출
- `auth/application/exception/AlreadyLinkedAccountException` : 에러 코드 4201
- `auth/application/exception/SlackMemberNotFoundException` : 에러 코드 4200
- `auth/presentation/dto/EeosSignUpRequest` : 회원가입 요청 DTO

---

## OAuth 클라이언트 등록 (ADMIN 전용)

### POST `/api/v2/auth/clients`

OAuth2 클라이언트를 등록한다. `WEB` 타입은 BCrypt 해시된 `clientSecret`이 발급되고, `APP` 타입은 발급되지 않는다.

- 인증: JWT 필수 (ADMIN 역할)
- 구현: `ClientController` → `ClientService`

#### 요청

```json
{
"clientName": "eeos-web-app",
"clientType": "WEB",
"redirectUris": [
"https://eeos.econovation.kr/callback",
"http://localhost:3000/callback"
]
}
```

| 필드 | 타입 | 필수 | 설명 |
|------|------|------|------|
| `clientName` | string | O | 클라이언트 이름 (공백 불가) |
| `clientType` | string | O | `WEB` 또는 `APP` (대소문자 무관) |
| `redirectUris` | string[] | O | 허용 리다이렉트 URI 목록. 1개 이상, 최대 10개, URI당 최대 512자 |

#### clientType 동작 차이

| clientType | 기밀 클라이언트 | clientSecret 발급 |
|------------|--------------|-----------------|
| `WEB` | O | O (BCrypt 해시 저장, 원본 1회 반환) |
| `APP` | X | X (null 반환) |

#### 응답

**HTTP 201 Created**

`clientSecret`는 `WEB` 타입일 때만 포함된다. 이후 재조회 불가 — 최초 응답에서 반드시 저장할 것.

```json
{
"success": true,
"code": "CREATE",
"data": {
"clientId": "a3f7c2d1-85b4-4e9a-bf32-1c0e7d9fa821",
"clientSecret": "xKz3Qp9mRvLs7wNt2YhJ4dUiOeAn0BfCgXvPqWmE5c"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

문서 예시에 시크릿 형태 값 노출을 피해주세요.

Line 175의 clientSecret 값은 실제 키 여부와 무관하게 비밀정보 탐지 규칙을 트리거할 수 있습니다. 플레이스홀더(예: <issued-once-secret>)로 바꾸는 편이 안전합니다.

🔧 제안 변경
-    "clientSecret": "xKz3Qp9mRvLs7wNt2YhJ4dUiOeAn0BfCgXvPqWmE5c"
+    "clientSecret": "<issued-once-secret>"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"clientSecret": "xKz3Qp9mRvLs7wNt2YhJ4dUiOeAn0BfCgXvPqWmE5c"
"clientSecret": "<issued-once-secret>"
🧰 Tools
🪛 Betterleaks (1.3.1)

[high] 175-175: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@eeos/docs/auth_README.md` at line 175, 문서에 노출된 민감한 값인 "clientSecret"의 실제
형태(예: "xKz3Qp9mRvLs7wNt2YhJ4dUiOeAn0BfCgXvPqWmE5c")를 플레이스홀더로 교체하세요: 해당 예제의
"clientSecret" 값을 실제 키처럼 보이는 문자열에서 "<issued-once-secret>" 또는
"<your-client-secret>" 같은 안전한 플레이스홀더로 바꾸고, 동일한 파일 내 유사한 예제(또는 "clientSecret"을
사용하는 다른 코드 블록)가 있으면 동일하게 대체해 보안 스캐너 트리거를 방지하십시오.

}
}
```

#### 오류

| HTTP | 코드 | 메시지 | 발생 조건 |
|------|------|--------|-----------|
| 400 | 4015 | 등록되지 않은 redirect URI입니다. | `redirectUris`가 비어있거나 10개 초과, 또는 URI가 512자 초과 |
| 403 | — | 관리자 권한 필요 | ADMIN 역할 없음 |

#### 보안 설정 근거

`SecurityFilterChainConfig`의 `authenticated` 체인에서 다음과 같이 설정되어 있다.

```java
// 매처: POST /api/v2/auth/clients를 authenticated 체인에 포함
.requestMatchers(HttpMethod.POST, "/api/v2/auth/clients")

// 권한: ADMIN 역할만 허용
requests.requestMatchers(HttpMethod.POST, "/api/v2/auth/clients").hasAnyRole(ADMIN);
```

#### 연관 컴포넌트

- `auth/presentation/controller/ClientController` : 진입점
- `auth/presentation/docs/ClientApi` : Swagger 인터페이스 (`@Tag`, `@Operation`, `@ApiResponses`)
- `auth/application/service/ClientService` : 등록 로직, 시크릿 생성 (`SecureRandom`, 32바이트, Base64url)
- `auth/application/domain/ClientType` : `WEB(confidential=true)`, `APP(confidential=false)`
- `auth/application/exception/InvalidRedirectUriException` : 에러 코드 4015
- `auth/persistence/client/ClientEntity` : JPA 엔티티 (클라이언트 + 리다이렉트 URI)

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

@Component
public class TokenResponseConverter {

public TokenResponse from(String accessToken, Long accessExpiredTime) {
return TokenResponse.builder()
.accessToken(accessToken)
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading