@cocreate/authenticate 1.10.2 → 1.12.1

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.
@@ -1,8 +1,10 @@
1
1
  name: Automated Workflow
2
+
2
3
  on:
3
4
  push:
4
5
  branches:
5
6
  - master
7
+
6
8
  jobs:
7
9
  about:
8
10
  runs-on: ubuntu-latest
@@ -18,52 +20,37 @@ jobs:
18
20
  with:
19
21
  direction: overwrite-github
20
22
  githubToken: "${{ secrets.GITHUB }}"
23
+
21
24
  release:
22
25
  runs-on: ubuntu-latest
23
26
  steps:
24
27
  - name: Checkout
25
- uses: actions/checkout@v3
26
- - name: Setup Node.js
27
- uses: actions/setup-node@v3
28
+ uses: actions/checkout@v4
28
29
  with:
29
- node-version: 14
30
- - name: Semantic Release
31
- uses: cycjimmy/semantic-release-action@v3
32
- id: semantic
30
+ fetch-depth: 0 # Required so semantic-release can trace git tags/history
31
+
32
+ - name: Setup Node.js
33
+ uses: actions/setup-node@v4
33
34
  with:
34
- extra_plugins: |
35
- @semantic-release/changelog
35
+ node-version: 22
36
+
37
+ - name: Install Semantic Release & Plugins
38
+ # Installs semantic-release and its plugins on the runner
39
+ run: |
40
+ npm install -g semantic-release \
41
+ @semantic-release/changelog \
42
+ @semantic-release/npm \
43
+ @semantic-release/github \
36
44
  @semantic-release/git
37
- @semantic-release/github
45
+
46
+ - name: Run Semantic Release (Native)
47
+ id: semantic
48
+ # This will automatically pick up your export default config file in the repository root
49
+ run: npx semantic-release
38
50
  env:
39
- GITHUB_TOKEN: "${{ secrets.GITHUB }}"
51
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
40
52
  NPM_TOKEN: "${{ secrets.NPM_TOKEN }}"
53
+
41
54
  outputs:
42
55
  new_release_published: "${{ steps.semantic.outputs.new_release_published }}"
