eionet2-dashboard 3.2.6 → 3.2.7
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 +4 -2
- package/package.json +1 -1
- package/tabs/public/auth-end.html +37 -60
- package/tabs/public/auth-start.html +34 -162
package/CHANGELOG.md
CHANGED
|
@@ -4,11 +4,13 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
-
### [3.2.
|
|
7
|
+
### [3.2.7](https://github.com/eea/eionet2-dashboard/compare/3.2.6...3.2.7) - 16 May 2026
|
|
8
8
|
|
|
9
9
|
#### :house: Internal changes
|
|
10
10
|
|
|
11
|
-
- chore:
|
|
11
|
+
- chore: simplify auth [Mihai Nicolae - [`d1866bb`](https://github.com/eea/eionet2-dashboard/commit/d1866bb85b0e0b99d1732f2cd3407155f489e748)]
|
|
12
|
+
|
|
13
|
+
### [3.2.6](https://github.com/eea/eionet2-dashboard/compare/3.2.5...3.2.6) - 14 May 2026
|
|
12
14
|
|
|
13
15
|
### [3.2.5](https://github.com/eea/eionet2-dashboard/compare/3.2.4...3.2.5) - 14 May 2026
|
|
14
16
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<!--This file is used during the Teams authentication flow to assist with retrieval of the access token.-->
|
|
2
2
|
<!--If you're not familiar with this, do not alter or remove this file from your project.-->
|
|
3
|
-
|
|
4
|
-
<html lang="en">
|
|
3
|
+
<html>
|
|
5
4
|
|
|
6
5
|
<head>
|
|
7
6
|
<title>Login End Page</title>
|
|
@@ -9,68 +8,46 @@
|
|
|
9
8
|
</head>
|
|
10
9
|
|
|
11
10
|
<body>
|
|
12
|
-
<script src="https://
|
|
13
|
-
integrity="sha384-
|
|
11
|
+
<script src="https://res.cdn.office.net/teams-js/2.22.0/js/MicrosoftTeams.min.js"
|
|
12
|
+
integrity="sha384-WSG/sWulIv7rel5TnFlH8JTpxl2OxzZh9Lux2mIzBFiTRLFvMBeFv9VURu/3vQdx"
|
|
14
13
|
crossorigin="anonymous"></script>
|
|
14
|
+
<script type="text/javascript" src="https://alcdn.msauth.net/browser/2.35.0/js/msal-browser.min.js"
|
|
15
|
+
integrity="sha384-s/NxjjAgw1QgpDhOlVjTceLl4axrp5nqpUbCPOEQy1PqbFit9On6uw2XmEF1eq0s" crossorigin="anonymous">
|
|
16
|
+
</script>
|
|
15
17
|
<script type="text/javascript">
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
var currentURL = new URL(window.location);
|
|
19
|
+
var clientId = currentURL.searchParams.get("clientId");
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// State does not match, report error
|
|
32
|
-
microsoftTeams.authentication.notifyFailure(
|
|
33
|
-
JSON.stringify({
|
|
34
|
-
error: "StateDoesNotMatch",
|
|
35
|
-
message: JSON.stringify(hashParams),
|
|
36
|
-
})
|
|
37
|
-
);
|
|
38
|
-
} else {
|
|
39
|
-
// Success -- return code information to the parent page.
|
|
40
|
-
var redirectUri = location.protocol + "//" + location.host + location.pathname;
|
|
41
|
-
var result = JSON.stringify({
|
|
42
|
-
code: hashParams["code"],
|
|
43
|
-
codeVerifier: localStorage.getItem("codeVerifier"),
|
|
44
|
-
redirectUri: redirectUri,
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
microsoftTeams.authentication.notifySuccess(result);
|
|
48
|
-
}
|
|
49
|
-
} else {
|
|
50
|
-
// Unexpected condition: hash does not contain error or access_token parameter
|
|
51
|
-
microsoftTeams.authentication.notifyFailure(
|
|
52
|
-
JSON.stringify({
|
|
53
|
-
error: "UnexpectedFailure",
|
|
54
|
-
message: JSON.stringify(hashParams),
|
|
55
|
-
})
|
|
56
|
-
);
|
|
57
|
-
}
|
|
21
|
+
microsoftTeams.app.initialize().then(() => {
|
|
22
|
+
microsoftTeams.app.getContext().then(async (context) => {
|
|
23
|
+
const msalConfig = {
|
|
24
|
+
auth: {
|
|
25
|
+
clientId: clientId,
|
|
26
|
+
authority: `https://login.microsoftonline.com/${context.tid}`,
|
|
27
|
+
navigateToLoginRequestUrl: false
|
|
28
|
+
},
|
|
29
|
+
cache: {
|
|
30
|
+
cacheLocation: "sessionStorage",
|
|
31
|
+
},
|
|
32
|
+
}
|
|
58
33
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
34
|
+
const msalInstance = new window.msal.PublicClientApplication(msalConfig);
|
|
35
|
+
msalInstance.handleRedirectPromise()
|
|
36
|
+
.then((tokenResponse) => {
|
|
37
|
+
if (tokenResponse !== null) {
|
|
38
|
+
microsoftTeams.authentication.notifySuccess(JSON.stringify({
|
|
39
|
+
sessionStorage: sessionStorage
|
|
40
|
+
}));
|
|
41
|
+
} else {
|
|
42
|
+
microsoftTeams.authentication.notifyFailure("Get empty response.");
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
.catch((error) => {
|
|
46
|
+
microsoftTeams.authentication.notifyFailure(JSON.stringify(error));
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
73
50
|
</script>
|
|
74
51
|
</body>
|
|
75
52
|
|
|
76
|
-
</html>
|
|
53
|
+
</html>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<!--This file is used during the Teams authentication flow to assist with retrieval of the access token.-->
|
|
2
2
|
<!--If you're not familiar with this, do not alter or remove this file from your project.-->
|
|
3
|
-
|
|
4
|
-
<html lang="en">
|
|
3
|
+
<html>
|
|
5
4
|
|
|
6
5
|
<head>
|
|
7
6
|
<title>Login Start Page</title>
|
|
@@ -9,169 +8,42 @@
|
|
|
9
8
|
</head>
|
|
10
9
|
|
|
11
10
|
<body>
|
|
12
|
-
<script src="https://
|
|
13
|
-
integrity="sha384-
|
|
11
|
+
<script src="https://res.cdn.office.net/teams-js/2.22.0/js/MicrosoftTeams.min.js"
|
|
12
|
+
integrity="sha384-WSG/sWulIv7rel5TnFlH8JTpxl2OxzZh9Lux2mIzBFiTRLFvMBeFv9VURu/3vQdx"
|
|
14
13
|
crossorigin="anonymous"></script>
|
|
14
|
+
<script type="text/javascript" src="https://alcdn.msauth.net/browser/2.35.0/js/msal-browser.min.js"
|
|
15
|
+
integrity="sha384-s/NxjjAgw1QgpDhOlVjTceLl4axrp5nqpUbCPOEQy1PqbFit9On6uw2XmEF1eq0s" crossorigin="anonymous">
|
|
16
|
+
</script>
|
|
15
17
|
<script type="text/javascript">
|
|
16
|
-
microsoftTeams.initialize()
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
let authorizeEndpoint = `https://login.microsoftonline.com/${context.tid}
|
|
47
|
-
/oauth2/v2.0/authorize?${toQueryString(queryParams)}`;
|
|
48
|
-
window.location.assign(authorizeEndpoint);
|
|
18
|
+
microsoftTeams.app.initialize().then(() => {
|
|
19
|
+
microsoftTeams.app.getContext().then(async (context) => {
|
|
20
|
+
// Generate random state string and store it, so we can verify it in the callback
|
|
21
|
+
var currentURL = new URL(window.location);
|
|
22
|
+
var clientId = currentURL.searchParams.get("clientId");
|
|
23
|
+
var scope = currentURL.searchParams.get("scope");
|
|
24
|
+
var loginHint = currentURL.searchParams.get("loginHint");
|
|
25
|
+
|
|
26
|
+
const msalConfig = {
|
|
27
|
+
auth: {
|
|
28
|
+
clientId: clientId,
|
|
29
|
+
authority: `https://login.microsoftonline.com/${context.user.tenant.id}`,
|
|
30
|
+
navigateToLoginRequestUrl: false
|
|
31
|
+
},
|
|
32
|
+
cache: {
|
|
33
|
+
cacheLocation: "sessionStorage",
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const msalInstance = new msal.PublicClientApplication(msalConfig);
|
|
38
|
+
const scopesArray = scope.split(" ");
|
|
39
|
+
const scopesRequest = {
|
|
40
|
+
scopes: scopesArray,
|
|
41
|
+
redirectUri: window.location.origin + `/auth-end.html?clientId=${clientId}`,
|
|
42
|
+
loginHint: loginHint
|
|
43
|
+
};
|
|
44
|
+
await msalInstance.loginRedirect(scopesRequest);
|
|
45
|
+
});
|
|
49
46
|
});
|
|
50
|
-
|
|
51
|
-
// Build query string from map of query parameter
|
|
52
|
-
function toQueryString(queryParams) {
|
|
53
|
-
let encodedQueryParams = [];
|
|
54
|
-
for (let key in queryParams) {
|
|
55
|
-
encodedQueryParams.push(key + "=" + encodeURIComponent(queryParams[key]));
|
|
56
|
-
}
|
|
57
|
-
return encodedQueryParams.join("&");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Converts decimal to hex equivalent
|
|
61
|
-
// (From ADAL.js: https://github.com/AzureAD/azure-activedirectory-library-for-js/blob/dev/lib/adal.js)
|
|
62
|
-
function _decimalToHex(number) {
|
|
63
|
-
var hex = number.toString(16);
|
|
64
|
-
while (hex.length < 2) {
|
|
65
|
-
hex = "0" + hex;
|
|
66
|
-
}
|
|
67
|
-
return hex;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Generates RFC4122 version 4 guid (128 bits)
|
|
71
|
-
// (From ADAL.js: https://github.com/AzureAD/azure-activedirectory-library-for-js/blob/dev/lib/adal.js)
|
|
72
|
-
function _guid() {
|
|
73
|
-
// RFC4122: The version 4 UUID is meant for generating UUIDs from truly-random or
|
|
74
|
-
// pseudo-random numbers.
|
|
75
|
-
// The algorithm is as follows:
|
|
76
|
-
// Set the two most significant bits (bits 6 and 7) of the
|
|
77
|
-
// clock_seq_hi_and_reserved to zero and one, respectively.
|
|
78
|
-
// Set the four most significant bits (bits 12 through 15) of the
|
|
79
|
-
// time_hi_and_version field to the 4-bit version number from
|
|
80
|
-
// Section 4.1.3. Version4
|
|
81
|
-
// Set all the other bits to randomly (or pseudo-randomly) chosen
|
|
82
|
-
// values.
|
|
83
|
-
// UUID = time-low "-" time-mid "-"time-high-and-version "-"clock-seq-reserved and low(2hexOctet)"-" node
|
|
84
|
-
// time-low = 4hexOctet
|
|
85
|
-
// time-mid = 2hexOctet
|
|
86
|
-
// time-high-and-version = 2hexOctet
|
|
87
|
-
// clock-seq-and-reserved = hexOctet:
|
|
88
|
-
// clock-seq-low = hexOctet
|
|
89
|
-
// node = 6hexOctet
|
|
90
|
-
// Format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
|
|
91
|
-
// y could be 1000, 1001, 1010, 1011 since most significant two bits needs to be 10
|
|
92
|
-
// y values are 8, 9, A, B
|
|
93
|
-
var cryptoObj = window.crypto || window.msCrypto; // for IE 11
|
|
94
|
-
if (cryptoObj?.getRandomValues) {
|
|
95
|
-
var buffer = new Uint8Array(16);
|
|
96
|
-
cryptoObj.getRandomValues(buffer);
|
|
97
|
-
//buffer[6] and buffer[7] represents the time_hi_and_version field. We will set the four most significant bits (4 through 7) of buffer[6] to represent decimal number 4 (UUID version number).
|
|
98
|
-
buffer[6] |= 0x40; //buffer[6] | 01000000 will set the 6 bit to 1.
|
|
99
|
-
buffer[6] &= 0x4f; //buffer[6] & 01001111 will set the 4, 5, and 7 bit to 0 such that bits 4-7 == 0100 = "4".
|
|
100
|
-
//buffer[8] represents the clock_seq_hi_and_reserved field. We will set the two most significant bits (6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively.
|
|
101
|
-
buffer[8] |= 0x80; //buffer[8] | 10000000 will set the 7 bit to 1.
|
|
102
|
-
buffer[8] &= 0xbf; //buffer[8] & 10111111 will set the 6 bit to 0.
|
|
103
|
-
return (
|
|
104
|
-
_decimalToHex(buffer[0]) +
|
|
105
|
-
_decimalToHex(buffer[1]) +
|
|
106
|
-
_decimalToHex(buffer[2]) +
|
|
107
|
-
_decimalToHex(buffer[3]) +
|
|
108
|
-
"-" +
|
|
109
|
-
_decimalToHex(buffer[4]) +
|
|
110
|
-
_decimalToHex(buffer[5]) +
|
|
111
|
-
"-" +
|
|
112
|
-
_decimalToHex(buffer[6]) +
|
|
113
|
-
_decimalToHex(buffer[7]) +
|
|
114
|
-
"-" +
|
|
115
|
-
_decimalToHex(buffer[8]) +
|
|
116
|
-
_decimalToHex(buffer[9]) +
|
|
117
|
-
"-" +
|
|
118
|
-
_decimalToHex(buffer[10]) +
|
|
119
|
-
_decimalToHex(buffer[11]) +
|
|
120
|
-
_decimalToHex(buffer[12]) +
|
|
121
|
-
_decimalToHex(buffer[13]) +
|
|
122
|
-
_decimalToHex(buffer[14]) +
|
|
123
|
-
_decimalToHex(buffer[15])
|
|
124
|
-
);
|
|
125
|
-
} else {
|
|
126
|
-
var guidHolder = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
|
|
127
|
-
var hex = "0123456789abcdef";
|
|
128
|
-
var r = 0;
|
|
129
|
-
var guidResponse = "";
|
|
130
|
-
for (var i = 0; i < 36; i++) {
|
|
131
|
-
if (guidHolder[i] !== "-" && guidHolder[i] !== "4") {
|
|
132
|
-
// each x and y needs to be random
|
|
133
|
-
r = Math.trunc(Math.random() * 16);
|
|
134
|
-
}
|
|
135
|
-
if (guidHolder[i] === "x") {
|
|
136
|
-
guidResponse += hex[r];
|
|
137
|
-
} else if (guidHolder[i] === "y") {
|
|
138
|
-
// clock-seq-and-reserved first hex is filtered and remaining hex values are random
|
|
139
|
-
r &= 0x3; // bit and with 0011 to set pos 2 to zero ?0??
|
|
140
|
-
r |= 0x8; // set pos 3 to 1 as 1???
|
|
141
|
-
guidResponse += hex[r];
|
|
142
|
-
} else {
|
|
143
|
-
guidResponse += guidHolder[i];
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return guidResponse;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Calculate the SHA256 hash of the input text.
|
|
151
|
-
// Returns a promise that resolves to an ArrayBuffer
|
|
152
|
-
function sha256(plain) {
|
|
153
|
-
const encoder = new TextEncoder();
|
|
154
|
-
const data = encoder.encode(plain);
|
|
155
|
-
return window.crypto.subtle.digest("SHA-256", data);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Base64-urlencodes the input string
|
|
159
|
-
function base64urlencode(str) {
|
|
160
|
-
// Convert the ArrayBuffer to string using Uint8 array to convert to what btoa accepts.
|
|
161
|
-
// btoa accepts chars only within ascii 0-255 and base64 encodes them.
|
|
162
|
-
// Then convert the base64 encoded to base64url encoded
|
|
163
|
-
// (replace + with -, replace / with _, trim trailing =)
|
|
164
|
-
return btoa(String.fromCharCode.apply(null, new Uint8Array(str)))
|
|
165
|
-
.replace(/\+/g, "-")
|
|
166
|
-
.replace(/\//g, "_")
|
|
167
|
-
.replace(/=+$/, "");
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Return the base64-urlencoded sha256 hash for the PKCE challenge
|
|
171
|
-
async function pkceChallengeFromVerifier(v) {
|
|
172
|
-
const hashed = await sha256(v);
|
|
173
|
-
return base64urlencode(hashed);
|
|
174
|
-
}
|
|
175
47
|
</script>
|
|
176
48
|
</body>
|
|
177
49
|
|