)8r&*L3PA
zGNYd+_^;nNKmTI~dY_~zXvYtC&`V1XP`{HN)&XeWGrj5UlH
zZee!1VNvH+5`n^X)VT_uHU@y|7KTyy(Z?5qDg$KFEcW)=_8v;X0rL`a)!hGn@n}0a
z!pymqFnJDNAMzAKwQ-_dH6PqoTW*@0bIGbgg_4V*9x0{sQ*CWmB{
zCeF05wqYfu%aUy;K=dliZ4bLVR6F%cgcF4tU#>fXa5Jho-GFog`9%anGa*?tt#`gv51zbJFbZpG+=eKbo&brl>piU(=FUrL*v%^1KT3SwBH<`1;$<}htc5GWLgY8n5X8dRx6S|dRbF$(&MAHwb{23GZb^tG;PV4|Q)OA)CH&$x5x
z^6A@po{orr<=f}~?N`B}df>Ti>g_7WArV5DI`Trc&QEbgq*`4VnY)=@(#yaHX^V!r
zbo+-j2rVb$%#S2pGbKPbZ)8D`hqBPEdT+)>YFSB!-rhmAHjS!yyDInZtEXnXt^9c&
zU)dIgeaii;y+7{#f=8PD`~G#$CK0;|*4f0gy~S5`iK?oCG{r%CriEw#NZIGH=7QR8
zwmXwIhA$ili;#J>xLoOKaP)Xx0ZSNmFV68J@XqI6eE>l8x?q>`Q1BaA`9;IOAqO)Y
z`-g#*1AQlkop833=9a0X_WK<)qZ$4u4Kb|@w!~L`Kl_u!og!QcNMFlRtpK%V#zEKd
z9`F?8_RCfii3E^sbSIuY$PbLg3^0qTd6?^*Bz<#w{WGw(NzIxBoM71GHc$F_CCDK|
zD#O*CdpRM40kPB2W;pi&D?_|p-{Y}rB&9furJCJ_BzE`$JErD%1mj7dvytXv}NCML!)g&Fjnqns32!WA~{ZIEY3HLstQ&@55lm4W9r
zQF(g9g`z+N>UVvVsPLmnVA?8(2_dO
z@L(I;NA&Ec9)Nbkw?FG>EBUA2@XihhLMM6rL>=%s8qRV|uI%V6lvM?QfYjKZNS|Ne
z@78l?1G?&t4{^)ENK2xK9-^CxwB?9mAkdc%%1EHnd8G1N0Rx7HNbkuA0ba0V=rQ|
zVt>}Ta!mPuQ*+dDGRjJrDviGR48=Gk`%;Ca(=GQWony#EsRSr4;h~H`q$FGGaq`mN
z0DwZyyop0a|BGgrb+rK1qj#R9I2IGM%G8Jw<__NI>4HDVRC~a2h=Fb1ySb^RuQnM?
zJ4NxA<&_KVpg$Q>{)&?0%8FaV9hs%j;5pnz`j@|
zF+1rzyYz;z)9R%&42Qrj!I$v5PVFLfoL_LiQNw592kSC){6wLA+e`Y)Kxg84j{{>^
z@Z>0DC{e%GEP30%6e1XUbqvGae@NgNFM#IANo)k9cIRnP-}2$Yx*)!`Vk9l^-8)cP
zbY|#7f5HzI1};cY`6te0UR6Bp21_DRC34xzXpi|
zd63C~WVSvzthcq09*E%CyU6+|`bK3=%OTX>jFE2Cv4prn?R7&_dm--vM@dpBJi_mq
zff)M+PtK_~`vdAUqM7?cEAYVSESgJG*9K!B(QuN(-rmuxDofgKzfwBSp#PE|i(
zB;r7|D`RL7DZAc1t6Ur|vjKR`Jfw?^hWMopf~-gQb_x5M1Bd`AN?j}mkil!@f6Cn4
zo^(kIJJT5f8>jS-@>C~RTUjq%Edd5k=8o24R>e6rvl}U*Gj1E}%(c#9YC)K2;)Trs
zq1nhdW{%?n(#N^m<~mF`kvf}pW`$g*_-vMub%IZmE_Zz`Z~LzAp|PFSF46Q0+L?eU
zR9$s;^ePI#%Eh~$YwrMF2%E8g_lj`$RA*aOdZ6y51jvXoae&
z&i=gm4N$PP190>KO=ySBI<3uU@~?j8aF6-P@(kdyNFtz0JJ
zQ@%~Rl~vh9BsPFaVx^8aBBs&?T1d$$O78P%*=>GKEscN{@TSS`R^UVF%CXENN5$-)
ztYD0$Pz_a8b&dZ5YZd5+V28!WW!rA%fHsPh1k_cXku)*^;*L@u-|&T!^q3D{4?EHe
zK`Q&3!#AC|mIlEvzH}U8#w_p{EireN{skqK?Z3u}3^X8oCBHD&YyjY6pz}z`5pH38
z`fCpsLtbJ}KJQ(l_yt&!v^NYa&BvR5M7Iuzzhwf7T7=3*5kb
zYI}2TTe$^U(|^zAgOd$Qz*lFSpXRFHRhyk~u1me9r}ovMMw}xFwJIB1r0*WvO&A`}
zlHG08^aKdiACDQy$Ay}7Wi^YD^o>GJ5t>qLbrr|i?!K1$pVTQGzy4q+1TaO$(ovhX
zR8#g&(wwt{iDdO;u5r~Cj@DMeADcP(r=~LxypIWCH|VxDptC+>)vkwnk6*{CpZt;0
z>r>E773uH3AwL-RMhguH@ss@v=!CraOe|&YSELx2p1#dk!*`?kM9}#ADJp8)Nczyk
zo(~iWwwo=&)!^Z6(ZmY0I_r3P3o@MB1R7AEOT$*{j?0&=1^AhK7%)(@!weecbiwV0
z9;_g7!s+uKnhsNoXWW$nJOOZie~j}
zpDKFj?*H11EuU9S5M7kLFt`JxBTCtip}2mW%?=k_?(|to{=WMcTyTFwcpzi
zJ-Kqr`U#W%OgLK0)o;83=hbeGs9^Tdp~>1{!aOp^N5O+YQmyR3bY7N3bVtM0PXol)wjH7(C45kZYIsHj3}AV89^$9?~Ifmv%UpAd}6EvRuc@8pyq
zOpUe-bn@WX#DNrWFv6`pYgl{5C!dEw>`l`c#OC0pctZzPs8sN^vu7>n%E@{IxCX(>
zT*4$DiDgPB(Qe$DsJlf5?x0Y@eDL83eoHvn6-pp+?GzwIK+4XMnd*D
zq~MsiUX(y%+nC=i8p3g#RJAwQUK#S>>Wn+e=r}(li)P~i!*njngB8oys<#G9yj{xx
zU`wzWHOydZ>`Y)%A0o4m1$K%_Az$=B{O~txVgyUdM^*tZz+KfeXe9L1A$VU=5U5IK_-l
zR#^ENCit=Le$l?XGlXLyF!`@f_hq)x
+ /// 第三方授权客户端占位实现。接入真实第三方接口时替换此服务即可。
+ ///
+ public sealed class DefaultPcThirdPartyAuthorizationClient : IPcThirdPartyAuthorizationClient
+ {
+ ///
+ /// 验证第三方授权码是否有效。默认实现将 "invalid" 视为授权丢失,其余视为有效。
+ ///
+ /// 第三方授权码。
+ /// 取消令牌。
+ /// 授权检查结果。
+ public Task ValidateAuthorizationCodeAsync(
+ string authorizationCode,
+ CancellationToken cancellationToken = default)
+ {
+ if (string.IsNullOrWhiteSpace(authorizationCode) ||
+ string.Equals(authorizationCode, "invalid", StringComparison.OrdinalIgnoreCase))
+ {
+ return Task.FromResult(ThirdPartyAuthCheckResult.AuthorizationLost);
+ }
+
+ return Task.FromResult(ThirdPartyAuthCheckResult.Valid);
+ }
+
+ ///
+ /// 刷新第三方授权。默认实现总是返回 TemporaryFailure,表示暂时无法刷新。
+ ///
+ /// 授权引用标识。
+ /// 取消令牌。
+ /// 授权检查结果。
+ public Task RefreshAuthorizationAsync(
+ string authorizationReference,
+ CancellationToken cancellationToken = default)
+ {
+ if (string.Equals(authorizationReference, "invalid", StringComparison.OrdinalIgnoreCase))
+ {
+ return Task.FromResult(ThirdPartyAuthCheckResult.AuthorizationLost);
+ }
+
+ return Task.FromResult(ThirdPartyAuthCheckResult.TemporaryFailure);
+ }
+ }
+}
diff --git a/Authentication/PcAuthEndpointService.cs b/Authentication/PcAuthEndpointService.cs
new file mode 100644
index 0000000..270b01b
--- /dev/null
+++ b/Authentication/PcAuthEndpointService.cs
@@ -0,0 +1,94 @@
+using Authentication;
+using Avalonia_Common.Core;
+using Avalonia_Services.Core;
+using Avalonia_Services.Services.AuthService;
+using System;
+using System.Text.Json;
+using System.Threading.Tasks;
+
+namespace Avalonia_PC.Authentication
+{
+ ///
+ /// PC 端鉴权端点服务,实现 ,
+ /// 处理授权码登录、Token 刷新和登出操作。
+ ///
+ public sealed class PcAuthEndpointService(PcGlobalTokenService tokenService) : IPcAuthEndpointService
+ {
+ private static readonly JsonSerializerOptions JsonOptions = new()
+ {
+ PropertyNameCaseInsensitive = true,
+ };
+
+ ///
+ public async Task