로그인 STA 스레드화·SSO 로그아웃·UserInfo 역직렬화 수정 및 AuthTest 추가

- LoginWindow: 로그인/로그아웃/쿠키삭제를 전용 STA 스레드(자체 Dispatcher 펌프)에서 실행
  → SignIn/SignInAsync가 MTA/STA 어느 스레드에서 호출돼도 동작 (RunOnDedicatedUiThreadAsync, AuthenticateAsync)
- SsoClient: 로그인/로그아웃 창을 AuthenticateAsync로 호출, 크로스스레드 Owner 제거
- BaronSSO: SignIn/SignOut을 Task.Run(...).GetAwaiter().GetResult()로 정리, SignInAsync 데드락 주석 추가
- UserInfo: private set 프로퍼티에 [JsonInclude] 적용 → FromSsoFile 역직렬화 복원 정상화, LastAuthTime [JsonIgnore]
- AuthTest 샘플 프로젝트 추가

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-16 19:20:12 +09:00
parent a15cab4bc9
commit dd2c4e4975
14 changed files with 277 additions and 45 deletions

View File

@@ -41,11 +41,8 @@ namespace BaronSoftware.SSO
$"&code_challenge={PKCEUtil.Challenge(verifier)}&code_challenge_method=S256" +
$"&state={state}&nonce={nonce}";
var window = new LoginWindow(authorizeUrl, options.RedirectUri);
if (Application.Current?.MainWindow is { } owner && !ReferenceEquals(owner, window))
window.Owner = owner;
var redirected = await window.ShowAndGetRedirectAsync();
// 전용 STA 스레드에서 로그인 창을 띄운다(호출 스레드가 MTA/STA 무엇이든 동작).
var redirected = await LoginWindow.AuthenticateAsync(authorizeUrl, options.RedirectUri);
var q = PKCEUtil.ParseQuery(redirected);
if (q.TryGetValue("error", out var error))
@@ -124,13 +121,10 @@ namespace BaronSoftware.SSO
$"&post_logout_redirect_uri={Uri.EscapeDataString(options.PostLogoutRedirectUri)}" +
$"&state={PKCEUtil.RandomToken()}";
var window = new LoginWindow(url, options.PostLogoutRedirectUri);
if (Application.Current?.MainWindow is { } owner && !ReferenceEquals(owner, window))
window.Owner = owner;
try
{
await window.ShowAndGetRedirectAsync();
// 전용 STA 스레드에서 로그아웃(end_session) 창을 띄운다.
await LoginWindow.AuthenticateAsync(url, options.PostLogoutRedirectUri);
}
catch (OperationCanceledException)
{