@@ -29,17 +29,34 @@ func NewAuth() *Auth {
2929}
3030
3131func (a * Auth ) Login (ctx context.Context , localPhone string , otpCallback OTPCallback ) (* model.Session , error ) {
32- a .mu .Lock ()
33- defer a .mu .Unlock ()
34-
3532 fullPhone := "62" + localPhone
36-
3733 session := & model.Session {
3834 Phone : localPhone ,
3935 FullPhone : fullPhone ,
4036 State : model .StateLoggingIn ,
4137 }
4238
39+ if err := a .RequestOTP (ctx , session ); err != nil {
40+ return nil , err
41+ }
42+
43+ log .Println ("[Login] Waiting for OTP from user..." )
44+ otp , err := otpCallback ()
45+ if err != nil {
46+ return nil , fmt .Errorf ("OTP callback: %w" , err )
47+ }
48+
49+ if err := a .SubmitOTP (ctx , session , otp ); err != nil {
50+ return nil , err
51+ }
52+
53+ return session , nil
54+ }
55+
56+ func (a * Auth ) RequestOTP (ctx context.Context , session * model.Session ) error {
57+ a .mu .Lock ()
58+ defer a .mu .Unlock ()
59+
4360 c := & http.Client {
4461 CheckRedirect : func (req * http.Request , via []* http.Request ) error {
4562 return http .ErrUseLastResponse
@@ -61,7 +78,7 @@ func (a *Auth) Login(ctx context.Context, localPhone string, otpCallback OTPCall
6178 "Sec-Fetch-Site" : []string {"same-site" },
6279 "Sec-Fetch-Mode" : []string {"cors" },
6380 "Sec-Fetch-Dest" : []string {"empty" },
64- "Am-Phonenumber" : []string {"+" + fullPhone },
81+ "Am-Phonenumber" : []string {"+" + session . FullPhone },
6582 "Am-Clientid" : []string {clientID },
6683 "Am-Send" : []string {"otp" },
6784 "Content-Type" : []string {"application/json" },
@@ -77,21 +94,21 @@ func (a *Auth) Login(ctx context.Context, localPhone string, otpCallback OTPCall
7794 req1 .Header = headers1
7895 resp1 , err := c .Do (req1 )
7996 if err != nil {
80- return nil , fmt .Errorf ("request OTP post: %w" , err )
97+ return fmt .Errorf ("request OTP post: %w" , err )
8198 }
8299 defer resp1 .Body .Close ()
83100
84101 if resp1 .StatusCode != 200 {
85102 b , _ := io .ReadAll (resp1 .Body )
86- return nil , fmt .Errorf ("request OTP status %d: %s" , resp1 .StatusCode , string (b ))
103+ return fmt .Errorf ("request OTP status %d: %s" , resp1 .StatusCode , string (b ))
87104 }
88105
89106 var authResp1 struct {
90107 AuthId string `json:"authId"`
91108 Callbacks []any `json:"callbacks"`
92109 }
93110 if err := json .NewDecoder (resp1 .Body ).Decode (& authResp1 ); err != nil {
94- return nil , fmt .Errorf ("decode OTP response: %w" , err )
111+ return fmt .Errorf ("decode OTP response: %w" , err )
95112 }
96113
97114 amlbcookie := ""
@@ -101,15 +118,27 @@ func (a *Auth) Login(ctx context.Context, localPhone string, otpCallback OTPCall
101118 }
102119 }
103120
104- log .Println ("[Login] Waiting for OTP from user..." )
105- otp , err := otpCallback ()
106- if err != nil {
107- return nil , fmt .Errorf ("OTP callback: %w" , err )
121+ session .PendingAuthId = authResp1 .AuthId
122+ session .PendingAmlbCookie = amlbcookie
123+ session .State = model .StateAwaitingOTP
124+ return nil
125+ }
126+
127+ func (a * Auth ) SubmitOTP (ctx context.Context , session * model.Session , otp string ) error {
128+ a .mu .Lock ()
129+ defer a .mu .Unlock ()
130+
131+ c := & http.Client {
132+ CheckRedirect : func (req * http.Request , via []* http.Request ) error {
133+ return http .ErrUseLastResponse
134+ },
108135 }
136+ userAgent := []string {config .AuthUserAgent }
137+ authURL := fmt .Sprintf ("%s/iam/v1/realms/%s/authenticate?authIndexType=service&authIndexValue=phoneLogin" , config .CiamBaseURL , config .CiamRealm )
109138
110139 log .Println ("[Login] Submitting OTP..." )
111140 reqBody2Map := map [string ]interface {}{
112- "authId" : authResp1 . AuthId ,
141+ "authId" : session . PendingAuthId ,
113142 "callbacks" : []map [string ]interface {}{
114143 {
115144 "type" : "PasswordCallback" ,
@@ -148,28 +177,28 @@ func (a *Auth) Login(ctx context.Context, localPhone string, otpCallback OTPCall
148177 "Accept-Language" : []string {"id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7" },
149178 "Priority" : []string {"u=1, i" },
150179 }
151- if amlbcookie != "" {
152- headers2 .Set ("Cookie" , amlbcookie )
180+ if session . PendingAmlbCookie != "" {
181+ headers2 .Set ("Cookie" , session . PendingAmlbCookie )
153182 }
154183
155184 req2 , _ := http .NewRequestWithContext (ctx , "POST" , authURL , bytes .NewReader (reqBody2Bytes ))
156185 req2 .Header = headers2
157186 resp2 , err := c .Do (req2 )
158187 if err != nil {
159- return nil , fmt .Errorf ("submit OTP post: %w" , err )
188+ return fmt .Errorf ("submit OTP post: %w" , err )
160189 }
161190 defer resp2 .Body .Close ()
162191
163192 if resp2 .StatusCode != 200 {
164193 b , _ := io .ReadAll (resp2 .Body )
165- return nil , fmt .Errorf ("submit OTP status %d: %s" , resp2 .StatusCode , string (b ))
194+ return fmt .Errorf ("submit OTP status %d: %s" , resp2 .StatusCode , string (b ))
166195 }
167196
168197 var authResp2 struct {
169198 TokenId string `json:"tokenId"`
170199 }
171200 if err := json .NewDecoder (resp2 .Body ).Decode (& authResp2 ); err != nil {
172- return nil , fmt .Errorf ("decode submit OTP response: %w" , err )
201+ return fmt .Errorf ("decode submit OTP response: %w" , err )
173202 }
174203
175204 iPlanetCookie := ""
@@ -206,8 +235,8 @@ func (a *Auth) Login(ctx context.Context, localPhone string, otpCallback OTPCall
206235 "Sec-Fetch-Dest" : []string {"empty" },
207236 }
208237 cookies3 := []string {}
209- if amlbcookie != "" {
210- cookies3 = append (cookies3 , amlbcookie )
238+ if session . PendingAmlbCookie != "" {
239+ cookies3 = append (cookies3 , session . PendingAmlbCookie )
211240 }
212241 if iPlanetCookie != "" {
213242 cookies3 = append (cookies3 , iPlanetCookie )
@@ -220,7 +249,7 @@ func (a *Auth) Login(ctx context.Context, localPhone string, otpCallback OTPCall
220249 req3 .Header = headers3
221250 resp3 , err := c .Do (req3 )
222251 if err != nil {
223- return nil , fmt .Errorf ("authorize get: %w" , err )
252+ return fmt .Errorf ("authorize get: %w" , err )
224253 }
225254 defer resp3 .Body .Close ()
226255
@@ -233,7 +262,7 @@ func (a *Auth) Login(ctx context.Context, localPhone string, otpCallback OTPCall
233262 }
234263 }
235264 if code == "" {
236- return nil , fmt .Errorf ("could not extract code from authorize redirect. Location: %s" , location )
265+ return fmt .Errorf ("could not extract code from authorize redirect. Location: %s" , location )
237266 }
238267
239268 log .Println ("[Login] Requesting access token..." )
@@ -269,25 +298,25 @@ func (a *Auth) Login(ctx context.Context, localPhone string, otpCallback OTPCall
269298 req4 .Header = headers4
270299 resp4 , err := c .Do (req4 )
271300 if err != nil {
272- return nil , fmt .Errorf ("access token post: %w" , err )
301+ return fmt .Errorf ("access token post: %w" , err )
273302 }
274303 defer resp4 .Body .Close ()
275304
276305 if resp4 .StatusCode != 200 {
277306 b , _ := io .ReadAll (resp4 .Body )
278- return nil , fmt .Errorf ("access token status %d: %s" , resp4 .StatusCode , string (b ))
307+ return fmt .Errorf ("access token status %d: %s" , resp4 .StatusCode , string (b ))
279308 }
280309
281310 var tokenResp struct {
282311 AccessToken string `json:"access_token"`
283312 IdToken string `json:"id_token"`
284313 }
285314 if err := json .NewDecoder (resp4 .Body ).Decode (& tokenResp ); err != nil {
286- return nil , fmt .Errorf ("decode access token response: %w" , err )
315+ return fmt .Errorf ("decode access token response: %w" , err )
287316 }
288317
289318 if tokenResp .AccessToken == "" {
290- return nil , fmt .Errorf ("access token is empty" )
319+ return fmt .Errorf ("access token is empty" )
291320 }
292321
293322 accessAuthEnc , authEnc := GenerateAuthHeaders (tokenResp .AccessToken , tokenResp .IdToken )
@@ -298,8 +327,10 @@ func (a *Auth) Login(ctx context.Context, localPhone string, otpCallback OTPCall
298327 session .Hash = util .RandomHex (28 )
299328 session .WebAppVersion = config .WebAppVersion
300329
330+ session .PendingAuthId = ""
331+ session .PendingAmlbCookie = ""
301332 session .State = model .StateLoggedIn
302333 session .LastLoginAt = time .Now ()
303334 log .Println ("[Login] ✓ Login successful, tokens captured!" )
304- return session , nil
335+ return nil
305336}
0 commit comments