Skip to content

Commit

Permalink
Merge pull request #13 from wayke-se/feature/WD-2214/retailer-bank-id
Browse files Browse the repository at this point in the history
Feature/wd 2214/retailer bank
  • Loading branch information
boscar committed Jul 1, 2020
2 parents 5752c2a + 8ed2f21 commit dbb372a
Show file tree
Hide file tree
Showing 16 changed files with 203 additions and 88 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,16 @@ To manually set these values, to enable a more granular control over the order o
topic: "[Dealer Specific Topic]",
channel: "[Ecom Channel Name]",
},
bankIdThumbprint: "[Dealer Specific BankId Certificate Thumbprint]"
};
config.bind(newConfig);

As an example, orders originating from https://www.wayke.se will have a topic `Wayke` and a channel `wayke.se`. For orders originating from the Wayke iOS app, the topic will be `Wayke` and the channel `iOS-app`. For Android, the channel will be `Android-app`.

### Swedish BankId Thumbprint

By default Wayke's BankId certificate is used to verify customer identity. There is an optional configuration property `bankIdThumbprint` which allows for dealers to use their own BankId certificate. If the certificate's thumbprint is set that certificate will be used instead, given that it is correctly setup in the Dealer back-office.

## Using

The information flow between clients and Wayke should be in a specific order. First of all we should retrieve all order options available for a vehicle, to know how to set up the rest of the information flow.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@wayke-se/ecom",
"version": "3.0.0",
"version": "3.1.0",
"description": "A SDK to utilize Wayke e-commerce APIs",
"main": "src/index.ts",
"typings": "src/index.d.ts",
Expand Down
48 changes: 47 additions & 1 deletion src/config/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const fixtures = require("../../test/fixtures");

import Configuration, { IOriginConfiguration } from ".";
import Configuration, { IOriginConfiguration, IConfigurationRoot } from ".";

const fixture = (id: string): any => fixtures.create(id);

Expand Down Expand Up @@ -125,4 +125,50 @@ describe("Configuration", () => {
expect(origin.channel).toEqual(expected);
});
});

describe("useBankIdThumbprint()", () => {
it("throws if not bound", () => {
const config = new Configuration();
expect(() => config.useBankIdThumbprint()).toThrowError();
});
it("returns false if no thumbprint is set", () => {
const fake = fixtures.create("IConfiguration");
delete fake.bankIdThumbprint;

const config = Configuration.bind(fake);

expect(config.useBankIdThumbprint()).toBe(false);
});
it("returns false if thumbrint is empty", () => {
const fake = fixtures.create(
"IConfiguration",
(c: IConfigurationRoot) => (c.bankIdThumbprint = "")
);

const config = Configuration.bind(fake);

expect(config.useBankIdThumbprint()).toBe(false);
});
it("returns true if thumbrint is set", () => {
const fake = fixtures.create("IConfiguration");

const config = Configuration.bind(fake);

expect(config.useBankIdThumbprint()).toBe(true);
});
});

describe("getBankIdThumbprint()", () => {
it("throws if not bound", () => {
const config = new Configuration();
expect(() => config.getBankIdThumbprint()).toThrowError();
});
it("returns bound thumbprint", () => {
const fake = fixtures.create("IConfiguration");

const config = Configuration.bind(fake);

expect(config.getBankIdThumbprint()).toBe(fake.bankIdThumbprint);
});
});
});
20 changes: 20 additions & 0 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ export interface IApiConfiguration {
export interface IConfigurationRoot {
api: IApiConfiguration;
origin?: IOriginConfiguration;
bankIdThumbprint?: string;
}

export interface IConfiguration {
getApiAddress(): string;
getOrigin(): IOriginConfiguration | undefined;
useBankIdThumbprint(): boolean;
getBankIdThumbprint(): string | undefined;
}

const createDefaultOrigin = (): IOriginConfiguration | undefined => {
Expand Down Expand Up @@ -69,6 +72,7 @@ class Configuration implements IConfiguration {
channel: newConfig.origin.channel,
}
: createDefaultOrigin(),
bankIdThumbprint: newConfig.bankIdThumbprint,
};

return Configuration.instance;
Expand Down Expand Up @@ -100,6 +104,22 @@ class Configuration implements IConfiguration {

return this.config.origin;
}

public useBankIdThumbprint(): boolean {
if (!this.config) {
throw Configuration.notBoundError;
}

return !!this.config.bankIdThumbprint;
}

public getBankIdThumbprint(): string | undefined {
if (!this.config) {
throw Configuration.notBoundError;
}

return this.config.bankIdThumbprint;
}
}

