From 462e1d08616970250abf5e4c8818daeecb3e51e4 Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Fri, 16 Jan 2026 11:07:16 +0700 Subject: [PATCH] =?UTF-8?q?feat:=20C=E1=BA=A5u=20h=C3=ACnh=20c=C3=A1c=20h?= =?UTF-8?q?=E1=BA=B1ng=20s=E1=BB=91=20client=20OAuth2=20v=C3=A0=20=C4=91?= =?UTF-8?q?=E1=BB=8Bnh=20tuy=E1=BA=BFn=20Traefik=20cho=20c=C3=A1c=20endpoi?= =?UTF-8?q?nt=20OIDC=20c=E1=BB=A7a=20IdentityServer.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UserInterfaceState.xcuserstate | Bin 52314 -> 53153 bytes .../Core/Constants/Constants.swift | 10 ++++++- .../Services/AuthManager.swift | 2 ++ infra/traefik/dynamic/routes.yml | 13 +++++++++ note.md | 27 +++++++++++------- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/apps/app-client-base-swift/AppClientBaseSwift/AppClientBaseSwift.xcodeproj/project.xcworkspace/xcuserdata/velikho.xcuserdatad/UserInterfaceState.xcuserstate b/apps/app-client-base-swift/AppClientBaseSwift/AppClientBaseSwift.xcodeproj/project.xcworkspace/xcuserdata/velikho.xcuserdatad/UserInterfaceState.xcuserstate index 0e6d5ed249bc04ea313d7ccf3276d741ed08bf0c..f079310fa51683fb5344d117b1ae5bc55d718fc2 100644 GIT binary patch delta 23260 zcmbrm1$-38|L}inXM4LFVnj&-aV4(A2n0wV#N987#Er<^#N93diYGyfLyH&JLUCH8 zK!H+P++Cj8yM)p&{r`Wz=lk$tm%ZEBxtaIJWahl_1M9@Pux?C- z&BqpC>#$AOc5DZ>7u$y&$4+7Auq)WF*j4N{_6PPFdyiu{jtg-TSHm@NUEBya#!YY= zd^GMW!N=p1@hNy19*!sCsdxsSgXiLTcrjjrm*TVVO1v7c!E5n4ya{i`yKxyl7w^Xh z@TK@Nd^x@X--vI*H{;*od+~kve*6G_5I>Ed!O!C7@bmbe_+R*4{2qQEe}F&4AK{Pj zm-s9EJ;5b-1fNhQR0vfLo(#5iI+;ZIB;CK8i~03wi>OiUqyh^a&{ zkwBynsYC{mNlYhZ5P3vCQB0H&+)J)Dz7_3(-Mz5^IRH#5!UKac+(d2?H<_ElP3LBF zr*R9oh1^zdCwC5aE_VsHkK51vmb;p}hP#EkgS(r%hr5@1lzWVOgL|8MpDTIJeZhUn z{mA{qN;&t=p z@#gau@RstH@s{&8@V?`1<89~d;O*xf;9cQe=l#LE!~2u>nD>PDl=qhRj`yC=V zU!6akZ_BsiJMqWxJtcfEzCV8geVPkMNK3PxH_4&+>oe|Hl8Ff1m$AKnMf^ zCBZO(vOr6qEzl7d3(N)90w;m9z(wFK@Daoc5(Vi3$xK0xAXiW-C=<*Q)Cw8}t%3!D zrGjOG<$^VWwSw;jTLgOr2L*=&#{@qLP6|#5&Ix`IToK$5+!p*HxGQ)pcrJJ$cqc@J z!-UF06``TfNN6lH5t<6kgyupEp{3ADXf3o6juzSq?SyVZci~u}pKzQoQWz^t5oQag zNrcmdg~B3Xu}~_k6*dYxg4}A|<4h1Y|W?Lw1mzWEa^@ z%EogBsYPg9TXiB9TpuIofDlGT@YOn{VMuX^q1(a=$`1l=&9(L=$+`j=mW)2 zO4Kk)nNp!tDK$!+(xMC~6UvmbqwFaM%8_!V#!%y^@svL`fto^vP@$A$8kIv8Q&p6N zl2Xl7JJn6iqvlfs)KcnO>O1OtY74cM+DYxB_EQI_W7Ln-aq2X6hB{0AO8rLNpl(xt zPhIr!UZ# z=v(w1`cL{k{eXT#Kb4vDwIw4MJw~4~U`8^d7(>R0F=m_?XU2u`WV{$}#*dlAOktv! zXeNeB4#nOgz01YnE_@gvy55JtYB6$ ztC(+@)y!6A8?&9+!R%yqF+VW7nS;zp<`i?9IitgzWzI2InQP2V<`3p2^NM-RykXul z@0gFwCs_sG3n|&Wi$4P8=1XaS6mI@aI0YwOXYZ?z-)zt98ZMjwkT8IR10-+r8)FHM zj{}JR<_e362zxbt^D)aeh+vF#JwUtx;ww9DeZbv@qrMcgz$`H<%v$YPElc6fpyu8>9VzD)6_9HYz#-eA9Ke%q_3rK`Y}(; zOZry!aJ1uiKP-@=z5*MEjmP}43D`tz5*8qRCw(vdApI!)1P~5DkQE#wYzjQ4!Xt!Z z$Z|m06V9G!DJ8X(o$fN0Io9s;!QzoaeOLlOFlonG4$Wb(WaQ9Nqzox%4{4sXL4I_c z<52RunOHVQy${O*2+@a40|-}UP-Ur$k!UG5&Ac6s`5G%rpW!LPQ zBo(mcN~|hwN~m>FQI%r!*C3-OrfT*&-=VD#}Q3Hswtglkr4qJ#VW2uja z-2bNj9&-PZI<}l+1c|SL$7hm^AiKs2Nc@{_bfY4}iE zcVa)Ve0Kpvs}I`^5N(#P1lx}t{x`lyu%lQpKy(123lJ#Qv)BoU>8GzTy{;&>lh_62 z%Ph`%KTV&ppXH35hGoxuT{d{fC>3RIzu(%^XXX%b)>E2}Nj`~dZ4)*AOLHDto z?lVaDg>06S_SiQp-M0WS8lwAw)!cHV9OppIZD8RV!+$!IR0i9D6F3jT#kl}6?Zcsl zn#tkfB3$WT;Nrt@WfrbEKr9q+adi%Z5C0n2?rwBUQS^jkyX`O4{p2BbX5r#mu&nmi zWh+-NjGD8|JAAY0@2b~jk=wq2i;ut!nB>)MMQUIAM`@uE9a3#Lx-wLjU z1tGo=wqU5t(#^#Bdwd7Saw)zA-->U;w*w>sAdvuxf~vn1--+*n+5;V33_ucD^~sb0 zH*c*&_>b%(hw&r$QT!M{VgV8dka&P3$ga3`TVKGhaV%HjKjXjP7x7E@W&8^MD}EIq zNdQR(ND4qw0U`!S8bHzklCgQddml3F3I2?w@Dw0fefV>LWU~|`uUQIjaOg&0Fq`=| zg%1SsFP$S$jv;{qWIEfq8B)urz_j$jh^(}dQQk$Pzl=GAfS~^Ed75KHC;=pgwX0mI zWwh+iG1ekNozQ?yBZdQ{KsM6Tau}gY=yNRli4lYzK#BlTEKBqZln^F_Bgb+rVM>@0 z=7a@dNmvoqgbgv8uqEsWd%^)Ar2v8YGz+lCSOJhqfK)+U2MAOj0FY{c)BvP*E#X8s z6D~+OY>PWQ#t@!_7vW9#u!dg;ka+;R18tZF*j@H?4`2@f_8t&84REu~HeT6CPzZA9 zTOyPQBf^OYB9e$AqKOzHmVhFv2S_78V4Q6Q2vj(zZQTIr0SHvHxlkj~*Bl0YgKR_J z5y?`H^cFxG5|!#@`^Ju!Jq|FIRk>)Xepx16QKm_@(f1p2n&LxCqEY~Sz{2@|8cBUw zQLf_IwnQa6_Sq4GBeXAz6e)^8W3K$%p1q@$)xT)+EJcy7M5VgVMXFqcvUXo>Qlhvg zOH>M%-vB`)^<$b7VULN!gfjs#6rB zEuxE9#IamMbQ3b7hv+3{6LW~U#5cq|Vm`5eSO}2$0D(3NFBSo0F+iYw_5q|HAOiqd z3Xo+0S-yr?Oe~Ql2B?o*0g&$iDg|gWK-&R&8K6%9mJP630BZu+0e~IZyl?zT)MPuc zlU2qY09n~b>;lNQQu{A4?Nc;&m2Atzuwe&@!))0@09oBf90AB0nRkhX=Ab7bjuStz zcTWIhZ69$GAnRla)w-6%S>hLH+r&BIJaK{e86ePEYyikcfNWYyT!iBZJ=7NL zIQ-U^9jQ)~5I2ci9Q7qjq?SXK|3N(ASh7kOMf^p?5%-`n#u5*qGCr0oAymBYp~?Yd zt6U+W`a#D76>{gd#8cuK@tk-;yd+)`uZcIrTjCu+egMd?0C@nAcK{UtR2!fc0G$lb zIDk%<+7JJN0GFd6uq9EcZBURQ0xqHWa@(L3%|u+G;+q|bN)4Zt#oI?&He<4?h|4H$ z?)p;M-b~iWIsk!Qat}cE0%RXR_5!xTUp;aG;0dib%hEd&INi@ix>%;Yfag*!I9Se}30CKXQJB~XZ zAg2IwPSzJTNh5$eg}oohoeYrE06Ejo4PxbbR#r9Dd}IWd4gTCnZWK2fAm;&c0U$pQ zaAUdh;QtFiF3NtKTEk1_FkCTKB?}8S;$^_=On5B~cF>y6&5_4!?o4^iz5-)5H;7f3 zv$8Xxnvx=}^uJ^X1{v0I>$we(VH3;n>JY=<0P+_=Sf_~GVvuz2Qip$Xpr$jyH4Lhd5j{IIEN1Kj28oylBizGndP zJKMRH-QmM!+M&YHYq=Z$4csQ~W_Hwc2OxhcMorwU5Z5+{D?HSQw-a9Pg4ZC_No^nZ zpaLD#9tI%y2WwZCC8hEt+#k6Y{!4N{50bk)sD0O1au0{dL7N=ZzBhk^yUBvP1&~KW z;E+FLPf~SsxDU9GSppBaj{x!nAW!?bPq;8_KLf~1R<+V!ao;Kky^#}o&i3IwEB+T> z582dD4-)4gJmO!_@whx5i|!RbUMtY?NDjjjL0rM%hI}3aKPbTumEq>vJQbe093D?i z4)5*XKP=lAt0~dpnf!P3c%}+^JWB;V-e{KI`yqNChv=ca&-8e#+47*-ei)?3bCJX2 zdGUN<8+qP5AAo!UD5sw{mgfgh1fVz^cpJ&G8VzlE6M2*Wjl~pR5M+U(0L2Dbgu?EJ z!S0J9jd+ppItpI9L|SOY@)G1C;Kj2dKnX~Kmjp$Ca%Gi~I$CMGOa-V678J_=;x-Fv zCa>(j1T||AR25IclX8rB)esaa90Y~Z038lc4QQaK=HI01SyBxEC5K4)z~S*yUJI|4 zJpd{KD5W?<1D&a4IHWK#-fWg+53d)XuoFuCyg9tN038NURj7s&wRsD9OB4`b=!FoJ z*c6CTnhg|?-uXdwyU0@1VFLw=PXDvInf(p%R~F(`fa(rG{LPz% zc!PJ7Jpeiapn8fkgh(mr4MF^icb|oLmv;}K1^^w|&wIdo2+&agHD)1Z@SgErDj>d) zLo{SN`I?1j^tCb5$A_x@z-Nc&{~18|C?8|lngG;P!IsbCFnm7b=^bmx=R?cpvz9$Q z)?Ay<@D)iR{xCUR^S^%>1`!PjUxRPRv0VLSB0%ns21gRK6Lvo^Qdo zq;tWIi_K-T?0if1{)cMX3 zI^Tuw${ql<0qAJO8A3m&q&i54@68_zneu)3z5ulYsC_@*k3SBeup(zUbp9khw0{_5 z_V+KOgX`0Sdb}UUoCVZden)1*RMLaF9Epj}NVTqRc39 zlvX#t7e0kG@!?bino{839aac?K7aXtXG{DQgK}Q2uqFO_R?1U`q#XR&mSR5J5+7y( z`}lAy9yBD?F&K7fV*G_;?8fPWC6VE~Pk zJ0t!v{t1Oh;b;vyqj0u|Cs~n3$mS(!k3PqTiMy{2<|6+RE4wIw!f_az=HXw3^124) zbvwz3cLQGEgxAB8Ewpa)|5Ol!gA7P8_KW)E=JJsL=D#HPc97sl1wjFvV*@mPh+y(( zg4v%53b>GC>B*3Kw(aSMI|udFalGEXJv{ZUtj@0Si%qIQ_Qsm zHUc}jFa*%bp)fKbEP(?nj4YXEsgFy;Tj_XvU%L8`Uyv!t0%$Hk z^ZEtT1kiNz0a_$iK0%(KP|@E4d4CJo{uHzQEtIv1bw-y9B>zTKDgZ1|__t(`XdQ%D z48}XXpbu+vs(kvuxf}a1K;}Fad%>BY~lmWDYolAPbIjmwzEm$aEgSKFiU@<^v z0kr%J{~@)E%giY#49rPQF3ifA87IyvNX^fhku_7cK8^HUAy@?+i(n-{D;16f7XMr# zd1m3z53CcwAv$z5f(>%nO1@wLW$Pi>DuDCr0l_xGcEJvS0)W;4v~EDKOYnnWH$b7~ zHv+WjA9HTO0r_kZt(HwqPv9R_e5i#VY-G37ZTLSazNm*^Sj#45SjLUpS0rW?J&H?Cg>3TN0>Sc*# z`B^>zLRI9@I#^C!I9#Y9)D&t7wS_uDUEv6!o={(CARH-w2oCkW0q8t{&IjlMfGz~+ zB7j1rSpv{Lfc67)0H8}Zf6Vg3b%gdpCn$4RrK9}O<^4iuA&iGB0J>e4Fw;Xv=ppoC z3ycxMC>+%PZiVUqwFaADr>SxjvlqE2jH{6MeY0 zCxq*I!Vq|baoDvzbTxZg%bvDCTUMm%g;CI!h0y?AGib`fIQjfQm?}(XTOt-hN45^2 z>-&Wn!c2f}0O)4cmLRYCBpK5v2bC9 zu#&ZK80)@QShx^y7-99-8T!Q|cW<0LZ^EbzvVdF>54r&%>jn~XEwq}1t*|**ldwf@ zPFtZl3G-OjvPm|OJ40J0WC!WO9u_P#CkS>93w9?97Ovb$gbRdA|My_w0-kUsJib+c z-NiE9!=BhY${^TvELiyaKMaB01VazI>?HhtaM=mn&BpFw+_&dA2J%%?;SM2O)$14T z6z&4(UV!fF7w#7B0qA~!9+Epy;X&aMSb#fO2y;0wU>sn3d5rDlLD{7I5u;BE&;A?U zbHej1-opSrGKlvgBzFmto11UM`xRbah1Uo3Ewp|U!t@zS@ur;Ou`lZPtW=K^{>63* z&VuF)b?O0YA`gX+gpY+!ginRfgwKU9gfE4!gs+8fgl~oK0D1zTKLPY4Ku-bmG(cgi z&jR!uK+gm80zjdG{sPd80KFtDFKDnJMI;T4n}k1crH^C)di5VZf>c%bh+h+x%0DN| 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%0A38p5-uWK{=AFHq`Zk3>lt{PUQTBTlP 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

diff --git a/apps/app-client-base-swift/AppClientBaseSwift/AppClientBaseSwift/Core/Constants/Constants.swift b/apps/app-client-base-swift/AppClientBaseSwift/AppClientBaseSwift/Core/Constants/Constants.swift index c857cd39..28ab91ee 100644 --- a/apps/app-client-base-swift/AppClientBaseSwift/AppClientBaseSwift/Core/Constants/Constants.swift +++ b/apps/app-client-base-swift/AppClientBaseSwift/AppClientBaseSwift/Core/Constants/Constants.swift @@ -26,9 +26,17 @@ enum APIConfig { /// OAuth2 token endpoint (không có version prefix) static let tokenEndpoint = "/connect/token" + /// OAuth2 client ID for password grant + /// OAuth2 client ID cho password grant + static let oauthClientId = "password-client" + + /// OAuth2 client secret for password grant + /// OAuth2 client secret cho password grant + static let oauthClientSecret = "password-client-secret" + /// OAuth2 scope for authentication /// OAuth2 scope cho xác thực - static let oauthScope = "openid profile email offline_access" + static let oauthScope = "openid profile email api offline_access" /// Request timeout in seconds /// Thời gian timeout request (giây) diff --git a/apps/app-client-base-swift/AppClientBaseSwift/AppClientBaseSwift/Services/AuthManager.swift b/apps/app-client-base-swift/AppClientBaseSwift/AppClientBaseSwift/Services/AuthManager.swift index 90a15b19..6204c40b 100644 --- a/apps/app-client-base-swift/AppClientBaseSwift/AppClientBaseSwift/Services/AuthManager.swift +++ b/apps/app-client-base-swift/AppClientBaseSwift/AppClientBaseSwift/Services/AuthManager.swift @@ -121,6 +121,8 @@ final class AuthManager: ObservableObject { // OAuth2 Password Grant let formData: [String: String] = [ "grant_type": "password", + "client_id": APIConfig.oauthClientId, + "client_secret": APIConfig.oauthClientSecret, "username": email, "password": password, "scope": APIConfig.oauthScope diff --git a/infra/traefik/dynamic/routes.yml b/infra/traefik/dynamic/routes.yml index 8fb0eccd..3f261a58 100644 --- a/infra/traefik/dynamic/routes.yml +++ b/infra/traefik/dynamic/routes.yml @@ -22,6 +22,19 @@ http: entryPoints: - web + # EN: IdentityServer OAuth2/OIDC Endpoints + # VI: IdentityServer OAuth2/OIDC Endpoints + iam-oidc-router: + rule: "PathPrefix(`/connect`) || PathPrefix(`/.well-known`)" + service: iam-service + priority: 150 + middlewares: + - auth-ratelimit + - cors + - secure-headers + entryPoints: + - web + web-admin-router: rule: "Host(`admin.goodgo.vn`) || Host(`admin.localhost`)" service: web-admin diff --git a/note.md b/note.md index 00b2854b..597df68a 100644 --- a/note.md +++ b/note.md @@ -5,18 +5,23 @@ Mật Khẩu: Velik@2026 admin@goodgo.com / 123456 dotnet build -c Debug -f net10.0-ios -t:Run -p:_DeviceName=:v2:udid=D8A27496-0AFB-4314-96EC-E8B685575330 -curl -s -X POST "http -://localhost:5001/connect/token" \ -> -H "Content-Type: application/x-www-fo -rm-urlencoded" \ -> -d "grant_type=password" \ -> -d "client_id=password-client" \ -> -d "client_secret=password-client-secret" \ -> -d "username=hongochai10@icloud.com" \ +curl -s -X POST "http://localhost:5001/connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=password" \ + -d "client_id=password-client" \ + -d "client_secret=password-client-secret" \ + -d "username=hongochai10@icloud.com" \ + -d "password=Velik@2026" \ + -d "scope=openid profile email api offline_access" 2>&1 | jq . -> -d "password=Velik@2026" \ -> -d "scope=openid profile email api offline_access" 2> -&1 | jq . +curl -s -X POST "http://localhost/connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=password" \ + -d "client_id=password-client" \ + -d "client_secret=password-client-secret" \ + -d "username=hongochai10@icloud.com" \ + -d "password=Velik@2026" \ + -d "scope=openid profile email api offline_access" 2>&1 | jq . 1. Kiểm tra hỗ trợ cho MSSQL, PSQL, MongoDB