@breakside/jskit 2024.40.0 → 2024.41.0
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/Frameworks/DOM.jsframework/Info.json +2 -2
- package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
- package/Frameworks/FontKit.jsframework/Info.json +2 -2
- package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
- package/Frameworks/Foundation.jsframework/Info.json +2 -2
- package/Frameworks/Foundation.jsframework/JS/Foundation+HTML.js +3 -1
- package/Frameworks/Foundation.jsframework/JS/JSHTMLUserAgent.js +130 -0
- package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
- package/Frameworks/Foundation.jsframework/sources.json +3 -1
- package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
- package/Frameworks/SecurityKit.jsframework/JS/SECCBOR.js +4 -0
- package/Frameworks/SecurityKit.jsframework/JS/SECHTMLDeviceAuthentication.js +69 -16
- package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
- package/Info.json +2 -2
- package/Node/io.breakside.jskit-bundle.js +2 -2
- package/Root/Frameworks/APIKit/Info.yaml +1 -1
- package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/AuthKit/Info.yaml +1 -1
- package/Root/Frameworks/CSSOM/Info.yaml +1 -1
- package/Root/Frameworks/ChartKit/Info.yaml +1 -1
- package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
- package/Root/Frameworks/DBKit/Info.yaml +1 -1
- package/Root/Frameworks/DOM/Info.yaml +1 -1
- package/Root/Frameworks/Dispatch/Info.yaml +1 -1
- package/Root/Frameworks/FontKit/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/Foundation+HTML.js +3 -1
- package/Root/Frameworks/Foundation/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/JSHTMLUserAgent.js +130 -0
- package/Root/Frameworks/ImageKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
- package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
- package/Root/Frameworks/PDFKit/Info.yaml +1 -1
- package/Root/Frameworks/QRKit/Info.yaml +1 -1
- package/Root/Frameworks/SearchKit/Info.yaml +1 -1
- package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
- package/Root/Frameworks/SecurityKit/SECCBOR.js +4 -0
- package/Root/Frameworks/SecurityKit/SECHTMLDeviceAuthentication.js +69 -16
- package/Root/Frameworks/ServerKit/Info.yaml +1 -1
- package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/TestKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/UIPlatform+HTML.js +2 -1
- package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"JSBundleType": "framework",
|
|
3
3
|
"JSBundleIdentifier": "io.breakside.JSKit.DOM",
|
|
4
|
-
"JSBundleVersion": "2024.
|
|
4
|
+
"JSBundleVersion": "2024.41.0",
|
|
5
5
|
"JSDevelopmentLanguage": "en",
|
|
6
6
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
7
7
|
"JSBundleEnvironments": {
|
|
@@ -9,5 +9,5 @@
|
|
|
9
9
|
"node": "DOM+Node.js"
|
|
10
10
|
},
|
|
11
11
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
12
|
-
"GitRevision": "
|
|
12
|
+
"GitRevision": "bf643e90b060044223efa5a59f0d727332802563"
|
|
13
13
|
}
|
|
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.DOM'] = {
|
|
|
3
3
|
"Info": {
|
|
4
4
|
"JSBundleType": "framework",
|
|
5
5
|
"JSBundleIdentifier": "io.breakside.JSKit.DOM",
|
|
6
|
-
"JSBundleVersion": "2024.
|
|
6
|
+
"JSBundleVersion": "2024.41.0",
|
|
7
7
|
"JSDevelopmentLanguage": "en",
|
|
8
8
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
9
9
|
"JSBundleEnvironments": {
|
|
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.DOM'] = {
|
|
|
11
11
|
"node": "DOM+Node.js"
|
|
12
12
|
},
|
|
13
13
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
14
|
-
"GitRevision": "
|
|
14
|
+
"GitRevision": "bf643e90b060044223efa5a59f0d727332802563"
|
|
15
15
|
},
|
|
16
16
|
"Resources": [],
|
|
17
17
|
"ResourceLookup": {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"JSBundleType": "framework",
|
|
3
3
|
"JSBundleIdentifier": "io.breakside.JSKit.FontKit",
|
|
4
|
-
"JSBundleVersion": "2024.
|
|
4
|
+
"JSBundleVersion": "2024.41.0",
|
|
5
5
|
"JSDevelopmentLanguage": "en",
|
|
6
6
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
7
7
|
"JSBundleEnvironments": {
|
|
8
8
|
"html": "FontKit+HTML.js"
|
|
9
9
|
},
|
|
10
10
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
11
|
-
"GitRevision": "
|
|
11
|
+
"GitRevision": "bf643e90b060044223efa5a59f0d727332802563"
|
|
12
12
|
}
|
|
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.JSKit.FontKit'] = {
|
|
|
3
3
|
"Info": {
|
|
4
4
|
"JSBundleType": "framework",
|
|
5
5
|
"JSBundleIdentifier": "io.breakside.JSKit.FontKit",
|
|
6
|
-
"JSBundleVersion": "2024.
|
|
6
|
+
"JSBundleVersion": "2024.41.0",
|
|
7
7
|
"JSDevelopmentLanguage": "en",
|
|
8
8
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
9
9
|
"JSBundleEnvironments": {
|
|
10
10
|
"html": "FontKit+HTML.js"
|
|
11
11
|
},
|
|
12
12
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
13
|
-
"GitRevision": "
|
|
13
|
+
"GitRevision": "bf643e90b060044223efa5a59f0d727332802563"
|
|
14
14
|
},
|
|
15
15
|
"Resources": [],
|
|
16
16
|
"ResourceLookup": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"JSBundleType": "framework",
|
|
3
3
|
"JSBundleIdentifier": "io.breakside.JSKit.Foundation",
|
|
4
|
-
"JSBundleVersion": "2024.
|
|
4
|
+
"JSBundleVersion": "2024.41.0",
|
|
5
5
|
"JSDevelopmentLanguage": "en",
|
|
6
6
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
7
7
|
"JSBundleEnvironments": {
|
|
@@ -9,5 +9,5 @@
|
|
|
9
9
|
"node": "Foundation+Node.js"
|
|
10
10
|
},
|
|
11
11
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
12
|
-
"GitRevision": "
|
|
12
|
+
"GitRevision": "bf643e90b060044223efa5a59f0d727332802563"
|
|
13
13
|
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// Copyright 2021 Breakside Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Breakside Public License, Version 1.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// If a copy of the License was not distributed with this file, you may
|
|
6
|
+
// obtain a copy at
|
|
7
|
+
//
|
|
8
|
+
// http://breakside.io/licenses/LICENSE-1.0.txt
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
|
|
16
|
+
// #import "JSObject.js"
|
|
17
|
+
"use strict";
|
|
18
|
+
|
|
19
|
+
JSClass("JSHTMLUserAgent", JSObject, {
|
|
20
|
+
|
|
21
|
+
string: null,
|
|
22
|
+
products: null,
|
|
23
|
+
productsByIdentifier: null,
|
|
24
|
+
comments: null,
|
|
25
|
+
commentSet: null,
|
|
26
|
+
|
|
27
|
+
initWithString: function(string){
|
|
28
|
+
if (string === null || string === undefined){
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
this.string = string;
|
|
32
|
+
this.products = [];
|
|
33
|
+
this.productsByIdentifier = new Set();
|
|
34
|
+
this.comments = [];
|
|
35
|
+
this.commentSet = new Set();
|
|
36
|
+
this.parse();
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
parse: function(){
|
|
40
|
+
var str = this.string;
|
|
41
|
+
var i = 0;
|
|
42
|
+
var l = this.string.length;
|
|
43
|
+
var product = "";
|
|
44
|
+
var version = "";
|
|
45
|
+
var comment = "";
|
|
46
|
+
while (i < l){
|
|
47
|
+
while (str[i] == " " || str[i] == "\t"){
|
|
48
|
+
++i;
|
|
49
|
+
}
|
|
50
|
+
if (i < l){
|
|
51
|
+
if (str[i] == "("){
|
|
52
|
+
comment = "";
|
|
53
|
+
++i;
|
|
54
|
+
while (i < l && str[i] !== ")"){
|
|
55
|
+
if (str[i] == ";"){
|
|
56
|
+
comment = comment.trim();
|
|
57
|
+
if (comment !== ""){
|
|
58
|
+
this.addComment(comment);
|
|
59
|
+
}
|
|
60
|
+
comment = "";
|
|
61
|
+
}else{
|
|
62
|
+
comment += str[i];
|
|
63
|
+
}
|
|
64
|
+
++i;
|
|
65
|
+
}
|
|
66
|
+
comment = comment.trim();
|
|
67
|
+
if (comment !== ""){
|
|
68
|
+
this.addComment(comment);
|
|
69
|
+
}
|
|
70
|
+
if (i < l){
|
|
71
|
+
++i;
|
|
72
|
+
}
|
|
73
|
+
}else{
|
|
74
|
+
product = "";
|
|
75
|
+
version = "";
|
|
76
|
+
while (i < l && str[i] !== "/" && str[i] !== " " && str[i] !== "\t"){
|
|
77
|
+
product += str[i];
|
|
78
|
+
++i;
|
|
79
|
+
}
|
|
80
|
+
if (i < l && str[i] == "/"){
|
|
81
|
+
++i;
|
|
82
|
+
while (i < l && str[i] !== "(" && str[i] !== " " && str[i] !== "\t"){
|
|
83
|
+
version += str[i];
|
|
84
|
+
++i;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
this.addProduct(product, version);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
addProduct: function(name, version){
|
|
94
|
+
if (version === "" || version === undefined){
|
|
95
|
+
version = null;
|
|
96
|
+
}
|
|
97
|
+
var product = {name: name, version: version};
|
|
98
|
+
this.products.push(product);
|
|
99
|
+
this.productsByIdentifier[name] = product;
|
|
100
|
+
if (version !== null){
|
|
101
|
+
this.productsByIdentifier["%s/%s".sprintf(name, version)] = product;
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
addComment: function(comment){
|
|
106
|
+
this.comments.push(comment);
|
|
107
|
+
this.commentSet.add(comment);
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
containsProduct: function(name, version){
|
|
111
|
+
if (version === undefined || version === null || version === ""){
|
|
112
|
+
return name in this.productsByIdentifier;
|
|
113
|
+
}
|
|
114
|
+
return "%s/%s".sprintf(name, version) in this.productsByIdentifier;
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
versionOfProduct: function(name){
|
|
118
|
+
var product = this.productsByIdentifier[name];
|
|
119
|
+
if (product){
|
|
120
|
+
return product.version;
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
containsComment: function(comment){
|
|
126
|
+
return this.commentSet.has(comment);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
});
|
|
130
|
+
|
|
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.Foundation'] = {
|
|
|
3
3
|
"Info": {
|
|
4
4
|
"JSBundleType": "framework",
|
|
5
5
|
"JSBundleIdentifier": "io.breakside.JSKit.Foundation",
|
|
6
|
-
"JSBundleVersion": "2024.
|
|
6
|
+
"JSBundleVersion": "2024.41.0",
|
|
7
7
|
"JSDevelopmentLanguage": "en",
|
|
8
8
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
9
9
|
"JSBundleEnvironments": {
|
|
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.Foundation'] = {
|
|
|
11
11
|
"node": "Foundation+Node.js"
|
|
12
12
|
},
|
|
13
13
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
14
|
-
"GitRevision": "
|
|
14
|
+
"GitRevision": "bf643e90b060044223efa5a59f0d727332802563"
|
|
15
15
|
},
|
|
16
16
|
"Resources": [
|
|
17
17
|
{
|
|
@@ -295,6 +295,7 @@
|
|
|
295
295
|
"JSFile+HTML.js",
|
|
296
296
|
"JSHTMLFile.js",
|
|
297
297
|
"JSHTMLFileEnumerator.js",
|
|
298
|
+
"JSHTMLUserAgent.js",
|
|
298
299
|
"Foundation+HTML.js"
|
|
299
300
|
],
|
|
300
301
|
"features": [
|
|
@@ -316,7 +317,8 @@
|
|
|
316
317
|
"JSHTMLFileManager",
|
|
317
318
|
"JSHTMLFile",
|
|
318
319
|
"JSHTMLFileListFileEnumerator",
|
|
319
|
-
"JSHTMLFileSystemEntryFileEnumerator"
|
|
320
|
+
"JSHTMLFileSystemEntryFileEnumerator",
|
|
321
|
+
"JSHTMLUserAgent"
|
|
320
322
|
]
|
|
321
323
|
},
|
|
322
324
|
"node": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"JSBundleType": "framework",
|
|
3
3
|
"JSBundleIdentifier": "io.breakside.JSKit.SecurityKit",
|
|
4
|
-
"JSBundleVersion": "2024.
|
|
4
|
+
"JSBundleVersion": "2024.41.0",
|
|
5
5
|
"JSDevelopmentLanguage": "en",
|
|
6
6
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
7
7
|
"JSBundleEnvironments": {
|
|
@@ -9,5 +9,5 @@
|
|
|
9
9
|
"node": "SecurityKit+Node.js"
|
|
10
10
|
},
|
|
11
11
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
12
|
-
"GitRevision": "
|
|
12
|
+
"GitRevision": "bf643e90b060044223efa5a59f0d727332802563"
|
|
13
13
|
}
|
|
@@ -44,6 +44,9 @@ JSClass("SECCBORParser", JSObject, {
|
|
|
44
44
|
},
|
|
45
45
|
|
|
46
46
|
readNext: function(){
|
|
47
|
+
if (this.offset >= this.data.length){
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
47
50
|
var b = this.data[this.offset++];
|
|
48
51
|
var info = b & 0x1F;
|
|
49
52
|
var majorType = (b & 0xE0) >> 5;
|
|
@@ -65,6 +68,7 @@ JSClass("SECCBORParser", JSObject, {
|
|
|
65
68
|
case SECCBOR.MajorType.other:
|
|
66
69
|
return this.readOther(info);
|
|
67
70
|
}
|
|
71
|
+
return null;
|
|
68
72
|
},
|
|
69
73
|
|
|
70
74
|
readUnsignedInteger: function(info){
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
// See the License for the specific language governing permissions and
|
|
14
14
|
// limitations under the License.
|
|
15
15
|
|
|
16
|
+
// #import Foundation
|
|
16
17
|
// #import "SECDeviceAuthentication.js"
|
|
17
18
|
// #import "SECCipher.js"
|
|
18
19
|
// #import "SECSign.js"
|
|
@@ -99,21 +100,19 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
|
|
|
99
100
|
challenge: registration.challengeData,
|
|
100
101
|
pubKeyCredParams: [],
|
|
101
102
|
authenticatorSelection: {
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
// Without a resident key, we need something like a username that the user can
|
|
108
|
-
// provide so we can lookup allowed key IDs on a server and send them back to
|
|
109
|
-
// the client before authenticating
|
|
110
|
-
requireResidentKey: false,
|
|
111
|
-
residentKey: "discouraged",
|
|
103
|
+
// requiring a resident key is necessary for Android to
|
|
104
|
+
// actually save a passkey. Apple OSes will save a passkey
|
|
105
|
+
// regardless of resident key settings
|
|
106
|
+
requireResidentKey: registration.platform ? true : false,
|
|
107
|
+
residentKey: registration.platform ? "required" : "discouraged",
|
|
112
108
|
userVerification: registration.platform && !registration.conditional ? "required" : "discouraged",
|
|
113
109
|
authenticatorAttachment: registration.platform ? "platform" : "cross-platform"
|
|
114
110
|
},
|
|
115
111
|
attestation: "none",
|
|
116
|
-
timeout:
|
|
112
|
+
timeout: 60000,
|
|
113
|
+
extensions: {
|
|
114
|
+
credProps: true
|
|
115
|
+
}
|
|
117
116
|
};
|
|
118
117
|
if (registration.domain !== undefined){
|
|
119
118
|
info.rp.id = registration.domain;
|
|
@@ -141,6 +140,7 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
|
|
|
141
140
|
var jwk = credential.response.getPublicJWK();
|
|
142
141
|
var webauthn = credential.toJSON();
|
|
143
142
|
var result = {
|
|
143
|
+
name: credential.jskitName,
|
|
144
144
|
jwk: jwk,
|
|
145
145
|
challenge: registration.challengeData,
|
|
146
146
|
webauthn: webauthn
|
|
@@ -187,9 +187,9 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
|
|
|
187
187
|
}
|
|
188
188
|
var info = {
|
|
189
189
|
challenge: request.challengeData,
|
|
190
|
-
userVerification: "discouraged",
|
|
191
|
-
timeout:
|
|
192
|
-
allowCredentials: []
|
|
190
|
+
userVerification: request.platform ? "required" : "discouraged",
|
|
191
|
+
timeout: 60000,
|
|
192
|
+
allowCredentials: [],
|
|
193
193
|
};
|
|
194
194
|
if (request.domain){
|
|
195
195
|
info.rpId = request.domain;
|
|
@@ -207,7 +207,7 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
|
|
|
207
207
|
id: request.allowedKeyIDs[i].dataByDecodingBase64URL()
|
|
208
208
|
};
|
|
209
209
|
if (request.platform){
|
|
210
|
-
allowedCredential.transports = ["internal"];
|
|
210
|
+
allowedCredential.transports = ["internal", "hybrid"];
|
|
211
211
|
}
|
|
212
212
|
info.allowCredentials.push(allowedCredential);
|
|
213
213
|
}catch (e){
|
|
@@ -265,12 +265,65 @@ if (window.PublicKeyCredential){
|
|
|
265
265
|
dictionary.rawId = JSData.initWithBuffer(this.rawId).base64URLStringRepresentation();
|
|
266
266
|
dictionary.authenticatorAttachment = this.authenticatorAttachment || "";
|
|
267
267
|
dictionary.type = this.type || "public-key";
|
|
268
|
-
dictionary.clientExtensionResults = this.getClientExtensionResults
|
|
268
|
+
dictionary.clientExtensionResults = this.getClientExtensionResults();
|
|
269
269
|
dictionary.response = this.response.toJSON ? this.response.toJSON() : {};
|
|
270
270
|
return dictionary;
|
|
271
271
|
};
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
+
if (!window.PublicKeyCredential.prototype.getClientExtensionResults){
|
|
275
|
+
window.PublicKeyCredential.prototype.getClientExtensionResults = function PublicKeyCredential_getClientExtensionResults(){
|
|
276
|
+
if (this._clientExtensionResults === undefined){
|
|
277
|
+
var authData = JSData.initWithBuffer(this.getAuthenticatorData());
|
|
278
|
+
var idLength = (authData[53] << 8) | authData[54];
|
|
279
|
+
var offset = 55 + idLength;
|
|
280
|
+
var cbor = SECCBORParser.initWithData(authData.subdataInRange(JSRange(offset, authData.length - offset)));
|
|
281
|
+
var coseKey = cbor.readNext(); // ingored, only reading to arrive at the extensions start location
|
|
282
|
+
this._clientExtensionResults = cbor.readNext() || {};
|
|
283
|
+
}
|
|
284
|
+
return this._clientExtensionResults;
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
Object.defineProperties(window.PublicKeyCredential.prototype, {
|
|
289
|
+
jskitName: {
|
|
290
|
+
enumerable: false,
|
|
291
|
+
configurable: false,
|
|
292
|
+
get: function PublicKeyCredential_getJSKitName(){
|
|
293
|
+
var extensions = this.getClientExtensionResults();
|
|
294
|
+
if (extensions.credProps){
|
|
295
|
+
if (extensions.credProps.authenticatorDisplayName){
|
|
296
|
+
return extensions.credProps.authenticatorDisplayName;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
var ua = JSHTMLUserAgent.initWithString(navigator.userAgent);
|
|
300
|
+
var apple = ua.containsComment("Macintosh") || ua.containsComment("iPhone") || ua.containsComment("iPad");
|
|
301
|
+
var windows = ua.containsComment("Win64") || ua.containsComment("Windows NT 10.0");
|
|
302
|
+
var linux = ua.containsComment("Linux");
|
|
303
|
+
var android = false;
|
|
304
|
+
if (linux){
|
|
305
|
+
var i, l;
|
|
306
|
+
for (i = 0, l = ua.comments.length; i < l; ++i){
|
|
307
|
+
if (ua.comments[i].startsWith("Android")){
|
|
308
|
+
android = true;
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (apple){
|
|
314
|
+
return "iCloud Keychain";
|
|
315
|
+
}
|
|
316
|
+
if (android){
|
|
317
|
+
return "Google Password Manager";
|
|
318
|
+
}
|
|
319
|
+
if (windows){
|
|
320
|
+
return "Windows Hello";
|
|
321
|
+
}
|
|
322
|
+
return "";
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
|
|
274
327
|
}
|
|
275
328
|
|
|
276
329
|
if (window.AuthenticatorAttestationResponse){
|
|
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.SecurityKit'] = {
|
|
|
3
3
|
"Info": {
|
|
4
4
|
"JSBundleType": "framework",
|
|
5
5
|
"JSBundleIdentifier": "io.breakside.JSKit.SecurityKit",
|
|
6
|
-
"JSBundleVersion": "2024.
|
|
6
|
+
"JSBundleVersion": "2024.41.0",
|
|
7
7
|
"JSDevelopmentLanguage": "en",
|
|
8
8
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
9
9
|
"JSBundleEnvironments": {
|
|
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.SecurityKit'] = {
|
|
|
11
11
|
"node": "SecurityKit+Node.js"
|
|
12
12
|
},
|
|
13
13
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
14
|
-
"GitRevision": "
|
|
14
|
+
"GitRevision": "bf643e90b060044223efa5a59f0d727332802563"
|
|
15
15
|
},
|
|
16
16
|
"Resources": [],
|
|
17
17
|
"ResourceLookup": {
|
package/Info.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"JSBundleType": "node",
|
|
3
3
|
"JSBundleIdentifier": "io.breakside.jskit",
|
|
4
|
-
"JSBundleVersion": "2024.
|
|
4
|
+
"JSBundleVersion": "2024.41.0",
|
|
5
5
|
"JSExecutableName": "jskit",
|
|
6
6
|
"NPMOrganization": "breakside",
|
|
7
7
|
"JSResources": [
|
|
8
8
|
"Tests/HTMLTestRunner.js",
|
|
9
9
|
"Tests/NodeTestRunner.js"
|
|
10
10
|
],
|
|
11
|
-
"GitRevision": "
|
|
11
|
+
"GitRevision": "bf643e90b060044223efa5a59f0d727332802563"
|
|
12
12
|
}
|
|
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.jskit'] = {
|
|
|
3
3
|
"Info": {
|
|
4
4
|
"JSBundleType": "node",
|
|
5
5
|
"JSBundleIdentifier": "io.breakside.jskit",
|
|
6
|
-
"JSBundleVersion": "2024.
|
|
6
|
+
"JSBundleVersion": "2024.41.0",
|
|
7
7
|
"JSExecutableName": "jskit",
|
|
8
8
|
"NPMOrganization": "breakside",
|
|
9
9
|
"JSResources": [
|
|
10
10
|
"Tests/HTMLTestRunner.js",
|
|
11
11
|
"Tests/NodeTestRunner.js"
|
|
12
12
|
],
|
|
13
|
-
"GitRevision": "
|
|
13
|
+
"GitRevision": "bf643e90b060044223efa5a59f0d727332802563"
|
|
14
14
|
},
|
|
15
15
|
"Resources": [
|
|
16
16
|
{
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// Copyright 2021 Breakside Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Breakside Public License, Version 1.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// If a copy of the License was not distributed with this file, you may
|
|
6
|
+
// obtain a copy at
|
|
7
|
+
//
|
|
8
|
+
// http://breakside.io/licenses/LICENSE-1.0.txt
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
|
|
16
|
+
// #import "JSObject.js"
|
|
17
|
+
"use strict";
|
|
18
|
+
|
|
19
|
+
JSClass("JSHTMLUserAgent", JSObject, {
|
|
20
|
+
|
|
21
|
+
string: null,
|
|
22
|
+
products: null,
|
|
23
|
+
productsByIdentifier: null,
|
|
24
|
+
comments: null,
|
|
25
|
+
commentSet: null,
|
|
26
|
+
|
|
27
|
+
initWithString: function(string){
|
|
28
|
+
if (string === null || string === undefined){
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
this.string = string;
|
|
32
|
+
this.products = [];
|
|
33
|
+
this.productsByIdentifier = new Set();
|
|
34
|
+
this.comments = [];
|
|
35
|
+
this.commentSet = new Set();
|
|
36
|
+
this.parse();
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
parse: function(){
|
|
40
|
+
var str = this.string;
|
|
41
|
+
var i = 0;
|
|
42
|
+
var l = this.string.length;
|
|
43
|
+
var product = "";
|
|
44
|
+
var version = "";
|
|
45
|
+
var comment = "";
|
|
46
|
+
while (i < l){
|
|
47
|
+
while (str[i] == " " || str[i] == "\t"){
|
|
48
|
+
++i;
|
|
49
|
+
}
|
|
50
|
+
if (i < l){
|
|
51
|
+
if (str[i] == "("){
|
|
52
|
+
comment = "";
|
|
53
|
+
++i;
|
|
54
|
+
while (i < l && str[i] !== ")"){
|
|
55
|
+
if (str[i] == ";"){
|
|
56
|
+
comment = comment.trim();
|
|
57
|
+
if (comment !== ""){
|
|
58
|
+
this.addComment(comment);
|
|
59
|
+
}
|
|
60
|
+
comment = "";
|
|
61
|
+
}else{
|
|
62
|
+
comment += str[i];
|
|
63
|
+
}
|
|
64
|
+
++i;
|
|
65
|
+
}
|
|
66
|
+
comment = comment.trim();
|
|
67
|
+
if (comment !== ""){
|
|
68
|
+
this.addComment(comment);
|
|
69
|
+
}
|
|
70
|
+
if (i < l){
|
|
71
|
+
++i;
|
|
72
|
+
}
|
|
73
|
+
}else{
|
|
74
|
+
product = "";
|
|
75
|
+
version = "";
|
|
76
|
+
while (i < l && str[i] !== "/" && str[i] !== " " && str[i] !== "\t"){
|
|
77
|
+
product += str[i];
|
|
78
|
+
++i;
|
|
79
|
+
}
|
|
80
|
+
if (i < l && str[i] == "/"){
|
|
81
|
+
++i;
|
|
82
|
+
while (i < l && str[i] !== "(" && str[i] !== " " && str[i] !== "\t"){
|
|
83
|
+
version += str[i];
|
|
84
|
+
++i;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
this.addProduct(product, version);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
addProduct: function(name, version){
|
|
94
|
+
if (version === "" || version === undefined){
|
|
95
|
+
version = null;
|
|
96
|
+
}
|
|
97
|
+
var product = {name: name, version: version};
|
|
98
|
+
this.products.push(product);
|
|
99
|
+
this.productsByIdentifier[name] = product;
|
|
100
|
+
if (version !== null){
|
|
101
|
+
this.productsByIdentifier["%s/%s".sprintf(name, version)] = product;
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
addComment: function(comment){
|
|
106
|
+
this.comments.push(comment);
|
|
107
|
+
this.commentSet.add(comment);
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
containsProduct: function(name, version){
|
|
111
|
+
if (version === undefined || version === null || version === ""){
|
|
112
|
+
return name in this.productsByIdentifier;
|
|
113
|
+
}
|
|
114
|
+
return "%s/%s".sprintf(name, version) in this.productsByIdentifier;
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
versionOfProduct: function(name){
|
|
118
|
+
var product = this.productsByIdentifier[name];
|
|
119
|
+
if (product){
|
|
120
|
+
return product.version;
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
containsComment: function(comment){
|
|
126
|
+
return this.commentSet.has(comment);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
});
|
|
130
|
+
|
|
@@ -44,6 +44,9 @@ JSClass("SECCBORParser", JSObject, {
|
|
|
44
44
|
},
|
|
45
45
|
|
|
46
46
|
readNext: function(){
|
|
47
|
+
if (this.offset >= this.data.length){
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
47
50
|
var b = this.data[this.offset++];
|
|
48
51
|
var info = b & 0x1F;
|
|
49
52
|
var majorType = (b & 0xE0) >> 5;
|
|
@@ -65,6 +68,7 @@ JSClass("SECCBORParser", JSObject, {
|
|
|
65
68
|
case SECCBOR.MajorType.other:
|
|
66
69
|
return this.readOther(info);
|
|
67
70
|
}
|
|
71
|
+
return null;
|
|
68
72
|
},
|
|
69
73
|
|
|
70
74
|
readUnsignedInteger: function(info){
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
// See the License for the specific language governing permissions and
|
|
14
14
|
// limitations under the License.
|
|
15
15
|
|
|
16
|
+
// #import Foundation
|
|
16
17
|
// #import "SECDeviceAuthentication.js"
|
|
17
18
|
// #import "SECCipher.js"
|
|
18
19
|
// #import "SECSign.js"
|
|
@@ -99,21 +100,19 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
|
|
|
99
100
|
challenge: registration.challengeData,
|
|
100
101
|
pubKeyCredParams: [],
|
|
101
102
|
authenticatorSelection: {
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
// Without a resident key, we need something like a username that the user can
|
|
108
|
-
// provide so we can lookup allowed key IDs on a server and send them back to
|
|
109
|
-
// the client before authenticating
|
|
110
|
-
requireResidentKey: false,
|
|
111
|
-
residentKey: "discouraged",
|
|
103
|
+
// requiring a resident key is necessary for Android to
|
|
104
|
+
// actually save a passkey. Apple OSes will save a passkey
|
|
105
|
+
// regardless of resident key settings
|
|
106
|
+
requireResidentKey: registration.platform ? true : false,
|
|
107
|
+
residentKey: registration.platform ? "required" : "discouraged",
|
|
112
108
|
userVerification: registration.platform && !registration.conditional ? "required" : "discouraged",
|
|
113
109
|
authenticatorAttachment: registration.platform ? "platform" : "cross-platform"
|
|
114
110
|
},
|
|
115
111
|
attestation: "none",
|
|
116
|
-
timeout:
|
|
112
|
+
timeout: 60000,
|
|
113
|
+
extensions: {
|
|
114
|
+
credProps: true
|
|
115
|
+
}
|
|
117
116
|
};
|
|
118
117
|
if (registration.domain !== undefined){
|
|
119
118
|
info.rp.id = registration.domain;
|
|
@@ -141,6 +140,7 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
|
|
|
141
140
|
var jwk = credential.response.getPublicJWK();
|
|
142
141
|
var webauthn = credential.toJSON();
|
|
143
142
|
var result = {
|
|
143
|
+
name: credential.jskitName,
|
|
144
144
|
jwk: jwk,
|
|
145
145
|
challenge: registration.challengeData,
|
|
146
146
|
webauthn: webauthn
|
|
@@ -187,9 +187,9 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
|
|
|
187
187
|
}
|
|
188
188
|
var info = {
|
|
189
189
|
challenge: request.challengeData,
|
|
190
|
-
userVerification: "discouraged",
|
|
191
|
-
timeout:
|
|
192
|
-
allowCredentials: []
|
|
190
|
+
userVerification: request.platform ? "required" : "discouraged",
|
|
191
|
+
timeout: 60000,
|
|
192
|
+
allowCredentials: [],
|
|
193
193
|
};
|
|
194
194
|
if (request.domain){
|
|
195
195
|
info.rpId = request.domain;
|
|
@@ -207,7 +207,7 @@ JSClass("SECHTMLDeviceAuthentication", JSObject, {
|
|
|
207
207
|
id: request.allowedKeyIDs[i].dataByDecodingBase64URL()
|
|
208
208
|
};
|
|
209
209
|
if (request.platform){
|
|
210
|
-
allowedCredential.transports = ["internal"];
|
|
210
|
+
allowedCredential.transports = ["internal", "hybrid"];
|
|
211
211
|
}
|
|
212
212
|
info.allowCredentials.push(allowedCredential);
|
|
213
213
|
}catch (e){
|
|
@@ -265,12 +265,65 @@ if (window.PublicKeyCredential){
|
|
|
265
265
|
dictionary.rawId = JSData.initWithBuffer(this.rawId).base64URLStringRepresentation();
|
|
266
266
|
dictionary.authenticatorAttachment = this.authenticatorAttachment || "";
|
|
267
267
|
dictionary.type = this.type || "public-key";
|
|
268
|
-
dictionary.clientExtensionResults = this.getClientExtensionResults
|
|
268
|
+
dictionary.clientExtensionResults = this.getClientExtensionResults();
|
|
269
269
|
dictionary.response = this.response.toJSON ? this.response.toJSON() : {};
|
|
270
270
|
return dictionary;
|
|
271
271
|
};
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
+
if (!window.PublicKeyCredential.prototype.getClientExtensionResults){
|
|
275
|
+
window.PublicKeyCredential.prototype.getClientExtensionResults = function PublicKeyCredential_getClientExtensionResults(){
|
|
276
|
+
if (this._clientExtensionResults === undefined){
|
|
277
|
+
var authData = JSData.initWithBuffer(this.getAuthenticatorData());
|
|
278
|
+
var idLength = (authData[53] << 8) | authData[54];
|
|
279
|
+
var offset = 55 + idLength;
|
|
280
|
+
var cbor = SECCBORParser.initWithData(authData.subdataInRange(JSRange(offset, authData.length - offset)));
|
|
281
|
+
var coseKey = cbor.readNext(); // ingored, only reading to arrive at the extensions start location
|
|
282
|
+
this._clientExtensionResults = cbor.readNext() || {};
|
|
283
|
+
}
|
|
284
|
+
return this._clientExtensionResults;
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
Object.defineProperties(window.PublicKeyCredential.prototype, {
|
|
289
|
+
jskitName: {
|
|
290
|
+
enumerable: false,
|
|
291
|
+
configurable: false,
|
|
292
|
+
get: function PublicKeyCredential_getJSKitName(){
|
|
293
|
+
var extensions = this.getClientExtensionResults();
|
|
294
|
+
if (extensions.credProps){
|
|
295
|
+
if (extensions.credProps.authenticatorDisplayName){
|
|
296
|
+
return extensions.credProps.authenticatorDisplayName;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
var ua = JSHTMLUserAgent.initWithString(navigator.userAgent);
|
|
300
|
+
var apple = ua.containsComment("Macintosh") || ua.containsComment("iPhone") || ua.containsComment("iPad");
|
|
301
|
+
var windows = ua.containsComment("Win64") || ua.containsComment("Windows NT 10.0");
|
|
302
|
+
var linux = ua.containsComment("Linux");
|
|
303
|
+
var android = false;
|
|
304
|
+
if (linux){
|
|
305
|
+
var i, l;
|
|
306
|
+
for (i = 0, l = ua.comments.length; i < l; ++i){
|
|
307
|
+
if (ua.comments[i].startsWith("Android")){
|
|
308
|
+
android = true;
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (apple){
|
|
314
|
+
return "iCloud Keychain";
|
|
315
|
+
}
|
|
316
|
+
if (android){
|
|
317
|
+
return "Google Password Manager";
|
|
318
|
+
}
|
|
319
|
+
if (windows){
|
|
320
|
+
return "Windows Hello";
|
|
321
|
+
}
|
|
322
|
+
return "";
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
|
|
274
327
|
}
|
|
275
328
|
|
|
276
329
|
if (window.AuthenticatorAttestationResponse){
|
|
@@ -21,8 +21,9 @@
|
|
|
21
21
|
|
|
22
22
|
var mac = navigator.userAgent.indexOf("Macintosh") >= 0;
|
|
23
23
|
var iphone = navigator.userAgent.indexOf("iPhone") >= 0;
|
|
24
|
+
var ipad = navigator.userAgent.indexOf("iPad") >= 0;
|
|
24
25
|
|
|
25
|
-
if (mac || iphone){
|
|
26
|
+
if (mac || iphone || ipad){
|
|
26
27
|
UIPlatform.shared = UIPlatform.initWithIdentifier(UIPlatform.Identifier.mac);
|
|
27
28
|
}else{
|
|
28
29
|
UIPlatform.shared = UIPlatform.initWithIdentifier(UIPlatform.Identifier.win);
|