export default Configuration;
4 changes: 2 additions & 2 deletions src/http/apis/bankid.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const http = require("..");
const authApi = require("./bankid/auth");
const collectApi = require("./bankid/collect");
const cancelApi = require("./bankid/cancel");
const bankidApiUtils = require("./bankid/utils");

import {
IBankIdAuthApiResponse,
Expand All @@ -15,10 +16,9 @@ import { auth, collect, cancel } from "./bankid";

describe("API: BankId", () => {
beforeAll(() => {
bankidApiUtils.createRequest = jest.fn();
authApi.getUrl = jest.fn();
authApi.buildRequest = jest.fn();
collectApi.getUrl = jest.fn();
collectApi.buildRequest = jest.fn();
cancelApi.getUrl = jest.fn();
});

Expand Down
18 changes: 1 addition & 17 deletions src/http/apis/bankid/auth.spec.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,19 @@
const fixtures = require("../../../../test/fixtures");
const fixture = (name: string): any => fixtures.create(name);

import { buildRequest, getUrl } from "./auth";
import { getUrl } from "./auth";
import Configuration from "../../../config";
import { IBankIdAuthRequest, AuthMethod } from "../../../bankid/types";
const http = require("../../");

describe("BankId Auth", () => {
let requestForgeryToken: string;
let host: string;

beforeAll(() => {
const response = fixture("IApiResponse");
http.context = jest.fn(() => ({ requestForgeryToken }));
requestForgeryToken = response.requestForgeryToken;

const fake = fixture("IConfiguration");
const config = Configuration.bind(fake);
host = config.getApiAddress();
});

describe(":buildRequest()", () => {
it("Should have request forgery token header", () => {
const request = buildRequest();
expect(request.headers).toHaveProperty(
"x-rf-token",
requestForgeryToken
);
});
});

describe(":getUrl()", () => {
it("Should be same device route, given same device method", () => {
const request = fixtures.create(
Expand Down
14 changes: 2 additions & 12 deletions src/http/apis/bankid/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,7 @@ import {
} from "../../../bankid/types";
import * as http from "../../index";
import Configuration from "../../../config/index";

export const buildRequest = (): RequestInit => {
const requestForgeryToken = http.context().requestForgeryToken;
const request = http
.builder()
.method("post")
.accept("application/json")
.requestForgeryToken(requestForgeryToken)
.build();
return request;
};
import { createRequest } from "./utils";

const getRoute = (method: AuthMethod) => {
switch (method) {
Expand All @@ -39,7 +29,7 @@ export const auth = (
requestOptions: IBankIdAuthRequest
): Promise<http.IApiResponse<IBankIdAuthApiResponse>> => {
const url = getUrl(requestOptions);
const request = buildRequest();
const request = createRequest();

return http.captureStateContext(
http.json<IBankIdAuthApiResponse>(url, request)
Expand Down
18 changes: 4 additions & 14 deletions src/http/apis/bankid/cancel.spec.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,24 @@
const fixtures = require("../../../../test/fixtures");
const fixture = (name: string): any => fixtures.create(name);

import { buildRequest, getUrl, cancel } from "./cancel";
import { getUrl, cancel } from "./cancel";
import Configuration from "../../../config";
const http = require("../../");

describe("BankId Cancel", () => {
let requestForgeryToken: string;
let host: string;

beforeAll(() => {
const response = fixture("IApiResponse");
http.context = jest.fn(() => ({ requestForgeryToken }));
requestForgeryToken = response.requestForgeryToken;
http.context = jest.fn(() => ({
requestForgeryToken: response.requestForgeryToken,
}));

const fake = fixture("IConfiguration");
const config = Configuration.bind(fake);
host = config.getApiAddress();
});

describe(":buildRequest()", () => {
it("Should have request forgery token header", () => {
const request = buildRequest();
expect(request.headers).toHaveProperty(
"x-rf-token",
requestForgeryToken
);
});
});

describe(":getUrl()", () => {
it("Should be cancel url", () => {
const orderRef = fixture("IBankIdCancelRequest").orderRef;
Expand Down
14 changes: 2 additions & 12 deletions src/http/apis/bankid/cancel.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import * as http from "../../index";
import Configuration from "../../../config/index";
import { IBankIdCancelRequest } from "../../../bankid/types";

export const buildRequest = (): RequestInit => {
const requestForgeryToken = http.context().requestForgeryToken;
const request = http
.builder()
.method("post")
.accept("application/json")
.requestForgeryToken(requestForgeryToken)
.build();
return request;
};
import { createRequest } from "./utils";

export const getUrl = (orderRef: string) => {
const host = Configuration.current().getApiAddress();
Expand All @@ -23,7 +13,7 @@ export const cancel = (
requestOptions: IBankIdCancelRequest
): Promise<Response> => {
const url = getUrl(requestOptions.orderRef);
const request = buildRequest();
const request = createRequest();

return http.raw(url, request);
};
17 changes: 1 addition & 16 deletions src/http/apis/bankid/collect.spec.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,19 @@
const fixtures = require("../../../../test/fixtures");
const fixture = (name: string): any => fixtures.create(name);

import { buildRequest, getUrl } from "./collect";
import { getUrl } from "./collect";
import Configuration from "../../../config";
const http = require("../../");

describe("BankId Collect", () => {
let requestForgeryToken: string;
let host: string;

beforeAll(() => {
const response = fixture("IApiResponse");
http.context = jest.fn(() => ({ requestForgeryToken }));
requestForgeryToken = response.requestForgeryToken;

const fake = fixture("IConfiguration");
const config = Configuration.bind(fake);
host = config.getApiAddress();
});

describe(":buildRequest()", () => {
it("Should have request forgery token header", () => {
const request = buildRequest();
expect(request.headers).toHaveProperty(
"x-rf-token",
requestForgeryToken
);
});
});

describe(":getUrl()", () => {
it("Should be collect url", () => {
const orderRef = fixture("IBankIdCollectRequest").orderRef;
Expand Down
14 changes: 2 additions & 12 deletions src/http/apis/bankid/collect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,7 @@ import {
IBankIdCollectApiResponse,
} from "../../../bankid/types";
import Configuration from "../../../config/index";

export const buildRequest = (): RequestInit => {
const requestForgeryToken = http.context().requestForgeryToken;
const request = http
.builder()
.method("post")
.accept("application/json")
.requestForgeryToken(requestForgeryToken)
.build();
return request;
};
import { createRequest } from "./utils";

export const getUrl = (orderRef: string) => {
const host = Configuration.current().getApiAddress();
Expand All @@ -26,7 +16,7 @@ export const collect = (
requestOptions: IBankIdCollectRequest
): Promise<http.IApiResponse<IBankIdCollectApiResponse>> => {
const url = getUrl(requestOptions.orderRef);
const request = buildRequest();
const request = createRequest();

return http.captureStateContext(
http.json<IBankIdCollectApiResponse>(url, request)
Expand Down

0 comments on commit dbb372a

Please sign in to comment.