@cocreate/authenticate 1.0.4 → 1.0.5
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/.github/workflows/automated.yml +38 -15
- package/CHANGELOG.md +7 -0
- package/CoCreate.config.js +3 -5
- package/package.json +8 -4
- package/src/index.js +108 -85
|
@@ -42,19 +42,42 @@ jobs:
|
|
|
42
42
|
new_release_published: "${{ steps.semantic.outputs.new_release_published }}"
|
|
43
43
|
new_release_version: "${{ steps.semantic.outputs.new_release_version }}"
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
45
|
+
upload:
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
|
|
48
|
+
steps:
|
|
49
|
+
- name: Checkout
|
|
50
|
+
uses: actions/checkout@v3
|
|
51
|
+
|
|
52
|
+
- name: Setup Node.js
|
|
53
|
+
uses: actions/setup-node@v3
|
|
54
|
+
with:
|
|
55
|
+
node-version: 16
|
|
56
|
+
|
|
57
|
+
- name: Get Environment Variables
|
|
58
|
+
run: |
|
|
59
|
+
echo "organization_id=${{ secrets.COCREATE_ORGANIZATION_ID }}" >> $GITHUB_ENV
|
|
60
|
+
echo "key=${{ secrets.COCREATE_KEY }}" >> $GITHUB_ENV
|
|
61
|
+
echo "host=${{ secrets.COCREATE_HOST }}" >> $GITHUB_ENV
|
|
62
|
+
|
|
63
|
+
- name: Install @cocreate/cli
|
|
64
|
+
run: npm install -g @cocreate/cli
|
|
65
|
+
|
|
66
|
+
- name: CoCreate CLI Upload
|
|
67
|
+
run: coc upload
|
|
60
68
|
|
|
69
|
+
# docs:
|
|
70
|
+
# runs-on: ubuntu-latest
|
|
71
|
+
# steps:
|
|
72
|
+
# - name: Checkout
|
|
73
|
+
# uses: actions/checkout@v3
|
|
74
|
+
# - name: setup nodejs
|
|
75
|
+
# uses: actions/setup-node@v3
|
|
76
|
+
# with:
|
|
77
|
+
# node-version: 16
|
|
78
|
+
# - name: update documentation
|
|
79
|
+
# uses: CoCreate-app/CoCreate-docs@master
|
|
80
|
+
# env:
|
|
81
|
+
# organization_id: ${{ secrets.COCREATE_ORGANIZATION_ID }}
|
|
82
|
+
# key: ${{ secrets.COCREATE_KEY }}
|
|
83
|
+
# host: ${{ secrets.COCREATE_HOST }}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [1.0.5](https://github.com/CoCreate-app/CoCreate-authenticate/compare/v1.0.4...v1.0.5) (2023-06-10)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* Update dependencies versions for [@cocreate](https://github.com/cocreate) libraries ([4f8053a](https://github.com/CoCreate-app/CoCreate-authenticate/commit/4f8053ab55494485b6b51af851a8ed95777d6947))
|
|
7
|
+
|
|
1
8
|
## [1.0.4](https://github.com/CoCreate-app/CoCreate-authenticate/compare/v1.0.3...v1.0.4) (2023-06-04)
|
|
2
9
|
|
|
3
10
|
|
package/CoCreate.config.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
"host": "general.cocreate.app"
|
|
6
|
-
},
|
|
2
|
+
"organization_id": "",
|
|
3
|
+
"key": "",
|
|
4
|
+
"host": "",
|
|
7
5
|
"sources": [
|
|
8
6
|
{
|
|
9
7
|
"collection": "files",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cocreate/authenticate",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "A simple authenticate component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"authenticate",
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"scripts": {
|
|
24
24
|
"start": "npx webpack --config webpack.config.js --watch",
|
|
25
25
|
"build": "NODE_ENV=production npx webpack --config webpack.config.js",
|
|
26
|
-
"docs": "node ./node_modules/@cocreate/docs/src/index.js"
|
|
26
|
+
"docs": "node ./node_modules/@cocreate/docs/src/index.js",
|
|
27
|
+
"postinstall": "node ./node_modules/@cocreate/cli/check-coc.js"
|
|
27
28
|
},
|
|
28
29
|
"publishConfig": {
|
|
29
30
|
"access": "public"
|
|
@@ -39,9 +40,12 @@
|
|
|
39
40
|
},
|
|
40
41
|
"main": "./src/index.js",
|
|
41
42
|
"homepage": "https://cocreate.app/docs/authenticate",
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@cocreate/cli": "^1.29.3"
|
|
45
|
+
},
|
|
42
46
|
"dependencies": {
|
|
43
|
-
"@cocreate/docs": "^1.
|
|
44
|
-
"@cocreate/uuid": "^1.4.
|
|
47
|
+
"@cocreate/docs": "^1.8.13",
|
|
48
|
+
"@cocreate/uuid": "^1.4.15",
|
|
45
49
|
"jsonwebtoken": "^9.0.0"
|
|
46
50
|
}
|
|
47
51
|
}
|
package/src/index.js
CHANGED
|
@@ -1,102 +1,125 @@
|
|
|
1
|
-
const jwt = require(
|
|
2
|
-
const uid = require("@cocreate/uuid")
|
|
3
|
-
|
|
4
|
-
class CoCreateAuthenticate {
|
|
5
|
-
/**
|
|
6
|
-
* config structure
|
|
7
|
-
* https://www.npmjs.com/package/jsonwebtoken
|
|
8
|
-
{
|
|
9
|
-
key: 'xxxxxx', // any value
|
|
10
|
-
options: {
|
|
11
|
-
algorithm: "HS256",
|
|
12
|
-
expiresIn: "30m",
|
|
13
|
-
issuer: "issuer"
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
**/
|
|
1
|
+
const jwt = require('jsonwebtoken');
|
|
17
2
|
|
|
3
|
+
// Configuration
|
|
4
|
+
const tokenExpiration = 60; // Token expiration in minutes
|
|
18
5
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
this.config['key'] = uid.generate(40)
|
|
22
|
-
}
|
|
6
|
+
// Array to store key pairs
|
|
7
|
+
const keyPairs = new Map();
|
|
23
8
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
9
|
+
// Map to store authenticated user
|
|
10
|
+
const users = new Map();
|
|
11
|
+
|
|
12
|
+
// TODO: user can have multiple sessions
|
|
13
|
+
const activeSessions = new Map();
|
|
14
|
+
|
|
15
|
+
// crud.listen('createDocument', function (data) {
|
|
16
|
+
// if (data.document && data.document[0] && data.document[0].type === 'keyPair')
|
|
17
|
+
// keyPairs.set(data.document[0]._id, data.document[0]);
|
|
18
|
+
// });
|
|
19
|
+
|
|
20
|
+
// crud.listen('deleteDocument', function (data) {
|
|
21
|
+
// if (data.document && data.document[0] && data.document[0].type === 'keyPair')
|
|
22
|
+
// keyPairs.delete(data.document[0]._id);
|
|
23
|
+
// });
|
|
24
|
+
|
|
25
|
+
// Create new RSA key pair
|
|
26
|
+
function createKeyPair() {
|
|
27
|
+
const { privateKey, publicKey } = jwt.generateKeyPairSync('rsa', {
|
|
28
|
+
modulusLength: 2048,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const keyPair = {
|
|
32
|
+
_id: crud.ObjectId(),
|
|
33
|
+
privateKey,
|
|
34
|
+
publicKey,
|
|
35
|
+
created: new Date().getTime(), // Store as timestamp
|
|
36
|
+
expires: new Date().getTime() + tokenExpiration * 60 * 1000 * 2, // Convert minutes to milliseconds
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
keyPairs.set(keyPair._id, keyPair);
|
|
40
|
+
|
|
41
|
+
// crud.createDocument({
|
|
42
|
+
// collection: 'keys',
|
|
43
|
+
// document: {
|
|
44
|
+
// ...keyPair,
|
|
45
|
+
// },
|
|
46
|
+
// organization_id: process.env.organization_id,
|
|
47
|
+
// });
|
|
48
|
+
|
|
49
|
+
return keyPair;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Function to retrieve keys from the database (example using CRUD operations)
|
|
53
|
+
function readKeyPairs() {
|
|
54
|
+
const keys = crud.readDocument({
|
|
55
|
+
collection: 'keys',
|
|
56
|
+
filter: {
|
|
57
|
+
query: [
|
|
58
|
+
{ name: 'type', value: 'keyPair' },
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
organization_id: process.env.organization_id,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Add retrieved key pairs to the keyPairs array
|
|
65
|
+
if (keys.document && keys.document.length) {
|
|
66
|
+
keys.document.forEach((keyPair) => {
|
|
67
|
+
keyPairs.set(keyPair._id, keyPair);
|
|
68
|
+
});
|
|
34
69
|
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Delete new RSA key pair
|
|
73
|
+
function deleteKeyPair(keyPair) {
|
|
74
|
+
keyPairs.delete(keyPair._id)
|
|
75
|
+
// crud.deleteDocument({
|
|
76
|
+
// collection: 'keys',
|
|
77
|
+
// document: {
|
|
78
|
+
// _id: keyPair._id,
|
|
79
|
+
// type: 'keyPair'
|
|
80
|
+
// },
|
|
81
|
+
// organization_id: process.env.organization_id,
|
|
82
|
+
// });
|
|
83
|
+
}
|
|
35
84
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
85
|
+
// Function to sign a new token using the newest keyPair
|
|
86
|
+
function encodeToken(payload) {
|
|
87
|
+
let keyPair = null
|
|
88
|
+
const currentTime = new Date().getTime();
|
|
89
|
+
for (let [key, value] of keyPairs) {
|
|
90
|
+
if (currentTime > value.expires) {
|
|
91
|
+
deleteKeyPair(value);
|
|
92
|
+
} else {
|
|
93
|
+
keyPair = value
|
|
42
94
|
}
|
|
43
95
|
}
|
|
44
96
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (cookie) {
|
|
48
|
-
cookie.split(';').forEach((c) => {
|
|
49
|
-
try {
|
|
50
|
-
var parts = c.split('=')
|
|
51
|
-
if (parts[0].trim() == 'token') {
|
|
52
|
-
token = decodeURI(parts[1].trim());
|
|
53
|
-
}
|
|
54
|
-
} catch (err) {
|
|
55
|
-
console.log(err)
|
|
56
|
-
}
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
return token;
|
|
97
|
+
if (!keyPair) {
|
|
98
|
+
keyPair = createKeyPair();
|
|
60
99
|
}
|
|
61
100
|
|
|
62
|
-
|
|
63
|
-
const headers = req.headers
|
|
64
|
-
let token = headers['sec-websocket-protocol'];
|
|
65
|
-
// let token = this.getTokenFromCookie(headers.cookie);
|
|
66
|
-
// if (!token) {
|
|
67
|
-
// token = headers['sec-websocket-protocol'];
|
|
68
|
-
// }
|
|
69
|
-
|
|
70
|
-
let result = null;
|
|
71
|
-
if (token && token !== 'null') {
|
|
72
|
-
result = await this.verifiyToken(token);
|
|
73
|
-
}
|
|
101
|
+
// TODO: payload could have previous user ip and device information which we could use to comapre to current ip and device information
|
|
74
102
|
|
|
75
|
-
|
|
76
|
-
}
|
|
103
|
+
const token = jwt.sign(payload, keyPair.privateKey, { expiresIn: tokenExpiration * 60 });
|
|
104
|
+
users.set(token, { _id: payload.user._id, expires: new Date().getTime() + tokenExpiration * 60 * 1000 })
|
|
105
|
+
return token;
|
|
106
|
+
}
|
|
77
107
|
|
|
78
|
-
|
|
108
|
+
// Verify and decode a token using the available keys
|
|
109
|
+
function decodeToken(req) {
|
|
110
|
+
const headers = req.headers;
|
|
111
|
+
const token = headers['sec-websocket-protocol'];
|
|
112
|
+
const currentTime = new Date().getTime();
|
|
79
113
|
|
|
80
|
-
|
|
114
|
+
let user = users.get(token)
|
|
115
|
+
if (user && currentTime < user.expires)
|
|
116
|
+
return user._id;
|
|
81
117
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
let decoded = await jwt.verify(token, this.config.key)
|
|
85
|
-
return decoded;
|
|
86
|
-
} catch (err) {
|
|
87
|
-
if (err.message === 'jwt expired') {
|
|
88
|
-
console.log('Expired Token')
|
|
89
|
-
return null
|
|
90
|
-
} else if (err.message === 'invalid token') {
|
|
91
|
-
console.log('Invalid Token')
|
|
92
|
-
return null
|
|
93
|
-
} else {
|
|
94
|
-
console.log('Invalid token', token)
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
118
|
+
users.delete(token)
|
|
119
|
+
return null
|
|
98
120
|
|
|
99
|
-
}
|
|
100
121
|
}
|
|
101
122
|
|
|
102
|
-
|
|
123
|
+
// readKeyPairs();
|
|
124
|
+
|
|
125
|
+
module.exports = { encodeToken, decodeToken };
|