@@ -10,6 +10,8 @@ import {
10
10
} from "./definitions" ;
11
11
import * as crypto from "crypto" ;
12
12
13
+ import { GSASRPAuthenticator } from "./srp/srp-wrapper" ;
14
+
13
15
export class ApplePortalSessionService implements IApplePortalSessionService {
14
16
private loginConfigEndpoint =
15
17
"https://appstoreconnect.apple.com/olympus/v1/app/config?hostname=itunesconnect.apple.com" ;
@@ -174,29 +176,53 @@ For more details how to set up your environment, please execute "ns publish ios
174
176
}
175
177
176
178
private async loginCore ( credentials : ICredentials ) : Promise < void > {
179
+ const wrapper = new GSASRPAuthenticator ( credentials . username ) ;
180
+ const initData = await wrapper . getInit ( ) ;
181
+
177
182
const loginConfig = await this . getLoginConfig ( ) ;
178
- const loginUrl = `${ loginConfig . authServiceUrl } /auth/signin` ;
183
+ const loginUrl = `${ loginConfig . authServiceUrl } /auth/signin/init ` ;
179
184
const headers = {
180
185
"Content-Type" : "application/json" ,
181
186
"X-Requested-With" : "XMLHttpRequest" ,
182
187
"X-Apple-Widget-Key" : loginConfig . authServiceKey ,
183
188
Accept : "application/json, text/javascript" ,
184
189
} ;
185
- const body = {
186
- accountName : credentials . username ,
187
- password : credentials . password ,
188
- rememberMe : true ,
189
- } ;
190
190
191
- const loginResponse = await this . $httpClient . httpRequest ( {
191
+ const initResponse = await this . $httpClient . httpRequest ( {
192
192
url : loginUrl ,
193
193
method : "POST" ,
194
- body,
194
+ body : initData ,
195
195
headers,
196
196
} ) ;
197
197
198
+ const body = JSON . parse ( initResponse . response . body ) ;
199
+
200
+ const completeData = await wrapper . getComplete ( credentials . password , body ) ;
201
+
202
+ const hashcash = await this . fetchHashcash (
203
+ loginConfig . authServiceUrl ,
204
+ loginConfig . authServiceKey
205
+ ) ;
206
+
207
+ const completeUrl = `${ loginConfig . authServiceUrl } /auth/signin/complete?isRememberMeEnabled=false` ;
208
+ const completeHeaders = {
209
+ "Content-Type" : "application/json" ,
210
+ "X-Requested-With" : "XMLHttpRequest" ,
211
+ "X-Apple-Widget-Key" : loginConfig . authServiceKey ,
212
+ Accept : "application/json, text/javascript" ,
213
+ "X-Apple-HC" : hashcash || "" ,
214
+ } ;
215
+
216
+ const completeResponse = await this . $httpClient . httpRequest ( {
217
+ url : completeUrl ,
218
+ method : "POST" ,
219
+ completeHeaders,
220
+ body : completeData ,
221
+ headers : completeHeaders ,
222
+ } ) ;
223
+
198
224
this . $applePortalCookieService . updateUserSessionCookie (
199
- loginResponse . headers [ "set-cookie" ]
225
+ completeResponse . headers [ "set-cookie" ]
200
226
) ;
201
227
}
202
228
@@ -221,6 +247,23 @@ For more details how to set up your environment, please execute "ns publish ios
221
247
return config || this . defaultLoginConfig ;
222
248
}
223
249
250
+ private async fetchHashcash (
251
+ authServiceUrl : string ,
252
+ authServiceKey : string
253
+ ) : Promise < string > {
254
+ const loginUrl = `${ authServiceUrl } /auth/signin?widgetKey=${ authServiceKey } ` ;
255
+ const response = await this . $httpClient . httpRequest ( {
256
+ url : loginUrl ,
257
+ method : "GET" ,
258
+ } ) ;
259
+
260
+ const headers = response . headers ;
261
+
262
+ const bits = headers [ "X-Apple-HC-Bits" ] ;
263
+ const challenge = headers [ "X-Apple-HC-Challenge" ] ;
264
+ return makeHashCash ( bits , challenge ) ;
265
+ }
266
+
224
267
private async handleTwoFactorAuthentication (
225
268
scnt : string ,
226
269
xAppleIdSessionId : string ,
0 commit comments