43
- new_release_version: "${{ steps.semantic.outputs.new_release_version }}"
44
- upload:
45
- runs-on: ubuntu-latest
46
- needs: release
47
- if: needs.release.outputs.new_release_published == 'true'
48
- env:
49
- VERSION: "${{ needs.release.outputs.new_release_version }}"
50
- steps:
51
- - name: Checkout
52
- uses: actions/checkout@v3
53
- - name: Setup Node.js
54
- uses: actions/setup-node@v3
55
- with:
56
- node-version: 16
57
- - name: Set npm registry auth
58
- run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
59
- - name: Install dependencies
60
- run: yarn install
61
-
62
- - name: Set Environment Variables
63
- run: |
64
- echo "organization_id=${{ secrets.COCREATE_ORGANIZATION_ID }}" >> $GITHUB_ENV
65
- echo "key=${{ secrets.COCREATE_KEY }}" >> $GITHUB_ENV
66
- echo "host=${{ secrets.COCREATE_HOST }}" >> $GITHUB_ENV
67
- - name: CoCreate Upload
68
- run: coc upload
69
-
56
+ new_release_version: "${{ steps.semantic.outputs.new_release_version }}"
package/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
1
+ ## [1.12.1](https://github.com/CoCreate-app/CoCreate-authenticate/compare/v1.12.0...v1.12.1) (2026-07-17)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * bump dependencies ([45aac1d](https://github.com/CoCreate-app/CoCreate-authenticate/commit/45aac1d37a9afb021ff4fb2556d41fa608769f1b))
7
+
8
+ # [1.12.0](https://github.com/CoCreate-app/CoCreate-authenticate/compare/v1.11.0...v1.12.0) (2026-07-17)
9
+
10
+
11
+ ### Features
12
+
13
+ * update automated workflow and release configuration for improved semantic release handling ([27e796c](https://github.com/CoCreate-app/CoCreate-authenticate/commit/27e796c89a53e9efeb708e736ef003b16aa5df9e))
14
+
15
+ # [1.11.0](https://github.com/CoCreate-app/CoCreate-authenticate/compare/v1.10.2...v1.11.0) (2026-07-14)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * removed post install ([5fd376c](https://github.com/CoCreate-app/CoCreate-authenticate/commit/5fd376cdfe83f0902c3e34c962ac7b45713a6bea))
21
+ * semantic version handling. Reorganize .gitignore for improved clarity and structure ([142646c](https://github.com/CoCreate-app/CoCreate-authenticate/commit/142646cf3d25491af4113c98f51361a71be72193))
22
+ * update module export to ES6 syntax in release.config.js ([ed8bcac](https://github.com/CoCreate-app/CoCreate-authenticate/commit/ed8bcac530a19268a9259babcf4cd975c301b1cd))
23
+
24
+
25
+ ### Features
26
+
27
+ * add ESM support and improve key pair management functions ([2418adb](https://github.com/CoCreate-app/CoCreate-authenticate/commit/2418adba54911236be478783b3b965e4cfcf9e98))
28
+
1
29
  ## [1.10.2](https://github.com/CoCreate-app/CoCreate-authenticate/compare/v1.10.1...v1.10.2) (2025-05-01)
2
30
 
3
31
 
package/package.json CHANGED
@@ -1,18 +1,10 @@
1
1
  {
2
2
  "name": "@cocreate/authenticate",
3
- "version": "1.10.2",
3
+ "version": "1.12.1",
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",
7
- "cocreate",
8
- "low-code-framework",
9
- "no-code-framework",
10
- "cocreatejs",
11
- "cocreatejs-component",
12
- "cocreate-framework",
13
- "no-code",
14
7
  "low-code",
15
- "collaborative-framework",
16
8
  "realtime",
17
9
  "realtime-framework",
18
10
  "collaboration",
@@ -21,9 +13,8 @@
21
13
  "javascript-framework"
22
14
  ],
23
15
  "scripts": {
24
- "start": "npx webpack --config webpack.config.js --watch",
25
- "build": "NODE_ENV=production npx webpack --config webpack.config.js",
26
- "postinstall": "node -e \"const { execSync } = require('child_process'); try { execSync('coc --version', { stdio: 'ignore' }); } catch (error) { try { execSync('npm install -g @cocreate/cli', { stdio: 'inherit' }); console.log('Installed \"@cocreate/cli\" globally.'); } catch (error) { console.error('Failed to install \"@cocreate/cli\" globally:', error); } }\""
16
+ "start": "webpack --config webpack.config.js --watch",
17
+ "build": "NODE_ENV=production webpack --config webpack.config.js"
27
18
  },
28
19
  "publishConfig": {
29
20
  "access": "public"
@@ -37,6 +28,7 @@
37
28
  "bugs": {
38
29
  "url": "https://github.com/CoCreate-app/CoCreate-authenticate/issues"
39
30
  },
31
+ "type": "module",
40
32
  "main": "./src/index.js",
41
33
  "homepage": "https://cocreate.app/docs/authenticate",
42
34
  "dependencies": {
package/release.config.js CHANGED
@@ -1,4 +1,4 @@
1
- module.exports = {
1
+ export default {
2
2
  dryRun: false,
3
3
  branches: ["master"],
4
4
  plugins: [
@@ -10,12 +10,20 @@ module.exports = {
10
10
  changelogFile: "CHANGELOG.md",
11
11
  },
12
12
  ],
13
- "@semantic-release/npm",
14
- "@semantic-release/github",
13
+ "@semantic-release/npm",
15
14
  [
16
- "@semantic-release/git",
15
+ "@semantic-release/github",
17
16
  {
17
+ successComment: false,
18
+ failTitle: false,
19
+ },
20
+ ],
21
+ [
22
+ "@semantic-release/git",
23
+ {
24
+ // Only stage and commit the changelog and package.json
18
25
  assets: ["CHANGELOG.md", "package.json"],
26
+ message: "chore(release): ${nextRelease.version} [skip ci]",
19
27
  },
20
28
  ],
21
29
  ],
package/src/index.js CHANGED
@@ -1,86 +1,104 @@
1
- const crypto = require('crypto');
2
- const jwt = require('jsonwebtoken');
3
-
4
- // Configuration
1
+ /********************************************************************************
2
+ * Copyright (C) 2023 CoCreate and Contributors.
3
+ *
4
+ * This program is free software: you can redistribute it and/or modify
5
+ * it under the terms of the GNU Affero General Public License as published
6
+ * by the Free Software Foundation, either version 3 of the License, or
7
+ * (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU Affero General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Affero General Public License
15
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
+ ********************************************************************************/
17
+
18
+ // Commercial Licensing Information:
19
+ // For commercial use of this software without the copyleft provisions of the AGPLv3,
20
+ // you must obtain a commercial license from CoCreate LLC.
21
+ // For details, visit <https://cocreate.app/licenses/> or contact us at sales@cocreate.app.
22
+
23
+ import crypto from 'crypto';
24
+ import jwt from 'jsonwebtoken';
25
+ import crud from '@cocreate/crud-server';
26
+
27
+ // ==========================================
28
+ // Module-Level Sandbox State (ESM Singleton Container)
29
+ // ==========================================
5
30
  const tokenExpiration = 60; // Token expiration in minutes
6
-
7
- // Array to store key pairs
8
31
  const keyPairs = new Map();
9
-
10
- // Map to store authenticated user payload and tokens
11
32
  const sessions = new Map();
12
33
 
13
- class CoCreateAuthenticate {
14
- constructor(crud) {
15
- this.wsManager = crud.wsManager
16
- this.crud = crud
17
- }
18
-
19
- // Create new RSA key pair
20
- createKeyPair() {
21
- const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
22
- modulusLength: 2048,
23
- });
24
-
25
- let created = new Date(new Date().toISOString()).getTime()
26
- const keyPair = {
27
- privateKey,
28
- publicKey,
29
- created,
30
- expires: created + tokenExpiration * 60 * 1000, // Convert minutes to milliseconds
31
- };
32
-
33
- keyPairs.set(keyPair._id, keyPair);
34
-
35
- // crud.send({
36
- // method: 'object.create',
37
- // array: 'keys',
38
- // object: {
39
- // ...keyPair,
40
- // },
41
- // organization_id: process.env.organization_id,
42
- // });
43
-
44
- return keyPair;
45
- }
34
+ /**
35
+ * Generates a new RSA key pair dynamically and tracks its expiration lifecycle.
36
+ * @returns {Object} Newly created key pair configuration
37
+ */
38
+ function createKeyPair() {
39
+ const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
40
+ modulusLength: 2048,
41
+ });
42
+
43
+ const created = new Date(new Date().toISOString()).getTime();
44
+ const keyPair = {
45
+ _id: crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).substring(2),
46
+ privateKey,
47
+ publicKey,
48
+ created,
49
+ expires: created + tokenExpiration * 60 * 1000,
50
+ };
51
+
52
+ keyPairs.set(keyPair._id, keyPair);
53
+ return keyPair;
54
+ }
46
55
 
47
- // Delete new RSA key pair
48
- deleteKeyPair(keyPair) {
49
- keyPairs.delete(keyPair._id)
50
- // crud.send({
51
- // method: 'object.delete',
52
- // array: 'keys',
53
- // object: {
54
- // _id: keyPair._id,
55
- // type: 'RSA'
56
- // },
57
- // organization_id: process.env.organization_id,
58
- // });
56
+ /**
57
+ * Deletes an expired or revoked RSA key pair from local tracking.
58
+ * @param {Object} keyPair - The target key pair to remove
59
+ */
60
+ function deleteKeyPair(keyPair) {
61
+ if (keyPair && keyPair._id) {
62
+ keyPairs.delete(keyPair._id);
59
63
  }
64
+ }
60
65
 
61
- // Function to sign a new token using the newest keyPair
62
- encodeToken(organization_id, user_id, clientId, host) {
63
- let keyPair = null
64
- const currentTime = new Date(new Date().toISOString()).getTime();
65
- for (let [key, value] of keyPairs) {
66
- if (currentTime > value.expires) {
67
- this.deleteKeyPair(value);
68
- } else {
69
- keyPair = value
70
- }
71
- }
72
-
73
- if (!keyPair) {
74
- keyPair = this.createKeyPair();
66
+ /**
67
+ * Creates and signs a new token utilizing the latest available RSA key pair.
68
+ * Saves session markers back to storage and registers client tracking nodes.
69
+ */
70
+ function encodeToken(organization_id, user_id, clientId, host) {
71
+ let keyPair = null;
72
+ const currentTime = new Date(new Date().toISOString()).getTime();
73
+
74
+ for (let [key, value] of keyPairs) {
75
+ if (currentTime > value.expires) {
76
+ deleteKeyPair(value);
77
+ } else {
78
+ keyPair = value;
75
79
  }
80
+ }
76
81
 
77
- const token = jwt.sign({ user_id, clientId }, keyPair.privateKey, { algorithm: 'RS256', expiresIn: tokenExpiration * 60 });
78
-
79
- // TODO: session could have previous user ip and device information which we could use to comapre to current ip and device information
80
- const session = { user_id, clientId, token, expires: currentTime + tokenExpiration * 60 * 1000 }
81
- sessions.set(clientId, session)
82
+ if (!keyPair) {
83
+ keyPair = createKeyPair();
84
+ }
82
85
 
83
- this.crud.send({
86
+ const token = jwt.sign({ user_id, clientId }, keyPair.privateKey, {
87
+ algorithm: 'RS256',
88
+ expiresIn: tokenExpiration * 60
89
+ });
90
+
91
+ const session = {
92
+ user_id,
93
+ clientId,
94
+ token,
95
+ expires: currentTime + tokenExpiration * 60 * 1000
96
+ };
97
+
98
+ sessions.set(clientId, session);
99
+
100
+ if (crud) {
101
+ crud.send({
84
102
  method: 'object.update',
85
103
  host,
86
104
  array: 'clients',
@@ -91,58 +109,74 @@ class CoCreateAuthenticate {
91
109
  upsert: true,
92
110
  organization_id
93
111
  });
94
-
95
- return token;
96
112
  }
97
113
 
98
- // Verify and decode a token using the available keys
99
- async decodeToken(token, organization_id, clientId, host) {
100
- if (!token)
101
- return {}
102
- const currentTime = new Date().getTime();
103
-
104
- let session = sessions.get(clientId)
105
- if (!session || session.token !== token)
106
- session = await this.read(organization_id, clientId, host)
107
-
108
- // TODO: request must be made from same clientId and user_id that created the token
109
- if (session && currentTime < session.expires && session.token === token)
110
- return { user_id: session.user_id, expires: session.expires };
114
+ return token;
115
+ }
111
116
 
112
- sessions.delete(clientId)
113
- this.crud.send({
114
- method: 'object.update',
115
- host,
116
- array: 'clients',
117
- object: {
118
- _id: clientId,
119
- session: undefined
120
- },
121
- organization_id,
122
- });
117
+ /**
118
+ * Reads, parses, and validates the configuration and active state of client sessions.
119
+ */
120
+ async function read(organization_id, clientId, host) {
121
+ if (!crud) return null;
122
+
123
+ const client = await crud.send({
124
+ method: 'object.read',
125
+ host,
126
+ array: 'clients',
127
+ object: {
128
+ _id: clientId
129
+ },
130
+ organization_id,
131
+ });
132
+
133
+ if (client && client.object && client.object.length) {
134
+ sessions.set(clientId, client.object[0].session);
135
+ return client.object[0].session;
136
+ }
137
+ return null;
138
+ }
123
139
 
124
- return {}
140
+ /**
141
+ * Verifies and decodes an incoming session token, resolving the associated user identifier.
142
+ */
143
+ async function decodeToken(token, organization_id, clientId, host) {
144
+ if (!token) return {};
145
+
146
+ const currentTime = new Date().getTime();
147
+ let session = sessions.get(clientId);
148
+
149
+ if (!session || session.token !== token) {
150
+ session = await read(organization_id, clientId, host);
151
+ }
125
152
 
153
+ if (session && currentTime < session.expires && session.token === token) {
154
+ return { user_id: session.user_id, expires: session.expires };
126
155
  }
127
156
 
128
- async read(organization_id, clientId, host) {
129
- const client = await this.crud.send({
130
- method: 'object.read',
157
+ sessions.delete(clientId);
158
+
159
+ if (crud) {
160
+ crud.send({
161
+ method: 'object.update',
131
162
  host,
132
163
  array: 'clients',
133
164
  object: {
134
- _id: clientId
165
+ _id: clientId,
166
+ session: null
135
167
  },
136
168
  organization_id,
137
169
  });
138
-
139
- if (client.object && client.object.length) {
140
- sessions.set(clientId, client.object[0].session)
141
- return client.object[0].session
142
- }
143
-
144
170
  }
145
171
 
172
+ return {};
146
173
  }
147
174
 
148
- module.exports = CoCreateAuthenticate;
175
+ // Export the API directly as a flat default object manifest
176
+ export default {
177
+ createKeyPair,
178
+ deleteKeyPair,
179
+ encodeToken,
180
+ decodeToken,
181
+ read
182
+ };