@haus-tech/bankid-auth-plugin 1.0.1 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +114 -0
- package/package.json +7 -13
- package/src/api/api-extensions.d.ts +1 -0
- package/src/api/api-extensions.js +32 -0
- package/src/api/api-extensions.js.map +1 -0
- package/{dist → src}/bankid-auth.plugin.js +16 -13
- package/src/bankid-auth.plugin.js.map +1 -0
- package/src/bankid-auth.resolver.d.ts +25 -0
- package/{dist/bankid-auth.controller.js → src/bankid-auth.resolver.js} +52 -39
- package/src/bankid-auth.resolver.js.map +1 -0
- package/{dist → src}/constants.js +1 -0
- package/src/constants.js.map +1 -0
- package/src/index.d.ts +2 -0
- package/{dist → src}/index.js +2 -0
- package/src/index.js.map +1 -0
- package/src/services/bankid-api.service.d.ts +10 -0
- package/src/services/bankid-api.service.js +68 -0
- package/src/services/bankid-api.service.js.map +1 -0
- package/src/services/bankid-auth.service.d.ts +14 -0
- package/src/services/bankid-auth.service.js +72 -0
- package/src/services/bankid-auth.service.js.map +1 -0
- package/src/services/bankid-session.service.d.ts +13 -0
- package/src/services/bankid-session.service.js +86 -0
- package/src/services/bankid-session.service.js.map +1 -0
- package/{dist → src}/types.d.ts +21 -9
- package/{dist → src}/types.js +6 -1
- package/src/types.js.map +1 -0
- package/src/utils.d.ts +12 -0
- package/src/utils.js +77 -0
- package/src/utils.js.map +1 -0
- package/dist/bankid-auth.controller.d.ts +0 -19
- package/dist/index.d.ts +0 -1
- package/dist/services/bankid-auth.service.d.ts +0 -13
- package/dist/services/bankid-auth.service.js +0 -117
- package/dist/utils.d.ts +0 -9
- package/dist/utils.js +0 -50
- /package/{dist → src}/bankid-auth.plugin.d.ts +0 -0
- /package/{dist → src}/constants.d.ts +0 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
## 1.0.3
|
|
2
|
+
|
|
3
|
+
This was a version bump only for bankid-auth-plugin to align it with other projects, there were no code changes.
|
|
4
|
+
|
|
5
|
+
## 1.0.2
|
|
6
|
+
|
|
7
|
+
### 🚀 Features
|
|
8
|
+
|
|
9
|
+
- **bankid-auth-plugin:** Add initial implementation of BankID auth plugin ([#54](https://github.com/WeAreHausTech/haus-tech-vendure-plugins/pull/54))
|
|
10
|
+
|
|
11
|
+
### 🩹 Fixes
|
|
12
|
+
|
|
13
|
+
- **product-import-export-plugin:** improve import parser handling ([c952c7b](https://github.com/WeAreHausTech/haus-tech-vendure-plugins/commit/c952c7b))
|
|
14
|
+
|
|
15
|
+
## 1.0.1
|
|
16
|
+
|
|
17
|
+
### 🚀 Features
|
|
18
|
+
|
|
19
|
+
- Add initial implementation of BankID auth plugin (#54) ([92faf35](https://github.com/WeAreHausTech/haus-vendure-plugins-public/commit/92faf354f6009b820f192fcdd28334b5bc370cdc))
|
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bankid-auth-plugin
|
|
3
|
+
title: BankID Auth Plugin
|
|
4
|
+
description: Vendure plugin that integrates BankID authentication into your e-commerce platform.
|
|
5
|
+
version: 1.0.1
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# BankID Auth Plugin
|
|
9
|
+
|
|
10
|
+
The `BankID Auth Plugin` is a Vendure plugin that integrates BankID authentication into your e-commerce platform. BankID is a secure and widely used electronic identification system, primarily in Sweden, that allows users to authenticate themselves online.
|
|
11
|
+
|
|
12
|
+
## Functionality
|
|
13
|
+
|
|
14
|
+
- Enable secure customer authentication using BankID.
|
|
15
|
+
- Provides REST endpoints for initiating, authenticating, and canceling BankID sessions.
|
|
16
|
+
- Validates user IP addresses during authentication for enhanced security.
|
|
17
|
+
- Supports a customizable post-authentication strategy for handling successful authentications.
|
|
18
|
+
|
|
19
|
+
## Use Cases
|
|
20
|
+
|
|
21
|
+
The BankID Auth Plugin is ideal for:
|
|
22
|
+
|
|
23
|
+
- E-commerce platforms that require secure and reliable customer authentication.
|
|
24
|
+
- Businesses operating in Sweden or regions where BankID is widely used.
|
|
25
|
+
- Scenarios where IP validation and session management are critical.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
To install the `BankID Auth Plugin`, follow these steps:
|
|
30
|
+
|
|
31
|
+
1. Install the plugin package:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
yarn add @haus-tech/bankid-auth-plugin
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or, if using npm:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install @haus-tech/bankid-auth-plugin
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
2. Add the plugin to your Vendure configuration in `vendure-config.ts`:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { BankidAuthPlugin } from '@haus-tech/bankid-auth-plugin';
|
|
47
|
+
|
|
48
|
+
export const config = {
|
|
49
|
+
plugins: [
|
|
50
|
+
BankidAuthPlugin.init({
|
|
51
|
+
bankidApiUrl: 'https://api.bankid.com',
|
|
52
|
+
clientCert: '/path/to/client-cert.pem',
|
|
53
|
+
clientKey: '/path/to/client-key.pem',
|
|
54
|
+
}),
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
3. Restart your Vendure server.
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
### Admin Configuration
|
|
64
|
+
|
|
65
|
+
The plugin does not provide a direct UI-based configuration. Instead, it is configured programmatically in the Vendure configuration file.
|
|
66
|
+
|
|
67
|
+
### REST API
|
|
68
|
+
|
|
69
|
+
The plugin provides the following REST endpoints:
|
|
70
|
+
|
|
71
|
+
- `POST /api/bankid/initiate`: Starts a BankID session.
|
|
72
|
+
- `POST /api/bankid/authenticate`: Authenticates a user based on an order reference.
|
|
73
|
+
- `POST /api/bankid/cancel`: Cancels an ongoing BankID session.
|
|
74
|
+
|
|
75
|
+
### Example Integration
|
|
76
|
+
|
|
77
|
+
To integrate BankID authentication into your storefront, use the provided REST endpoints. For example:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
fetch('/api/bankid/initiate', {
|
|
81
|
+
method: 'POST',
|
|
82
|
+
headers: { 'Content-Type': 'application/json' },
|
|
83
|
+
body: JSON.stringify({ endUserIp: '192.168.1.1' }),
|
|
84
|
+
})
|
|
85
|
+
.then((res) => res.json())
|
|
86
|
+
.then((data) => {
|
|
87
|
+
console.log(data);
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Testing
|
|
92
|
+
|
|
93
|
+
1. Run `yarn test` to execute the e2e tests.
|
|
94
|
+
2. Implement additional tests to cover your specific use cases.
|
|
95
|
+
|
|
96
|
+
## Publish to NPM
|
|
97
|
+
|
|
98
|
+
1. Make sure you are [logged in to NPM](https://docs.npmjs.com/cli/v9/commands/npm-login).
|
|
99
|
+
2. Build the plugin:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
yarn build
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
3. Publish the plugin:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
yarn publish
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Resources
|
|
112
|
+
|
|
113
|
+
- [Vendure Plugin Documentation](https://www.vendure.io/docs/plugins/)
|
|
114
|
+
- [BankID API Documentation](https://www.bankid.com/rp-info) for detailed information on BankID's authentication services.
|
package/package.json
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haus-tech/bankid-auth-plugin",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Support for authentication via Swedish BankID",
|
|
5
|
-
"main": "
|
|
6
|
-
"types": "
|
|
7
|
-
"files": [
|
|
8
|
-
"dist",
|
|
9
|
-
"README.md"
|
|
10
|
-
],
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"types": "src/index.d.ts",
|
|
11
7
|
"scripts": {
|
|
12
|
-
"start": "yarn ts-node test/dev-server.ts"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
}
|
|
8
|
+
"start": "yarn ts-node test/dev-server.ts"
|
|
9
|
+
},
|
|
10
|
+
"type": "commonjs"
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const shopSchema: import("graphql").DocumentNode;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.shopSchema = void 0;
|
|
4
|
+
const graphql_tag_1 = require("graphql-tag");
|
|
5
|
+
exports.shopSchema = (0, graphql_tag_1.gql) `
|
|
6
|
+
extend type Mutation {
|
|
7
|
+
initiateBankidAuth: InitiateBankidAuthResponse!
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type InitiateBankidAuthResponse {
|
|
11
|
+
autoStartToken: String!
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
extend type Mutation {
|
|
15
|
+
getBankidAuthStatus(input: GetBankidAuthStatusInput!): GetBankidAuthStatusResponse!
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
input GetBankidAuthStatusInput {
|
|
19
|
+
isSameDevice: Boolean!
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type GetBankidAuthStatusResponse {
|
|
23
|
+
status: String!
|
|
24
|
+
hintCode: String
|
|
25
|
+
autoStartToken: String
|
|
26
|
+
qrData: String
|
|
27
|
+
}
|
|
28
|
+
extend type Mutation {
|
|
29
|
+
cancelBankidAuth: Boolean!
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
//# sourceMappingURL=api-extensions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-extensions.js","sourceRoot":"","sources":["../../../../../packages/bankid-auth-plugin/src/api/api-extensions.ts"],"names":[],"mappings":";;;AAAA,6CAAiC;AAEpB,QAAA,UAAU,GAAG,IAAA,iBAAG,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;CA0B5B,CAAA"}
|
|
@@ -11,36 +11,39 @@ exports.BankIdAuthPlugin = void 0;
|
|
|
11
11
|
const core_1 = require("@vendure/core");
|
|
12
12
|
const constants_1 = require("./constants");
|
|
13
13
|
const bankid_auth_service_1 = require("./services/bankid-auth.service");
|
|
14
|
-
const
|
|
15
|
-
|
|
14
|
+
const bankid_api_service_1 = require("./services/bankid-api.service");
|
|
15
|
+
const bankid_session_service_1 = require("./services/bankid-session.service");
|
|
16
|
+
const api_extensions_1 = require("./api/api-extensions");
|
|
17
|
+
const bankid_auth_resolver_1 = require("./bankid-auth.resolver");
|
|
18
|
+
let BankIdAuthPlugin = class BankIdAuthPlugin {
|
|
19
|
+
static { BankIdAuthPlugin_1 = this; }
|
|
16
20
|
static options;
|
|
17
21
|
static init(options) {
|
|
18
22
|
this.options = options;
|
|
19
|
-
if (!options.postAuthStrategy) {
|
|
20
|
-
throw new Error('BankIdAuthPlugin requires a PostAuthenticateStrategy but none was provided');
|
|
21
|
-
}
|
|
22
23
|
if (!options.bankIdApiBaseUrl) {
|
|
23
24
|
throw new Error('BankIdAuthPlugin requires a bankIdApiBaseUrl but none was provided');
|
|
24
25
|
}
|
|
25
26
|
return BankIdAuthPlugin_1;
|
|
26
27
|
}
|
|
27
28
|
};
|
|
28
|
-
BankIdAuthPlugin =
|
|
29
|
+
exports.BankIdAuthPlugin = BankIdAuthPlugin;
|
|
30
|
+
exports.BankIdAuthPlugin = BankIdAuthPlugin = BankIdAuthPlugin_1 = __decorate([
|
|
29
31
|
(0, core_1.VendurePlugin)({
|
|
30
32
|
imports: [core_1.PluginCommonModule],
|
|
31
33
|
providers: [
|
|
32
|
-
{ provide: constants_1.BANKID_AUTH_PLUGIN_OPTIONS, useFactory: () =>
|
|
34
|
+
{ provide: constants_1.BANKID_AUTH_PLUGIN_OPTIONS, useFactory: () => BankIdAuthPlugin.options },
|
|
35
|
+
bankid_api_service_1.BankIdApiService,
|
|
36
|
+
bankid_session_service_1.BankIdSessionService,
|
|
33
37
|
bankid_auth_service_1.BankIdAuthService,
|
|
34
38
|
],
|
|
39
|
+
shopApiExtensions: {
|
|
40
|
+
resolvers: [bankid_auth_resolver_1.BankIdAuthResolver],
|
|
41
|
+
schema: api_extensions_1.shopSchema,
|
|
42
|
+
},
|
|
35
43
|
configuration: (config) => {
|
|
36
|
-
// Plugin-specific configuration
|
|
37
|
-
// such as custom fields, custom permissions,
|
|
38
|
-
// strategies etc. can be configured here by
|
|
39
|
-
// modifying the `config` object.
|
|
40
44
|
return config;
|
|
41
45
|
},
|
|
42
|
-
controllers: [bankid_auth_controller_1.BankIdAuthController],
|
|
43
46
|
compatibility: '^3.0.0',
|
|
44
47
|
})
|
|
45
48
|
], BankIdAuthPlugin);
|
|
46
|
-
|
|
49
|
+
//# sourceMappingURL=bankid-auth.plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bankid-auth.plugin.js","sourceRoot":"","sources":["../../../../packages/bankid-auth-plugin/src/bankid-auth.plugin.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,wCAAuE;AACvE,2CAAwD;AACxD,wEAAkE;AAClE,sEAAgE;AAChE,8EAAwE;AAExE,yDAAiD;AACjD,iEAA2D;AAmBpD,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;;IAC3B,MAAM,CAAC,OAAO,CAAyB;IAEvC,MAAM,CAAC,IAAI,CAAC,OAAgC;QAC1C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAA;QACvF,CAAC;QACD,OAAO,kBAAgB,CAAA;IACzB,CAAC;CACF,CAAA;AAVY,4CAAgB;2BAAhB,gBAAgB;IAjB5B,IAAA,oBAAa,EAAC;QACb,OAAO,EAAE,CAAC,yBAAkB,CAAC;QAC7B,SAAS,EAAE;YACT,EAAE,OAAO,EAAE,sCAA0B,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE;YACnF,qCAAgB;YAChB,6CAAoB;YACpB,uCAAiB;SAClB;QACD,iBAAiB,EAAE;YACjB,SAAS,EAAE,CAAC,yCAAkB,CAAC;YAC/B,MAAM,EAAE,2BAAU;SACnB;QACD,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE;YACxB,OAAO,MAAM,CAAA;QACf,CAAC;QACD,aAAa,EAAE,QAAQ;KACxB,CAAC;GACW,gBAAgB,CAU5B"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BankIdAuthService } from './services/bankid-auth.service';
|
|
2
|
+
import { BankIdSessionService } from './services/bankid-session.service';
|
|
3
|
+
import { RequestContext } from '@vendure/core';
|
|
4
|
+
import { GetBankidAuthStatusInput } from './types';
|
|
5
|
+
import { Request } from 'express';
|
|
6
|
+
export declare class BankIdAuthResolver {
|
|
7
|
+
private bankIdAuthService;
|
|
8
|
+
private bankIdSessionService;
|
|
9
|
+
constructor(bankIdAuthService: BankIdAuthService, bankIdSessionService: BankIdSessionService);
|
|
10
|
+
initiateBankidAuth(ctx: RequestContext, req: Request): Promise<Pick<import("./types").InitiateResponse, "autoStartToken">>;
|
|
11
|
+
getBankidAuthStatus(ctx: RequestContext, args: {
|
|
12
|
+
input: GetBankidAuthStatusInput;
|
|
13
|
+
}): Promise<{
|
|
14
|
+
status: string;
|
|
15
|
+
hintCode: null;
|
|
16
|
+
autoStartToken: null;
|
|
17
|
+
qrData: null;
|
|
18
|
+
} | {
|
|
19
|
+
status: import("./types").BankIdOrderStatus;
|
|
20
|
+
hintCode: string;
|
|
21
|
+
autoStartToken: string;
|
|
22
|
+
qrData: string | undefined;
|
|
23
|
+
}>;
|
|
24
|
+
cancelBankidAuth(ctx: RequestContext): Promise<boolean>;
|
|
25
|
+
}
|
|
@@ -12,40 +12,52 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
12
12
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.
|
|
15
|
+
exports.BankIdAuthResolver = void 0;
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
17
|
const bankid_auth_service_1 = require("./services/bankid-auth.service");
|
|
18
|
+
const bankid_session_service_1 = require("./services/bankid-session.service");
|
|
18
19
|
const core_1 = require("@vendure/core");
|
|
19
20
|
const utils_1 = require("./utils");
|
|
20
21
|
const utils_2 = require("./utils");
|
|
21
|
-
|
|
22
|
+
const graphql_1 = require("@nestjs/graphql");
|
|
23
|
+
const graphql_2 = require("@nestjs/graphql");
|
|
24
|
+
const lodash_1 = require("lodash");
|
|
25
|
+
let BankIdAuthResolver = class BankIdAuthResolver {
|
|
22
26
|
bankIdAuthService;
|
|
23
|
-
|
|
24
|
-
constructor(bankIdAuthService,
|
|
27
|
+
bankIdSessionService;
|
|
28
|
+
constructor(bankIdAuthService, bankIdSessionService) {
|
|
25
29
|
this.bankIdAuthService = bankIdAuthService;
|
|
26
|
-
this.
|
|
30
|
+
this.bankIdSessionService = bankIdSessionService;
|
|
27
31
|
}
|
|
28
|
-
async
|
|
29
|
-
const endUserIp = (0, utils_1.
|
|
32
|
+
async initiateBankidAuth(ctx, req) {
|
|
33
|
+
const endUserIp = (0, utils_1.getClientIp)(req);
|
|
30
34
|
try {
|
|
31
35
|
const result = await this.bankIdAuthService.initiate(ctx, endUserIp);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return { data: result };
|
|
36
|
+
await this.bankIdSessionService.save(ctx, result, endUserIp);
|
|
37
|
+
return (0, lodash_1.pick)(result, ['autoStartToken']);
|
|
35
38
|
}
|
|
36
39
|
catch (error) {
|
|
37
40
|
throw (0, utils_1.handleBankIdError)(error);
|
|
38
41
|
}
|
|
39
42
|
}
|
|
40
|
-
async
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
async getBankidAuthStatus(ctx, args) {
|
|
44
|
+
const data = await this.bankIdSessionService.get(ctx);
|
|
45
|
+
if (!data || !data.orderRef) {
|
|
46
|
+
return {
|
|
47
|
+
status: 'NOT_INITIATED',
|
|
48
|
+
hintCode: null,
|
|
49
|
+
autoStartToken: null,
|
|
50
|
+
qrData: null,
|
|
51
|
+
};
|
|
43
52
|
}
|
|
44
|
-
const cacheKey = `bankid:session:${body.orderRef}`;
|
|
45
|
-
const cachedIpAddress = (await this.cacheService.get(cacheKey));
|
|
46
53
|
try {
|
|
47
|
-
const
|
|
48
|
-
return {
|
|
54
|
+
const statusResponse = await this.bankIdAuthService.getBankidAuthStatus(ctx, data, args.input.isSameDevice);
|
|
55
|
+
return {
|
|
56
|
+
status: statusResponse.status,
|
|
57
|
+
hintCode: statusResponse.hintCode,
|
|
58
|
+
autoStartToken: data.autoStartToken,
|
|
59
|
+
qrData: statusResponse.qrData,
|
|
60
|
+
};
|
|
49
61
|
}
|
|
50
62
|
catch (error) {
|
|
51
63
|
if (error instanceof utils_2.IpMismatchError) {
|
|
@@ -54,47 +66,48 @@ let BankIdAuthController = class BankIdAuthController {
|
|
|
54
66
|
throw (0, utils_1.handleBankIdError)(error);
|
|
55
67
|
}
|
|
56
68
|
}
|
|
57
|
-
async
|
|
58
|
-
|
|
59
|
-
|
|
69
|
+
async cancelBankidAuth(ctx) {
|
|
70
|
+
const data = await this.bankIdSessionService.get(ctx);
|
|
71
|
+
if (!data || !data.orderRef) {
|
|
72
|
+
throw new common_1.HttpException('No active BankID order to cancel', common_1.HttpStatus.BAD_REQUEST);
|
|
60
73
|
}
|
|
61
74
|
try {
|
|
62
|
-
await this.bankIdAuthService.cancel(ctx,
|
|
75
|
+
await this.bankIdAuthService.cancel(ctx, data.orderRef);
|
|
76
|
+
await this.bankIdSessionService.clear(ctx);
|
|
77
|
+
return true;
|
|
63
78
|
}
|
|
64
79
|
catch (error) {
|
|
65
80
|
throw (0, utils_1.handleBankIdError)(error);
|
|
66
81
|
}
|
|
67
82
|
}
|
|
68
83
|
};
|
|
84
|
+
exports.BankIdAuthResolver = BankIdAuthResolver;
|
|
69
85
|
__decorate([
|
|
70
|
-
(0,
|
|
71
|
-
(0, common_1.HttpCode)(common_1.HttpStatus.CREATED),
|
|
86
|
+
(0, graphql_1.Mutation)(),
|
|
72
87
|
__param(0, (0, core_1.Ctx)()),
|
|
88
|
+
__param(1, (0, graphql_2.Context)('req')),
|
|
73
89
|
__metadata("design:type", Function),
|
|
74
|
-
__metadata("design:paramtypes", [core_1.RequestContext]),
|
|
90
|
+
__metadata("design:paramtypes", [core_1.RequestContext, Object]),
|
|
75
91
|
__metadata("design:returntype", Promise)
|
|
76
|
-
],
|
|
92
|
+
], BankIdAuthResolver.prototype, "initiateBankidAuth", null);
|
|
77
93
|
__decorate([
|
|
78
|
-
(0,
|
|
79
|
-
(0, common_1.HttpCode)(common_1.HttpStatus.OK),
|
|
94
|
+
(0, graphql_1.Mutation)(),
|
|
80
95
|
__param(0, (0, core_1.Ctx)()),
|
|
81
|
-
__param(1, (0,
|
|
96
|
+
__param(1, (0, graphql_1.Args)()),
|
|
82
97
|
__metadata("design:type", Function),
|
|
83
98
|
__metadata("design:paramtypes", [core_1.RequestContext, Object]),
|
|
84
99
|
__metadata("design:returntype", Promise)
|
|
85
|
-
],
|
|
100
|
+
], BankIdAuthResolver.prototype, "getBankidAuthStatus", null);
|
|
86
101
|
__decorate([
|
|
87
|
-
(0,
|
|
88
|
-
(0, common_1.HttpCode)(common_1.HttpStatus.OK),
|
|
102
|
+
(0, graphql_1.Mutation)(),
|
|
89
103
|
__param(0, (0, core_1.Ctx)()),
|
|
90
|
-
__param(1, (0, common_1.Body)()),
|
|
91
104
|
__metadata("design:type", Function),
|
|
92
|
-
__metadata("design:paramtypes", [core_1.RequestContext
|
|
105
|
+
__metadata("design:paramtypes", [core_1.RequestContext]),
|
|
93
106
|
__metadata("design:returntype", Promise)
|
|
94
|
-
],
|
|
95
|
-
|
|
96
|
-
(0,
|
|
107
|
+
], BankIdAuthResolver.prototype, "cancelBankidAuth", null);
|
|
108
|
+
exports.BankIdAuthResolver = BankIdAuthResolver = __decorate([
|
|
109
|
+
(0, graphql_1.Resolver)(),
|
|
97
110
|
__metadata("design:paramtypes", [bankid_auth_service_1.BankIdAuthService,
|
|
98
|
-
|
|
99
|
-
],
|
|
100
|
-
|
|
111
|
+
bankid_session_service_1.BankIdSessionService])
|
|
112
|
+
], BankIdAuthResolver);
|
|
113
|
+
//# sourceMappingURL=bankid-auth.resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bankid-auth.resolver.js","sourceRoot":"","sources":["../../../../packages/bankid-auth-plugin/src/bankid-auth.resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,3 +3,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.loggerCtx = exports.BANKID_AUTH_PLUGIN_OPTIONS = void 0;
|
|
4
4
|
exports.BANKID_AUTH_PLUGIN_OPTIONS = Symbol('BANKID_AUTH_PLUGIN_OPTIONS');
|
|
5
5
|
exports.loggerCtx = 'BankidAuthPlugin';
|
|
6
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../packages/bankid-auth-plugin/src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,0BAA0B,GAAG,MAAM,CAAC,4BAA4B,CAAC,CAAA;AACjE,QAAA,SAAS,GAAG,kBAAkB,CAAA"}
|
package/src/index.d.ts
ADDED
package/{dist → src}/index.js
RENAMED
|
@@ -15,3 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./bankid-auth.plugin"), exports);
|
|
18
|
+
__exportStar(require("./services/bankid-session.service"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/bankid-auth-plugin/src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uDAAoC;AACpC,oEAAiD"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RequestContext } from '@vendure/core';
|
|
2
|
+
import { InitiateResponse, CollectResponse, BankIdAuthPluginOptions } from '../types';
|
|
3
|
+
export declare class BankIdApiService {
|
|
4
|
+
private options;
|
|
5
|
+
private readonly axiosInstance;
|
|
6
|
+
constructor(options: BankIdAuthPluginOptions);
|
|
7
|
+
initiate(_ctx: RequestContext, endUserIp: string): Promise<InitiateResponse>;
|
|
8
|
+
collect(_ctx: RequestContext, orderRef: string): Promise<CollectResponse>;
|
|
9
|
+
cancel(_ctx: RequestContext, orderRef: string): Promise<boolean>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.BankIdApiService = void 0;
|
|
19
|
+
const common_1 = require("@nestjs/common");
|
|
20
|
+
const core_1 = require("@vendure/core");
|
|
21
|
+
const constants_1 = require("../constants");
|
|
22
|
+
const constants_2 = require("../constants");
|
|
23
|
+
const axios_1 = __importDefault(require("axios"));
|
|
24
|
+
const https_1 = __importDefault(require("https"));
|
|
25
|
+
let BankIdApiService = class BankIdApiService {
|
|
26
|
+
options;
|
|
27
|
+
axiosInstance;
|
|
28
|
+
constructor(options) {
|
|
29
|
+
this.options = options;
|
|
30
|
+
this.axiosInstance = axios_1.default.create({
|
|
31
|
+
baseURL: this.options.bankIdApiBaseUrl,
|
|
32
|
+
httpsAgent: new https_1.default.Agent({
|
|
33
|
+
cert: this.options.clientCert,
|
|
34
|
+
key: this.options.privateKey,
|
|
35
|
+
ca: this.options.caCert,
|
|
36
|
+
rejectUnauthorized: process.env.BANKID_REJECT_UNAUTHORIZED !== 'false',
|
|
37
|
+
}),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async initiate(_ctx, endUserIp) {
|
|
41
|
+
const response = await this.axiosInstance.post('/auth', { endUserIp });
|
|
42
|
+
return response.data;
|
|
43
|
+
}
|
|
44
|
+
async collect(_ctx, orderRef) {
|
|
45
|
+
try {
|
|
46
|
+
const response = await this.axiosInstance.post('/collect', { orderRef });
|
|
47
|
+
return response.data;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
core_1.Logger.error('BankID collect error', constants_1.loggerCtx);
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async cancel(_ctx, orderRef) {
|
|
55
|
+
const response = await this.axiosInstance.post('/cancel', { orderRef });
|
|
56
|
+
if (response.status !== 200) {
|
|
57
|
+
throw new Error('Failed to cancel order');
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
exports.BankIdApiService = BankIdApiService;
|
|
63
|
+
exports.BankIdApiService = BankIdApiService = __decorate([
|
|
64
|
+
(0, common_1.Injectable)(),
|
|
65
|
+
__param(0, (0, common_1.Inject)(constants_2.BANKID_AUTH_PLUGIN_OPTIONS)),
|
|
66
|
+
__metadata("design:paramtypes", [Object])
|
|
67
|
+
], BankIdApiService);
|
|
68
|
+
//# sourceMappingURL=bankid-api.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bankid-api.service.js","sourceRoot":"","sources":["../../../../../packages/bankid-auth-plugin/src/services/bankid-api.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,2CAAmD;AACnD,wCAAsD;AACtD,4CAAwC;AACxC,4CAAyD;AACzD,kDAA4C;AAC5C,kDAAyB;AAIlB,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAG6B;IAFvC,aAAa,CAAe;IAE7C,YAAwD,OAAgC;QAAhC,YAAO,GAAP,OAAO,CAAyB;QACtF,IAAI,CAAC,aAAa,GAAG,eAAK,CAAC,MAAM,CAAC;YAChC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,gBAAgB;YACtC,UAAU,EAAE,IAAI,eAAK,CAAC,KAAK,CAAC;gBAC1B,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU;gBAC7B,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU;gBAC5B,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;gBACvB,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,0BAA0B,KAAK,OAAO;aACvE,CAAC;SACH,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAoB,EAAE,SAAiB;QACpD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QACtE,OAAO,QAAQ,CAAC,IAAI,CAAA;IACtB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAoB,EAAE,QAAgB;QAClD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAkB,UAAU,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;YACzF,OAAO,QAAQ,CAAC,IAAI,CAAA;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,aAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE,qBAAS,CAAC,CAAA;YAC/C,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAoB,EAAE,QAAgB;QACjD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;QACvE,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAA;QAC3C,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;CACF,CAAA;AAtCY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,mBAAU,GAAE;IAIE,WAAA,IAAA,eAAM,EAAC,sCAA0B,CAAC,CAAA;;GAHpC,gBAAgB,CAsC5B"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { RequestContext } from '@vendure/core';
|
|
2
|
+
import { InitiateResponse, OrderStatusResponse, CollectResponse } from '../types';
|
|
3
|
+
import { BankIdApiService } from './bankid-api.service';
|
|
4
|
+
import { BankIdSessionService } from './bankid-session.service';
|
|
5
|
+
import { BankIdSessionData } from '../types';
|
|
6
|
+
export declare class BankIdAuthService {
|
|
7
|
+
private apiService;
|
|
8
|
+
private bankIdSessionService;
|
|
9
|
+
constructor(apiService: BankIdApiService, bankIdSessionService: BankIdSessionService);
|
|
10
|
+
initiate(ctx: RequestContext, endUserIp: string): Promise<InitiateResponse>;
|
|
11
|
+
getBankidAuthStatus(ctx: RequestContext, data: BankIdSessionData, isSameDevice: boolean): Promise<OrderStatusResponse>;
|
|
12
|
+
handleComplete(ctx: RequestContext, response: CollectResponse, isSameDevice: boolean, cachedIpAddress: string): Promise<Pick<CollectResponse, "orderRef" | "status" | "hintCode">>;
|
|
13
|
+
cancel(ctx: RequestContext, orderRef: string): Promise<boolean>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.BankIdAuthService = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const core_1 = require("@vendure/core");
|
|
15
|
+
const constants_1 = require("../constants");
|
|
16
|
+
const types_1 = require("../types");
|
|
17
|
+
const utils_1 = require("../utils");
|
|
18
|
+
const lodash_1 = require("lodash");
|
|
19
|
+
const bankid_api_service_1 = require("./bankid-api.service");
|
|
20
|
+
const bankid_session_service_1 = require("./bankid-session.service");
|
|
21
|
+
let BankIdAuthService = class BankIdAuthService {
|
|
22
|
+
apiService;
|
|
23
|
+
bankIdSessionService;
|
|
24
|
+
constructor(apiService, bankIdSessionService) {
|
|
25
|
+
this.apiService = apiService;
|
|
26
|
+
this.bankIdSessionService = bankIdSessionService;
|
|
27
|
+
}
|
|
28
|
+
async initiate(ctx, endUserIp) {
|
|
29
|
+
return this.apiService.initiate(ctx, endUserIp);
|
|
30
|
+
}
|
|
31
|
+
async getBankidAuthStatus(ctx, data, isSameDevice) {
|
|
32
|
+
try {
|
|
33
|
+
const response = await this.apiService.collect(ctx, data.orderRef);
|
|
34
|
+
if (response.status === types_1.BankIdOrderStatus.Complete && response.completionData != null) {
|
|
35
|
+
return await this.handleComplete(ctx, response, isSameDevice, data.endUserIp);
|
|
36
|
+
}
|
|
37
|
+
const qrData = (0, utils_1.generateQrData)(data);
|
|
38
|
+
const result = {
|
|
39
|
+
...response,
|
|
40
|
+
qrData: qrData,
|
|
41
|
+
};
|
|
42
|
+
return (0, lodash_1.pick)(result, ['status', 'hintCode', 'qrData', 'orderRef']);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
core_1.Logger.error('BankID collect error', constants_1.loggerCtx);
|
|
46
|
+
await this.bankIdSessionService.clear(ctx);
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async handleComplete(ctx, response, isSameDevice, cachedIpAddress) {
|
|
51
|
+
await this.bankIdSessionService.clear(ctx);
|
|
52
|
+
const { user, device } = response.completionData || {};
|
|
53
|
+
if (!user || !device) {
|
|
54
|
+
throw new Error('User or device not found'); // This should never happen since we check for completionData in the collect response
|
|
55
|
+
}
|
|
56
|
+
if (isSameDevice && cachedIpAddress != device.ipAddress) {
|
|
57
|
+
throw new utils_1.IpMismatchError(cachedIpAddress, device.ipAddress);
|
|
58
|
+
}
|
|
59
|
+
await this.bankIdSessionService.saveAuthenticatedUser(ctx, user.personalNumber);
|
|
60
|
+
return (0, lodash_1.pick)(response, ['status', 'hintCode', 'orderRef']);
|
|
61
|
+
}
|
|
62
|
+
async cancel(ctx, orderRef) {
|
|
63
|
+
return this.apiService.cancel(ctx, orderRef);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
exports.BankIdAuthService = BankIdAuthService;
|
|
67
|
+
exports.BankIdAuthService = BankIdAuthService = __decorate([
|
|
68
|
+
(0, common_1.Injectable)(),
|
|
69
|
+
__metadata("design:paramtypes", [bankid_api_service_1.BankIdApiService,
|
|
70
|
+
bankid_session_service_1.BankIdSessionService])
|
|
71
|
+
], BankIdAuthService);
|
|
72
|
+
//# sourceMappingURL=bankid-auth.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bankid-auth.service.js","sourceRoot":"","sources":["../../../../../packages/bankid-auth-plugin/src/services/bankid-auth.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA2C;AAC3C,wCAAsD;AACtD,4CAAwC;AACxC,oCAAoG;AACpG,oCAA0D;AAC1D,mCAA6B;AAC7B,6DAAuD;AACvD,qEAA+D;AAIxD,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAElB;IACA;IAFV,YACU,UAA4B,EAC5B,oBAA0C;QAD1C,eAAU,GAAV,UAAU,CAAkB;QAC5B,yBAAoB,GAApB,oBAAoB,CAAsB;IACjD,CAAC;IAEJ,KAAK,CAAC,QAAQ,CAAC,GAAmB,EAAE,SAAiB;QACnD,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;IACjD,CAAC;IAED,KAAK,CAAC,mBAAmB,CACvB,GAAmB,EACnB,IAAuB,EACvB,YAAqB;QAErB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;YAElE,IAAI,QAAQ,CAAC,MAAM,KAAK,yBAAiB,CAAC,QAAQ,IAAI,QAAQ,CAAC,cAAc,IAAI,IAAI,EAAE,CAAC;gBACtF,OAAO,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;YAC/E,CAAC;YAED,MAAM,MAAM,GAAG,IAAA,sBAAc,EAAC,IAAI,CAAC,CAAA;YAEnC,MAAM,MAAM,GAAG;gBACb,GAAG,QAAQ;gBACX,MAAM,EAAE,MAAM;aACf,CAAA;YAED,OAAO,IAAA,aAAI,EAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAA;QACnE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,aAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE,qBAAS,CAAC,CAAA;YAC/C,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YAC1C,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,GAAmB,EACnB,QAAyB,EACzB,YAAqB,EACrB,eAAuB;QAEvB,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC1C,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC,cAAc,IAAI,EAAE,CAAA;QAEtD,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA,CAAC,qFAAqF;QACnI,CAAC;QAED,IAAI,YAAY,IAAI,eAAe,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACxD,MAAM,IAAI,uBAAe,CAAC,eAAe,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;QAC9D,CAAC;QAED,MAAM,IAAI,CAAC,oBAAoB,CAAC,qBAAqB,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,CAAA;QAE/E,OAAO,IAAA,aAAI,EAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAA;IAC3D,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAmB,EAAE,QAAgB;QAChD,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IAC9C,CAAC;CACF,CAAA;AA9DY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,mBAAU,GAAE;qCAGW,qCAAgB;QACN,6CAAoB;GAHzC,iBAAiB,CA8D7B"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RequestContext, CacheService } from '@vendure/core';
|
|
2
|
+
import { InitiateResponse } from '../types';
|
|
3
|
+
import { BankIdSessionData } from '../types';
|
|
4
|
+
export declare class BankIdSessionService {
|
|
5
|
+
private cacheService;
|
|
6
|
+
constructor(cacheService: CacheService);
|
|
7
|
+
save(ctx: RequestContext, bankIdData: InitiateResponse, endUserIp: string): Promise<void>;
|
|
8
|
+
get(ctx: RequestContext): Promise<BankIdSessionData | undefined>;
|
|
9
|
+
clear(ctx: RequestContext): Promise<void>;
|
|
10
|
+
getSessionToken(ctx: RequestContext): Promise<string | undefined>;
|
|
11
|
+
saveAuthenticatedUser(ctx: RequestContext, ssn: string): Promise<void>;
|
|
12
|
+
getAuthenticatedUser(ctx: RequestContext): Promise<string | undefined>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.BankIdSessionService = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const core_1 = require("@vendure/core");
|
|
18
|
+
const lodash_1 = require("lodash");
|
|
19
|
+
const crypto_js_1 = __importDefault(require("crypto-js"));
|
|
20
|
+
const CACHE_TTL_MS = 1800000; // 30 minutes
|
|
21
|
+
const ENCRYPTION_KEY = process.env.BANKID_ENCRYPTION_KEY;
|
|
22
|
+
let BankIdSessionService = class BankIdSessionService {
|
|
23
|
+
cacheService;
|
|
24
|
+
constructor(cacheService) {
|
|
25
|
+
this.cacheService = cacheService;
|
|
26
|
+
}
|
|
27
|
+
async save(ctx, bankIdData, endUserIp) {
|
|
28
|
+
const sessionToken = await this.getSessionToken(ctx);
|
|
29
|
+
const data = {
|
|
30
|
+
...(0, lodash_1.pick)(bankIdData, ['orderRef', 'autoStartToken', 'qrStartToken', 'qrStartSecret']),
|
|
31
|
+
endUserIp,
|
|
32
|
+
};
|
|
33
|
+
const cacheKey = `bankid:${sessionToken}:authExtra`;
|
|
34
|
+
await this.cacheService.set(cacheKey, data, { ttl: CACHE_TTL_MS });
|
|
35
|
+
}
|
|
36
|
+
async get(ctx) {
|
|
37
|
+
const sessionToken = await this.getSessionToken(ctx);
|
|
38
|
+
if (!sessionToken) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
const cacheKey = `bankid:${sessionToken}:authExtra`;
|
|
42
|
+
return await this.cacheService.get(cacheKey);
|
|
43
|
+
}
|
|
44
|
+
async clear(ctx) {
|
|
45
|
+
const sessionToken = await this.getSessionToken(ctx);
|
|
46
|
+
const cacheKey = `bankid:${sessionToken}:authExtra`;
|
|
47
|
+
await this.cacheService.delete(cacheKey);
|
|
48
|
+
}
|
|
49
|
+
async getSessionToken(ctx) {
|
|
50
|
+
return ctx.session?.token;
|
|
51
|
+
}
|
|
52
|
+
async saveAuthenticatedUser(ctx, ssn) {
|
|
53
|
+
const sessionToken = await this.getSessionToken(ctx);
|
|
54
|
+
if (!ENCRYPTION_KEY) {
|
|
55
|
+
throw new Error('BANKID_ENCRYPTION_KEY is not set');
|
|
56
|
+
}
|
|
57
|
+
const encrypted = crypto_js_1.default.AES.encrypt(ssn, ENCRYPTION_KEY).toString();
|
|
58
|
+
const cacheKey = `bankid:${sessionToken}:authUser`;
|
|
59
|
+
await this.cacheService.set(cacheKey, encrypted, { ttl: CACHE_TTL_MS });
|
|
60
|
+
}
|
|
61
|
+
async getAuthenticatedUser(ctx) {
|
|
62
|
+
const sessionToken = await this.getSessionToken(ctx);
|
|
63
|
+
if (!sessionToken) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
const cacheKey = `bankid:${sessionToken}:authUser`;
|
|
67
|
+
const encrypted = (await this.cacheService.get(cacheKey));
|
|
68
|
+
if (!encrypted || !ENCRYPTION_KEY) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const decrypted = crypto_js_1.default.AES.decrypt(encrypted, ENCRYPTION_KEY).toString(crypto_js_1.default.enc.Utf8);
|
|
73
|
+
return decrypted;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
console.error('error decrypting encrypted ssn', error);
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
exports.BankIdSessionService = BankIdSessionService;
|
|
82
|
+
exports.BankIdSessionService = BankIdSessionService = __decorate([
|
|
83
|
+
(0, common_1.Injectable)(),
|
|
84
|
+
__metadata("design:paramtypes", [core_1.CacheService])
|
|
85
|
+
], BankIdSessionService);
|
|
86
|
+
//# sourceMappingURL=bankid-session.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bankid-session.service.js","sourceRoot":"","sources":["../../../../../packages/bankid-auth-plugin/src/services/bankid-session.service.ts"],"names":[],"mappings":"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"}
|
package/{dist → src}/types.d.ts
RENAMED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { InjectableStrategy, Injector, RequestContext } from '@vendure/core';
|
|
2
1
|
/**
|
|
3
2
|
* @description
|
|
4
3
|
* The plugin can be configured using the following options:
|
|
@@ -8,7 +7,9 @@ export interface BankIdAuthPluginOptions {
|
|
|
8
7
|
clientCert: string;
|
|
9
8
|
privateKey: string;
|
|
10
9
|
caCert: string;
|
|
11
|
-
|
|
10
|
+
}
|
|
11
|
+
export interface GetBankidAuthStatusInput {
|
|
12
|
+
isSameDevice: boolean;
|
|
12
13
|
}
|
|
13
14
|
export interface InitiateResponse {
|
|
14
15
|
orderRef: string;
|
|
@@ -17,8 +18,8 @@ export interface InitiateResponse {
|
|
|
17
18
|
qrStartSecret: string;
|
|
18
19
|
}
|
|
19
20
|
export interface CollectResponse {
|
|
20
|
-
orderRef:
|
|
21
|
-
status:
|
|
21
|
+
orderRef: string;
|
|
22
|
+
status: BankIdOrderStatus.Complete | BankIdOrderStatus.Failed | BankIdOrderStatus.Pending;
|
|
22
23
|
hintCode: string;
|
|
23
24
|
completionData?: CompletionData;
|
|
24
25
|
}
|
|
@@ -39,6 +40,15 @@ export interface AuthResponse {
|
|
|
39
40
|
userId?: string;
|
|
40
41
|
hintCode?: string;
|
|
41
42
|
}
|
|
43
|
+
export type OrderStatusResponse = {
|
|
44
|
+
orderRef: string;
|
|
45
|
+
status: BankIdOrderStatus;
|
|
46
|
+
hintCode: string;
|
|
47
|
+
autoStartToken?: string;
|
|
48
|
+
qrData?: string;
|
|
49
|
+
user?: User;
|
|
50
|
+
sessionToken?: string;
|
|
51
|
+
};
|
|
42
52
|
export declare enum BankIdOrderStatus {
|
|
43
53
|
Pending = "pending",
|
|
44
54
|
Complete = "complete",
|
|
@@ -48,11 +58,13 @@ export interface BadRequestResponse {
|
|
|
48
58
|
errorCode: string;
|
|
49
59
|
details: string;
|
|
50
60
|
}
|
|
51
|
-
export interface PostAuthenticateStrategy extends InjectableStrategy {
|
|
52
|
-
handleSuccess(ctx: RequestContext, injector: Injector, input: {
|
|
53
|
-
personalNumber: string;
|
|
54
|
-
}): Promise<AuthenticatedUser>;
|
|
55
|
-
}
|
|
56
61
|
export interface AuthenticatedUser {
|
|
57
62
|
userId: string;
|
|
58
63
|
}
|
|
64
|
+
export type BankIdSessionData = {
|
|
65
|
+
orderRef: string;
|
|
66
|
+
autoStartToken: string;
|
|
67
|
+
qrStartToken: string;
|
|
68
|
+
qrStartSecret: string;
|
|
69
|
+
endUserIp: string;
|
|
70
|
+
};
|
package/{dist → src}/types.js
RENAMED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @description
|
|
4
|
+
* The plugin can be configured using the following options:
|
|
5
|
+
*/
|
|
2
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
7
|
exports.BankIdOrderStatus = void 0;
|
|
4
8
|
var BankIdOrderStatus;
|
|
@@ -6,4 +10,5 @@ var BankIdOrderStatus;
|
|
|
6
10
|
BankIdOrderStatus["Pending"] = "pending";
|
|
7
11
|
BankIdOrderStatus["Complete"] = "complete";
|
|
8
12
|
BankIdOrderStatus["Failed"] = "failed";
|
|
9
|
-
})(BankIdOrderStatus
|
|
13
|
+
})(BankIdOrderStatus || (exports.BankIdOrderStatus = BankIdOrderStatus = {}));
|
|
14
|
+
//# sourceMappingURL=types.js.map
|
package/src/types.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../packages/bankid-auth-plugin/src/types.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AA0DH,IAAY,iBAIX;AAJD,WAAY,iBAAiB;IAC3B,wCAAmB,CAAA;IACnB,0CAAqB,CAAA;IACrB,sCAAiB,CAAA;AACnB,CAAC,EAJW,iBAAiB,iCAAjB,iBAAiB,QAI5B"}
|
package/src/utils.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { HttpException } from '@nestjs/common';
|
|
2
|
+
import { AxiosError } from 'axios';
|
|
3
|
+
import { Request } from 'express';
|
|
4
|
+
import { InitiateResponse } from './types';
|
|
5
|
+
export declare function handleBankIdError(error: AxiosError | Error): HttpException;
|
|
6
|
+
export declare function getClientIp(req: Request): string;
|
|
7
|
+
export declare function generateQrData(data: InitiateResponse | null): string;
|
|
8
|
+
export declare class IpMismatchError extends Error {
|
|
9
|
+
expected: string;
|
|
10
|
+
actual: string;
|
|
11
|
+
constructor(expected: string, actual: string);
|
|
12
|
+
}
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IpMismatchError = void 0;
|
|
4
|
+
exports.handleBankIdError = handleBankIdError;
|
|
5
|
+
exports.getClientIp = getClientIp;
|
|
6
|
+
exports.generateQrData = generateQrData;
|
|
7
|
+
const common_1 = require("@nestjs/common");
|
|
8
|
+
const core_1 = require("@vendure/core");
|
|
9
|
+
const constants_1 = require("./constants");
|
|
10
|
+
const crypto_1 = require("crypto");
|
|
11
|
+
function handleBankIdError(error) {
|
|
12
|
+
if (error?.isAxiosError) {
|
|
13
|
+
const axiosError = error;
|
|
14
|
+
const status = axiosError.response?.status || 500;
|
|
15
|
+
core_1.Logger.error(`BankID error: ${status} - ${axiosError.message}`, constants_1.loggerCtx);
|
|
16
|
+
if (status >= 500) {
|
|
17
|
+
return new common_1.HttpException({
|
|
18
|
+
message: 'BankID service unavailable',
|
|
19
|
+
details: axiosError.response?.data,
|
|
20
|
+
}, status === common_1.HttpStatus.INTERNAL_SERVER_ERROR ? common_1.HttpStatus.BAD_GATEWAY : status);
|
|
21
|
+
}
|
|
22
|
+
if (status === 400) {
|
|
23
|
+
return new common_1.HttpException({
|
|
24
|
+
message: 'Invalid request to BankID',
|
|
25
|
+
}, status);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return new common_1.HttpException({
|
|
29
|
+
message: 'Unexpected error',
|
|
30
|
+
}, common_1.HttpStatus.INTERNAL_SERVER_ERROR);
|
|
31
|
+
}
|
|
32
|
+
function getClientIp(req) {
|
|
33
|
+
// Check various headers for the real client IP
|
|
34
|
+
const xForwardedFor = req.headers['x-forwarded-for'];
|
|
35
|
+
const xRealIp = req.headers['x-real-ip'];
|
|
36
|
+
const cfConnectingIp = req.headers['cf-connecting-ip']; // Cloudflare
|
|
37
|
+
if (xForwardedFor) {
|
|
38
|
+
return xForwardedFor.split(',')[0].trim();
|
|
39
|
+
}
|
|
40
|
+
if (xRealIp) {
|
|
41
|
+
return xRealIp;
|
|
42
|
+
}
|
|
43
|
+
if (cfConnectingIp) {
|
|
44
|
+
return cfConnectingIp;
|
|
45
|
+
}
|
|
46
|
+
const remoteAddress = req.socket?.remoteAddress;
|
|
47
|
+
if (remoteAddress) {
|
|
48
|
+
return remoteAddress;
|
|
49
|
+
}
|
|
50
|
+
throw new Error('Could not determine client IP address');
|
|
51
|
+
}
|
|
52
|
+
function generateQrData(data) {
|
|
53
|
+
if (!data || !data.qrStartToken || !data.qrStartSecret) {
|
|
54
|
+
throw new Error('BankID data not found');
|
|
55
|
+
}
|
|
56
|
+
const orderTimeSeconds = Date.now() / 1000;
|
|
57
|
+
const qrTime = Math.floor(Date.now() / 1000 - orderTimeSeconds);
|
|
58
|
+
const qrTimeString = qrTime.toString();
|
|
59
|
+
const qrAuthCode = (0, crypto_1.createHmac)('sha256', data.qrStartSecret).update(qrTimeString).digest('hex');
|
|
60
|
+
const qrData = `bankid.${data.qrStartToken}.${qrTimeString}.${qrAuthCode}`;
|
|
61
|
+
return qrData;
|
|
62
|
+
}
|
|
63
|
+
class IpMismatchError extends Error {
|
|
64
|
+
expected;
|
|
65
|
+
actual;
|
|
66
|
+
constructor(expected, actual) {
|
|
67
|
+
super(`IP mismatch: expected ${expected}, got ${actual}`);
|
|
68
|
+
this.expected = expected;
|
|
69
|
+
this.actual = actual;
|
|
70
|
+
this.expected = expected;
|
|
71
|
+
this.actual = actual;
|
|
72
|
+
this.name = 'IpMismatchError';
|
|
73
|
+
Object.setPrototypeOf(this, IpMismatchError.prototype);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.IpMismatchError = IpMismatchError;
|
|
77
|
+
//# sourceMappingURL=utils.js.map
|
package/src/utils.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../packages/bankid-auth-plugin/src/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { BankIdAuthService } from './services/bankid-auth.service';
|
|
2
|
-
import { CacheService, RequestContext } from '@vendure/core';
|
|
3
|
-
export declare class BankIdAuthController {
|
|
4
|
-
private bankIdAuthService;
|
|
5
|
-
private cacheService;
|
|
6
|
-
constructor(bankIdAuthService: BankIdAuthService, cacheService: CacheService);
|
|
7
|
-
initiate(ctx: RequestContext): Promise<{
|
|
8
|
-
data: import("./types").InitiateResponse;
|
|
9
|
-
}>;
|
|
10
|
-
authenticate(ctx: RequestContext, body: {
|
|
11
|
-
orderRef: string;
|
|
12
|
-
isSameDevice: boolean;
|
|
13
|
-
}): Promise<{
|
|
14
|
-
data: import("./types").AuthResponse;
|
|
15
|
-
}>;
|
|
16
|
-
cancel(ctx: RequestContext, body: {
|
|
17
|
-
orderRef: string;
|
|
18
|
-
}): Promise<void>;
|
|
19
|
-
}
|
package/dist/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './bankid-auth.plugin';
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { ModuleRef } from '@nestjs/core';
|
|
2
|
-
import { RequestContext } from '@vendure/core';
|
|
3
|
-
import { InitiateResponse, AuthResponse, BankIdAuthPluginOptions } from '../types';
|
|
4
|
-
export declare class BankIdAuthService {
|
|
5
|
-
private options;
|
|
6
|
-
private moduleRef;
|
|
7
|
-
private readonly axiosInstance;
|
|
8
|
-
constructor(options: BankIdAuthPluginOptions, moduleRef: ModuleRef);
|
|
9
|
-
initiate(ctx: RequestContext, endUserIp: string): Promise<InitiateResponse>;
|
|
10
|
-
authenticate(ctx: RequestContext, orderRef: string, cachedIpAddress: string, isSameDevice: boolean): Promise<AuthResponse>;
|
|
11
|
-
cancel(ctx: RequestContext, orderRef: string): Promise<boolean>;
|
|
12
|
-
private collect;
|
|
13
|
-
}
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
-
};
|
|
11
|
-
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
-
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
-
};
|
|
14
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
-
};
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.BankIdAuthService = void 0;
|
|
19
|
-
const common_1 = require("@nestjs/common");
|
|
20
|
-
const core_1 = require("@nestjs/core");
|
|
21
|
-
const core_2 = require("@vendure/core");
|
|
22
|
-
const constants_1 = require("../constants");
|
|
23
|
-
const axios_1 = __importDefault(require("axios"));
|
|
24
|
-
const https_1 = __importDefault(require("https"));
|
|
25
|
-
const types_1 = require("../types");
|
|
26
|
-
const utils_1 = require("../utils");
|
|
27
|
-
let BankIdAuthService = class BankIdAuthService {
|
|
28
|
-
options;
|
|
29
|
-
moduleRef;
|
|
30
|
-
axiosInstance;
|
|
31
|
-
constructor(options, moduleRef) {
|
|
32
|
-
this.options = options;
|
|
33
|
-
this.moduleRef = moduleRef;
|
|
34
|
-
this.axiosInstance = axios_1.default.create({
|
|
35
|
-
baseURL: this.options.bankIdApiBaseUrl,
|
|
36
|
-
httpsAgent: new https_1.default.Agent({
|
|
37
|
-
cert: this.options.clientCert,
|
|
38
|
-
key: this.options.privateKey,
|
|
39
|
-
ca: this.options.caCert,
|
|
40
|
-
rejectUnauthorized: false,
|
|
41
|
-
}),
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
async initiate(ctx, endUserIp) {
|
|
45
|
-
try {
|
|
46
|
-
const response = await this.axiosInstance.post('/auth', { endUserIp });
|
|
47
|
-
return response.data;
|
|
48
|
-
}
|
|
49
|
-
catch (error) {
|
|
50
|
-
throw error;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
async authenticate(ctx, orderRef, cachedIpAddress, isSameDevice) {
|
|
54
|
-
try {
|
|
55
|
-
const response = await this.collect(ctx, orderRef, 2000);
|
|
56
|
-
if (response.status === types_1.BankIdOrderStatus.Failed) {
|
|
57
|
-
return { success: false, hintCode: response?.hintCode };
|
|
58
|
-
}
|
|
59
|
-
if (response.status === types_1.BankIdOrderStatus.Complete && response.completionData != null) {
|
|
60
|
-
const { user, device } = response.completionData;
|
|
61
|
-
if (isSameDevice && cachedIpAddress != device.ipAddress) {
|
|
62
|
-
throw new utils_1.IpMismatchError(cachedIpAddress, device.ipAddress);
|
|
63
|
-
}
|
|
64
|
-
const { userId } = await this.options.postAuthStrategy.handleSuccess(ctx, new core_2.Injector(this.moduleRef), {
|
|
65
|
-
personalNumber: user.personalNumber,
|
|
66
|
-
});
|
|
67
|
-
return {
|
|
68
|
-
success: true,
|
|
69
|
-
userId: userId,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
throw error;
|
|
75
|
-
}
|
|
76
|
-
return { success: false };
|
|
77
|
-
}
|
|
78
|
-
async cancel(ctx, orderRef) {
|
|
79
|
-
try {
|
|
80
|
-
const response = await this.axiosInstance.post('/cancel', { orderRef });
|
|
81
|
-
if (response.status !== 200) {
|
|
82
|
-
throw new Error('Failed to cancel order');
|
|
83
|
-
}
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
catch (error) {
|
|
87
|
-
throw error;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
async collect(ctx, orderRef, pollingIntervalMs) {
|
|
91
|
-
return new Promise((resolve, reject) => {
|
|
92
|
-
const interval = setInterval(async () => {
|
|
93
|
-
try {
|
|
94
|
-
const response = await this.axiosInstance.post('/collect', { orderRef });
|
|
95
|
-
if (response.data.status === types_1.BankIdOrderStatus.Complete) {
|
|
96
|
-
clearInterval(interval);
|
|
97
|
-
resolve(response.data);
|
|
98
|
-
}
|
|
99
|
-
if (response.data.status === types_1.BankIdOrderStatus.Failed) {
|
|
100
|
-
clearInterval(interval);
|
|
101
|
-
reject(response.data);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
catch (error) {
|
|
105
|
-
clearInterval(interval);
|
|
106
|
-
reject(error);
|
|
107
|
-
}
|
|
108
|
-
}, pollingIntervalMs);
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
BankIdAuthService = __decorate([
|
|
113
|
-
(0, common_1.Injectable)(),
|
|
114
|
-
__param(0, (0, common_1.Inject)(constants_1.BANKID_AUTH_PLUGIN_OPTIONS)),
|
|
115
|
-
__metadata("design:paramtypes", [Object, core_1.ModuleRef])
|
|
116
|
-
], BankIdAuthService);
|
|
117
|
-
exports.BankIdAuthService = BankIdAuthService;
|
package/dist/utils.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { HttpException } from '@nestjs/common';
|
|
2
|
-
import { RequestContext } from '@vendure/core';
|
|
3
|
-
export declare function handleBankIdError(error: any): HttpException;
|
|
4
|
-
export declare function getEndUserIp(ctx: RequestContext): string;
|
|
5
|
-
export declare class IpMismatchError extends Error {
|
|
6
|
-
expected: string;
|
|
7
|
-
actual: string;
|
|
8
|
-
constructor(expected: string, actual: string);
|
|
9
|
-
}
|
package/dist/utils.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.IpMismatchError = exports.getEndUserIp = exports.handleBankIdError = void 0;
|
|
4
|
-
const common_1 = require("@nestjs/common");
|
|
5
|
-
function handleBankIdError(error) {
|
|
6
|
-
if (error?.isAxiosError) {
|
|
7
|
-
const axiosError = error;
|
|
8
|
-
const status = axiosError.response?.status || 500;
|
|
9
|
-
if (status >= 500) {
|
|
10
|
-
return new common_1.HttpException({
|
|
11
|
-
message: 'BankID service unavailable',
|
|
12
|
-
details: axiosError.response?.data,
|
|
13
|
-
}, status === common_1.HttpStatus.INTERNAL_SERVER_ERROR ? common_1.HttpStatus.BAD_GATEWAY : status);
|
|
14
|
-
}
|
|
15
|
-
if (status === 400) {
|
|
16
|
-
return new common_1.HttpException({
|
|
17
|
-
message: 'Invalid request to BankID',
|
|
18
|
-
}, status);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return new common_1.HttpException({
|
|
22
|
-
message: 'Unexpected error',
|
|
23
|
-
}, common_1.HttpStatus.INTERNAL_SERVER_ERROR);
|
|
24
|
-
}
|
|
25
|
-
exports.handleBankIdError = handleBankIdError;
|
|
26
|
-
function getEndUserIp(ctx) {
|
|
27
|
-
const xForwardedFor = ctx.req?.headers['x-forwarded-for'];
|
|
28
|
-
if (typeof xForwardedFor === 'string') {
|
|
29
|
-
return xForwardedFor.split(',')[0].trim();
|
|
30
|
-
}
|
|
31
|
-
if (Array.isArray(xForwardedFor)) {
|
|
32
|
-
return xForwardedFor[0];
|
|
33
|
-
}
|
|
34
|
-
throw new Error('Could not determine end user IP');
|
|
35
|
-
}
|
|
36
|
-
exports.getEndUserIp = getEndUserIp;
|
|
37
|
-
class IpMismatchError extends Error {
|
|
38
|
-
expected;
|
|
39
|
-
actual;
|
|
40
|
-
constructor(expected, actual) {
|
|
41
|
-
super(`IP mismatch: expected ${expected}, got ${actual}`);
|
|
42
|
-
this.expected = expected;
|
|
43
|
-
this.actual = actual;
|
|
44
|
-
this.expected = expected;
|
|
45
|
-
this.actual = actual;
|
|
46
|
-
this.name = 'IpMismatchError';
|
|
47
|
-
Object.setPrototypeOf(this, IpMismatchError.prototype);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
exports.IpMismatchError = IpMismatchError;
|
|
File without changes
|
|
File without changes
|