# WinForm Keycloak SSO Demo

这是一个完整的 WinForm 对接 Keycloak SSO 的示例项目。

## 项目结构

```
KeycloakDemo/
├── App.config              # 配置文件（Keycloak 连接参数）
├── KeycloakConfig.cs       # 配置读取类
├── PkceHelper.cs           # PKCE 密钥对生成
├── TokenStorage.cs         # Token 安全存储（DPAPI 加密）
├── TokenResponse.cs        # Token 响应模型
├── UserInfo.cs             # 用户信息模型
├── KeycloakAuthService.cs  # 核心认证服务
├── MainForm.cs             # 主窗体 UI
├── Program.cs              # 程序入口
└── packages.config         # NuGet 依赖
```

## 快速开始

### 1. 修改配置

编辑 `App.config`，修改以下配置项：

```xml
<!-- Keycloak 服务器地址 -->
<add key="Keycloak:Authority" value="https://你的keycloak地址/realms/你的realm" />

<!-- 客户端 ID -->
<add key="Keycloak:ClientId" value="你的客户端ID" />
```

### 2. 还原 NuGet 包

```bash
nuget restore KeycloakDemo.csproj
```

或在 Visual Studio 中右键项目 → "还原 NuGet 包"

### 3. 编译运行

```bash
msbuild KeycloakDemo.csproj
```

## 配置说明

| 配置项 | 说明 | 示例值 |
|--------|------|--------|
| `Keycloak:Authority` | Keycloak 服务器地址（含 realm） | `https://sso.company.com/realms/corp` |
| `Keycloak:ClientId` | 客户端 ID | `winform-legacy-app` |
| `Keycloak:Scope` | 请求的权限范围 | `openid profile email` |
| `Keycloak:CallbackPort` | 本地回调端口 | `18080` |
| `Keycloak:TokenRefreshBuffer` | Token 提前刷新秒数 | `60` |
| `Keycloak:EnableTokenCache` | 是否缓存 Token | `true` |

## Keycloak 服务端配置

在 Keycloak 管理后台创建 Client：

1. **Client ID**: `winform-legacy-app`
2. **Client Protocol**: `openid-connect`
3. **Access Type**: `public`
4. **Standard Flow Enabled**: ON
5. **Valid Redirect URIs**: `http://localhost:18080/*`
6. **PKCE Code Challenge Method**: `S256`（必须！）

## 核心流程

```
1. 用户点击登录
2. 生成 PKCE 密钥对 (code_verifier, code_challenge)
3. 打开系统浏览器 → Keycloak 登录页
4. 用户输入凭据登录
5. 浏览器回调到 localhost:18080
6. 用 code + code_verifier 换取 Token
7. 解析 id_token 获取用户信息
8. Token 加密存储到本地
```

## 依赖项

- .NET Framework 4.6.2+
- System.IdentityModel.Tokens.Jwt（JWT 解析）
