aboutsummaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2024-04-21 14:55:26 -0300
committerSebastian <sebasjm@gmail.com>2024-04-22 08:52:55 -0300
commiteada01727571fe0aae632696baa97bc4ab6be521 (patch)
tree9feae9659e13a6f902144486175cbf98a201ae8c /packages
parent96d0833d703a55e9a5e707dd464f85ad0c78ab0e (diff)
downloadwallet-core-eada01727571fe0aae632696baa97bc4ab6be521.tar.xz
fix challenger api
Diffstat (limited to 'packages')
-rw-r--r--packages/taler-util/src/http-client/challenger.ts67
-rw-r--r--packages/taler-util/src/http-client/types.ts8
-rw-r--r--packages/taler-util/src/http-common.ts41
-rw-r--r--packages/taler-util/src/operation.ts5
4 files changed, 92 insertions, 29 deletions
diff --git a/packages/taler-util/src/http-client/challenger.ts b/packages/taler-util/src/http-client/challenger.ts
index fa4214aa6..8d23ed273 100644
--- a/packages/taler-util/src/http-client/challenger.ts
+++ b/packages/taler-util/src/http-client/challenger.ts
@@ -4,10 +4,13 @@ import { createPlatformHttpLib } from "../http.js";
import { LibtoolVersion } from "../libtool-version.js";
import {
FailCasesByMethod,
+ RedirectResult,
ResultByMethod,
+ opFixedSuccess,
+ opKnownAlternativeFailure,
opKnownHttpFailure,
opSuccessFromHttp,
- opUnknownFailure
+ opUnknownFailure,
} from "../operation.js";
import {
AccessToken,
@@ -16,7 +19,8 @@ import {
codecForChallengeStatus,
codecForChallengerAuthResponse,
codecForChallengerInfoResponse,
- codecForChallengerTermsOfServiceResponse
+ codecForChallengerTermsOfServiceResponse,
+ codecForInvalidPinResponse,
} from "./types.js";
import { makeBearerTokenAuthHeader } from "./utils.js";
@@ -91,7 +95,12 @@ export class ChallengerHttpClient {
* https://docs.taler.net/core/api-challenger.html#post--authorize-$NONCE
*
*/
- async login(nonce: string, clientId: string, redirectUri: string, state: string | undefined) {
+ async login(
+ nonce: string,
+ clientId: string,
+ redirectUri: string,
+ state: string | undefined,
+ ) {
const url = new URL(`authorize/${nonce}`, this.baseUrl);
url.searchParams.set("response_type", "code");
url.searchParams.set("client_id", clientId);
@@ -127,17 +136,23 @@ export class ChallengerHttpClient {
*/
async challenge(nonce: string, body: Record<"email", string>) {
const url = new URL(`challenge/${nonce}`, this.baseUrl);
-
+
const resp = await this.httpLib.fetch(url.href, {
method: "POST",
body: new URLSearchParams(Object.entries(body)).toString(),
headers: {
- "Content-Type": "application/x-www-form-urlencoded"
- }
+ "Content-Type": "application/x-www-form-urlencoded",
+ },
+ redirect: "manual",
});
switch (resp.status) {
case HttpStatusCode.Ok:
return opSuccessFromHttp(resp, codecForChallengeCreateResponse());
+ case HttpStatusCode.Found:
+ const redirect = resp.headers.get("Location")!;
+ return opFixedSuccess<RedirectResult>({
+ redirectURL: new URL(redirect),
+ });
case HttpStatusCode.BadRequest:
return opKnownHttpFailure(resp.status, resp);
case HttpStatusCode.NotFound:
@@ -165,23 +180,25 @@ export class ChallengerHttpClient {
method: "POST",
body: new URLSearchParams(Object.entries(body)).toString(),
headers: {
- "Content-Type": "application/x-www-form-urlencoded"
+ "Content-Type": "application/x-www-form-urlencoded",
},
redirect: "manual",
});
switch (resp.status) {
case HttpStatusCode.Found:
- const redirect = resp.headers.get("Location")!
- const uri = new URL(redirect)
- const code = uri.searchParams.get("code")!
- return {
- type: "ok" as const,
- body: { code }
- }
- // return opSuccessFromHttp(resp, codecForChallengeCreateResponse());
+ const redirect = resp.headers.get("Location")!;
+ return opFixedSuccess<RedirectResult>({
+ redirectURL: new URL(redirect),
+ });
case HttpStatusCode.BadRequest:
return opKnownHttpFailure(resp.status, resp);
- case HttpStatusCode.NotFound:
+ case HttpStatusCode.Forbidden:
+ return opKnownAlternativeFailure(
+ resp,
+ resp.status,
+ codecForInvalidPinResponse(),
+ );
+ case HttpStatusCode.NotFound:
return opKnownHttpFailure(resp.status, resp);
case HttpStatusCode.NotAcceptable:
return opKnownHttpFailure(resp.status, resp);
@@ -210,15 +227,17 @@ export class ChallengerHttpClient {
const resp = await this.httpLib.fetch(url.href, {
method: "POST",
headers: {
- "Content-Type": "application/x-www-form-urlencoded"
+ "Content-Type": "application/x-www-form-urlencoded",
},
- body: new URLSearchParams(Object.entries({
- client_id,
- redirect_uri,
- client_secret,
- code,
- grant_type: "authorization_code",
- })).toString(),
+ body: new URLSearchParams(
+ Object.entries({
+ client_id,
+ redirect_uri,
+ client_secret,
+ code,
+ grant_type: "authorization_code",
+ }),
+ ).toString(),
});
switch (resp.status) {
case HttpStatusCode.Ok:
diff --git a/packages/taler-util/src/http-client/types.ts b/packages/taler-util/src/http-client/types.ts
index e12c2ed6b..13ef9a3e6 100644
--- a/packages/taler-util/src/http-client/types.ts
+++ b/packages/taler-util/src/http-client/types.ts
@@ -1533,7 +1533,7 @@ export const codecForChallengeCreateResponse =
export const codecForInvalidPinResponse =
(): Codec<ChallengerApi.InvalidPinResponse> =>
buildCodecForObject<ChallengerApi.InvalidPinResponse>()
- .property("ec", codecForNumber())
+ .property("ec", codecOptional(codecForNumber()))
.property("hint", codecForAny())
.property("addresses_left", codecForNumber())
.property("pin_transmissions_left", codecForNumber())
@@ -5319,17 +5319,17 @@ export namespace ChallengerApi {
// timestamp explaining when we would re-transmit the challenge the next
// time (at the earliest) if requested by the user
- next_tx_time: String;
+ next_tx_time: string;
}
export interface InvalidPinResponse {
// numeric Taler error code, should be shown to indicate the error
// compactly for reporting to developers
- ec: Integer;
+ ec?: number;
// human-readable Taler error code, should be shown for the user to
// understand the error
- hint: String;
+ hint: string;
// how many times is the user still allowed to change the address;
// if 0, the user should not be shown a link to jump to the
diff --git a/packages/taler-util/src/http-common.ts b/packages/taler-util/src/http-common.ts
index cc75debd5..d8cd36287 100644
--- a/packages/taler-util/src/http-common.ts
+++ b/packages/taler-util/src/http-common.ts
@@ -268,6 +268,47 @@ export async function readSuccessResponseJsonOrErrorCode<T>(
};
}
+export async function readResponseJsonOrErrorCode<T>(
+ httpResponse: HttpResponse,
+ codec: Codec<T>,
+): Promise<{ isError: boolean; response: T }> {
+ let respJson;
+ try {
+ respJson = await httpResponse.json();
+ } catch (e: any) {
+ throw TalerError.fromDetail(
+ TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
+ {
+ requestUrl: httpResponse.requestUrl,
+ requestMethod: httpResponse.requestMethod,
+ httpStatusCode: httpResponse.status,
+ validationError: e.toString(),
+ },
+ "Couldn't parse JSON format from response",
+ );
+ }
+ let parsedResponse: T;
+ try {
+ parsedResponse = codec.decode(respJson);
+ } catch (e: any) {
+ throw TalerError.fromDetail(
+ TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
+ {
+ requestUrl: httpResponse.requestUrl,
+ requestMethod: httpResponse.requestMethod,
+ httpStatusCode: httpResponse.status,
+ validationError: e.toString(),
+ },
+ "Response invalid",
+ );
+ }
+ return {
+ isError: !(httpResponse.status >= 200 && httpResponse.status < 300),
+ response: parsedResponse,
+ };
+}
+
+
type HttpErrorDetails = {
requestUrl: string;
requestMethod: string;
diff --git a/packages/taler-util/src/operation.ts b/packages/taler-util/src/operation.ts
index 771f5860b..e2ab9d4e4 100644
--- a/packages/taler-util/src/operation.ts
+++ b/packages/taler-util/src/operation.ts
@@ -19,6 +19,7 @@
*/
import {
HttpResponse,
+ readResponseJsonOrErrorCode,
readSuccessResponseJsonOrThrow,
readTalerErrorResponse,
} from "./http-common.js";
@@ -126,7 +127,7 @@ export async function opKnownAlternativeFailure<T extends HttpStatusCode, B>(
s: T,
codec: Codec<B>,
): Promise<OperationAlternative<T, B>> {
- const body = await readSuccessResponseJsonOrThrow(resp, codec);
+ const body = (await readResponseJsonOrErrorCode(resp, codec)).response;
return { type: "fail", case: s, body };
}
@@ -193,3 +194,5 @@ export type FailCasesByMethod<TT extends object, p extends keyof TT> = Exclude<
ResultByMethod<TT, p>,
OperationOk<any>
>;
+
+export type RedirectResult = { redirectURL: URL }