authscape 1.0.762 → 1.0.764
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/index.js +849 -181
- package/package.json +3 -3
- package/src/components/AuthScapeApp.js +459 -38
- package/src/services/apiService.js +50 -150
- package/src/services/authService.js +13 -2
- package/src/services/signInValidator.js +33 -5
|
@@ -3,11 +3,22 @@ import querystring from 'query-string';
|
|
|
3
3
|
import fileDownload from 'js-file-download';
|
|
4
4
|
import Cookies from 'js-cookie';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// Cookie utility function
|
|
7
|
+
const setCookie = (name, value, options = {}) => {
|
|
8
|
+
return new Promise((resolve) => {
|
|
9
|
+
let cookieString = `${name}=${value};`;
|
|
10
|
+
if (options.maxAge) cookieString += `max-age=${options.maxAge};`;
|
|
11
|
+
if (options.path) cookieString += `path=${options.path};`;
|
|
12
|
+
if (options.domain) cookieString += `domain=${options.domain};`;
|
|
13
|
+
if (options.secure) cookieString += `secure;`;
|
|
14
|
+
document.cookie = cookieString;
|
|
15
|
+
resolve();
|
|
16
|
+
});
|
|
17
|
+
};
|
|
7
18
|
|
|
19
|
+
const setupDefaultOptions = async (ctx = null) => {
|
|
8
20
|
let defaultOptions = {};
|
|
9
|
-
if (ctx == null)
|
|
10
|
-
{
|
|
21
|
+
if (ctx == null) {
|
|
11
22
|
let accessToken = Cookies.get('access_token') || '';
|
|
12
23
|
|
|
13
24
|
if (accessToken !== null && accessToken !== undefined && accessToken != "") {
|
|
@@ -16,19 +27,14 @@ const setupDefaultOptions = async (ctx = null) => {
|
|
|
16
27
|
Authorization: "Bearer " + accessToken
|
|
17
28
|
}
|
|
18
29
|
};
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
30
|
+
} else {
|
|
21
31
|
defaultOptions = {
|
|
22
|
-
headers: {
|
|
23
|
-
},
|
|
32
|
+
headers: {},
|
|
24
33
|
};
|
|
25
34
|
}
|
|
26
|
-
}
|
|
27
|
-
else
|
|
28
|
-
{
|
|
35
|
+
} else {
|
|
29
36
|
defaultOptions = {
|
|
30
|
-
headers: {
|
|
31
|
-
},
|
|
37
|
+
headers: {},
|
|
32
38
|
};
|
|
33
39
|
}
|
|
34
40
|
|
|
@@ -36,7 +42,6 @@ const setupDefaultOptions = async (ctx = null) => {
|
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
const RefreshToken = async (originalRequest, instance) => {
|
|
39
|
-
|
|
40
45
|
let accessToken = Cookies.get('access_token') || '';
|
|
41
46
|
let refreshToken = Cookies.get('refresh_token') || '';
|
|
42
47
|
|
|
@@ -53,69 +58,36 @@ const RefreshToken = async (originalRequest, instance) => {
|
|
|
53
58
|
}
|
|
54
59
|
});
|
|
55
60
|
|
|
56
|
-
if (response != null && response.status == 200)
|
|
57
|
-
{
|
|
61
|
+
if (response != null && response.status == 200) {
|
|
58
62
|
let domainHost = window.location.hostname.split('.').slice(-2).join('.');
|
|
59
63
|
originalRequest.headers['Authorization'] = 'Bearer ' + response.data.access_token;
|
|
60
64
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
65
|
await setCookie('access_token', response.data.access_token, {
|
|
66
|
-
maxAge: 60 * 60 * 24 * 365,
|
|
66
|
+
maxAge: 60 * 60 * 24 * 365,
|
|
67
67
|
path: '/',
|
|
68
68
|
domain: domainHost,
|
|
69
69
|
secure: true
|
|
70
70
|
});
|
|
71
71
|
|
|
72
72
|
await setCookie('expires_in', response.data.expires_in, {
|
|
73
|
-
maxAge: 60 * 60 * 24 * 365,
|
|
73
|
+
maxAge: 60 * 60 * 24 * 365,
|
|
74
74
|
path: '/',
|
|
75
75
|
domain: domainHost,
|
|
76
76
|
secure: true
|
|
77
77
|
});
|
|
78
78
|
|
|
79
79
|
await setCookie('refresh_token', response.data.refresh_token, {
|
|
80
|
-
maxAge: 60 * 60 * 24 * 365,
|
|
80
|
+
maxAge: 60 * 60 * 24 * 365,
|
|
81
81
|
path: '/',
|
|
82
82
|
domain: domainHost,
|
|
83
83
|
secure: true
|
|
84
84
|
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
// await setCookie(null, "access_token", response.data.access_token,
|
|
89
|
-
// {
|
|
90
|
-
// maxAge: 2147483647,
|
|
91
|
-
// path: '/',
|
|
92
|
-
// domain: domainHost,
|
|
93
|
-
// secure: true
|
|
94
|
-
// });
|
|
95
|
-
|
|
96
|
-
// await setCookie(null, "expires_in", response.data.expires_in,
|
|
97
|
-
// {
|
|
98
|
-
// maxAge: 2147483647,
|
|
99
|
-
// path: '/',
|
|
100
|
-
// domain: domainHost,
|
|
101
|
-
// secure: true
|
|
102
|
-
// });
|
|
103
|
-
|
|
104
|
-
// await setCookie(null, "refresh_token", response.data.refresh_token,
|
|
105
|
-
// {
|
|
106
|
-
// maxAge: 2147483647,
|
|
107
|
-
// path: '/',
|
|
108
|
-
// domain: domainHost,
|
|
109
|
-
// secure: true
|
|
110
|
-
// });
|
|
111
85
|
}
|
|
112
86
|
}
|
|
113
87
|
|
|
114
88
|
export const apiService = (ctx = null) => {
|
|
115
|
-
|
|
116
89
|
let env = process.env.stage;
|
|
117
|
-
if (env == "development")
|
|
118
|
-
{
|
|
90
|
+
if (env == "development") {
|
|
119
91
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
120
92
|
}
|
|
121
93
|
|
|
@@ -123,185 +95,113 @@ export const apiService = (ctx = null) => {
|
|
|
123
95
|
|
|
124
96
|
const instance = axios.create({
|
|
125
97
|
baseURL: baseUri,
|
|
126
|
-
|
|
127
|
-
params: {} // do not remove this, its added to add params later in the config
|
|
98
|
+
params: {}
|
|
128
99
|
});
|
|
129
100
|
|
|
130
101
|
instance.interceptors.response.use(
|
|
131
102
|
(response) => {
|
|
132
|
-
|
|
133
|
-
return response;
|
|
103
|
+
return response;
|
|
134
104
|
},
|
|
135
105
|
async (error) => {
|
|
136
106
|
const originalConfig = error.config;
|
|
137
107
|
if (error.response) {
|
|
138
|
-
|
|
139
108
|
if (error.response.status === 401 && !originalConfig._retry) {
|
|
140
109
|
originalConfig._retry = true;
|
|
141
|
-
|
|
142
|
-
// Do something, call refreshToken() request for example;
|
|
143
110
|
await RefreshToken(originalConfig, instance);
|
|
144
|
-
|
|
145
|
-
// return a request
|
|
146
111
|
return instance.request(originalConfig);
|
|
147
112
|
}
|
|
148
113
|
|
|
149
114
|
if (error.response.status === 400) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (error.response.config.url.includes("/connect/token")) // remove the access and refresh if invalid
|
|
153
|
-
{
|
|
115
|
+
if (error.response.config.url.includes("/connect/token")) {
|
|
154
116
|
let domainHost = window.location.hostname.split('.').slice(-2).join('.');
|
|
155
|
-
|
|
156
|
-
|
|
157
117
|
Cookies.remove('access_token', { path: '/', domain: domainHost });
|
|
158
118
|
Cookies.remove('refresh_token', { path: '/', domain: domainHost });
|
|
159
119
|
Cookies.remove('expires_in', { path: '/', domain: domainHost });
|
|
160
|
-
|
|
161
|
-
// destroyCookie(null, "access_token", {
|
|
162
|
-
// maxAge: 2147483647,
|
|
163
|
-
// path: '/',
|
|
164
|
-
// domain: domainHost
|
|
165
|
-
// });
|
|
166
|
-
|
|
167
|
-
// destroyCookie(null, "refresh_token", {
|
|
168
|
-
// maxAge: 2147483647,
|
|
169
|
-
// path: '/',
|
|
170
|
-
// domain: domainHost
|
|
171
|
-
// });
|
|
172
|
-
|
|
173
|
-
// destroyCookie(null, "expires_in", {
|
|
174
|
-
// maxAge: 2147483647,
|
|
175
|
-
// path: '/',
|
|
176
|
-
// domain: domainHost
|
|
177
|
-
// });
|
|
178
120
|
}
|
|
179
|
-
|
|
180
121
|
return Promise.reject(error);
|
|
181
122
|
}
|
|
182
123
|
}
|
|
183
|
-
|
|
184
124
|
return Promise.reject(error);
|
|
185
125
|
}
|
|
186
126
|
);
|
|
187
127
|
|
|
188
128
|
return {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
try
|
|
193
|
-
{
|
|
129
|
+
get: async (url, options = {}) => {
|
|
130
|
+
try {
|
|
194
131
|
let defaultOptions = await setupDefaultOptions(ctx);
|
|
195
132
|
return await instance.get(url, { ...defaultOptions, ...options });
|
|
196
|
-
}
|
|
197
|
-
catch(error)
|
|
198
|
-
{
|
|
133
|
+
} catch (error) {
|
|
199
134
|
return error.response;
|
|
200
135
|
}
|
|
201
136
|
},
|
|
202
137
|
post: async (url, data, options = {}) => {
|
|
203
|
-
|
|
204
|
-
try
|
|
205
|
-
{
|
|
138
|
+
try {
|
|
206
139
|
let defaultOptions = await setupDefaultOptions(ctx);
|
|
207
140
|
return await instance.post(url, data, { ...defaultOptions, ...options });
|
|
208
|
-
}
|
|
209
|
-
catch(error)
|
|
210
|
-
{
|
|
141
|
+
} catch (error) {
|
|
211
142
|
return error.response;
|
|
212
143
|
}
|
|
213
144
|
},
|
|
214
145
|
put: async (url, data, options = {}) => {
|
|
215
|
-
|
|
216
|
-
try
|
|
217
|
-
{
|
|
146
|
+
try {
|
|
218
147
|
let defaultOptions = await setupDefaultOptions(ctx);
|
|
219
148
|
return await instance.put(url, data, { ...defaultOptions, ...options });
|
|
220
|
-
}
|
|
221
|
-
catch(error)
|
|
222
|
-
{
|
|
149
|
+
} catch (error) {
|
|
223
150
|
return error.response;
|
|
224
151
|
}
|
|
225
152
|
},
|
|
226
153
|
delete: async (url, options = {}) => {
|
|
227
|
-
|
|
228
|
-
try
|
|
229
|
-
{
|
|
154
|
+
try {
|
|
230
155
|
let defaultOptions = await setupDefaultOptions(ctx);
|
|
231
156
|
return await instance.delete(url, { ...defaultOptions, ...options });
|
|
232
|
-
}
|
|
233
|
-
catch(error)
|
|
234
|
-
{
|
|
157
|
+
} catch (error) {
|
|
235
158
|
return error.response;
|
|
236
159
|
}
|
|
237
160
|
},
|
|
238
161
|
GetCurrentUser: async () => {
|
|
239
|
-
|
|
240
|
-
try
|
|
241
|
-
{
|
|
162
|
+
try {
|
|
242
163
|
let accessToken = Cookies.get('access_token') || null;
|
|
243
164
|
|
|
244
|
-
if (accessToken)
|
|
245
|
-
{
|
|
165
|
+
if (accessToken) {
|
|
246
166
|
let defaultOptions = await setupDefaultOptions(null);
|
|
247
167
|
const response = await instance.get('/UserManagement', defaultOptions);
|
|
248
|
-
if (response != null && response.status == 200)
|
|
249
|
-
{
|
|
168
|
+
if (response != null && response.status == 200) {
|
|
250
169
|
return response.data;
|
|
251
170
|
}
|
|
252
|
-
// else if (response != null && response.status == 401)
|
|
253
|
-
// {
|
|
254
|
-
// // call the login window maybe?
|
|
255
|
-
// }
|
|
256
171
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
//return -1;
|
|
260
|
-
console.log(exp.message);
|
|
172
|
+
} catch (exp) {
|
|
173
|
+
// Token invalid or expired
|
|
261
174
|
}
|
|
262
|
-
return null;
|
|
175
|
+
return null;
|
|
263
176
|
},
|
|
264
|
-
DownloadFile
|
|
265
|
-
|
|
266
|
-
try
|
|
267
|
-
{
|
|
268
|
-
//let defaultOptions = await setupDefaultOptions();
|
|
177
|
+
DownloadFile: async (url, fileName, completed, method = "get", data = {}, mimeType = "application/octet-stream", passData = false) => {
|
|
178
|
+
try {
|
|
269
179
|
let defaultOptions = {};
|
|
270
180
|
let options = { responseType: "blob" };
|
|
271
181
|
|
|
272
182
|
let response = null;
|
|
273
|
-
if (method == "get")
|
|
274
|
-
{
|
|
183
|
+
if (method == "get") {
|
|
275
184
|
response = await instance.get(url, { ...defaultOptions, ...options });
|
|
276
|
-
}
|
|
277
|
-
else if (method == "post")
|
|
278
|
-
{
|
|
185
|
+
} else if (method == "post") {
|
|
279
186
|
response = await instance.post(url, data, { ...defaultOptions, ...options });
|
|
280
187
|
}
|
|
281
|
-
|
|
282
|
-
if (response != null && response.status === 200) {
|
|
283
188
|
|
|
284
|
-
|
|
285
|
-
{
|
|
189
|
+
if (response != null && response.status === 200) {
|
|
190
|
+
if (!passData) {
|
|
286
191
|
fileDownload(response.data, fileName, mimeType);
|
|
287
192
|
if (completed !== undefined) {
|
|
288
193
|
completed();
|
|
289
194
|
}
|
|
290
|
-
}
|
|
291
|
-
else
|
|
292
|
-
{
|
|
195
|
+
} else {
|
|
293
196
|
completed(response.data);
|
|
294
197
|
}
|
|
295
198
|
}
|
|
296
|
-
}
|
|
297
|
-
catch(error)
|
|
298
|
-
{
|
|
199
|
+
} catch (error) {
|
|
299
200
|
console.error(error);
|
|
300
201
|
if (completed !== undefined) {
|
|
301
202
|
completed();
|
|
302
203
|
}
|
|
303
204
|
}
|
|
304
|
-
|
|
305
205
|
}
|
|
306
206
|
}
|
|
307
|
-
}
|
|
207
|
+
}
|
|
@@ -75,16 +75,27 @@ export const authService = () => {
|
|
|
75
75
|
let verifier = authService().generateRandomString();
|
|
76
76
|
var challenge = await authService().challenge_from_verifier(verifier);
|
|
77
77
|
|
|
78
|
+
console.log('[PKCE] Login initiated');
|
|
79
|
+
console.log('[PKCE] Verifier generated | length:', verifier.length, '| preview:', verifier.substring(0, 10) + '...');
|
|
80
|
+
console.log('[PKCE] Challenge generated | value:', challenge);
|
|
81
|
+
console.log('[PKCE] authorityUri:', process.env.authorityUri);
|
|
82
|
+
console.log('[PKCE] client_id:', process.env.client_id);
|
|
83
|
+
|
|
78
84
|
window.localStorage.setItem("verifier", verifier);
|
|
79
85
|
|
|
86
|
+
const storedVerifier = window.localStorage.getItem("verifier");
|
|
87
|
+
console.log('[PKCE] Verifier stored successfully:', storedVerifier === verifier);
|
|
88
|
+
console.log('[PKCE] Stored verifier length:', storedVerifier?.length);
|
|
89
|
+
|
|
80
90
|
let redirectUri = window.location.origin + "/signin-oidc";
|
|
81
91
|
let loginUri = process.env.authorityUri + "/connect/authorize?response_type=code&state=" + state + "&client_id=" + process.env.client_id + "&scope=email%20openid%20offline_access%20profile%20api1&redirect_uri=" + redirectUri + "&code_challenge=" + challenge + "&code_challenge_method=S256";
|
|
82
|
-
|
|
92
|
+
|
|
83
93
|
if (deviceId)
|
|
84
94
|
{
|
|
85
95
|
loginUri += "&deviceId=" + deviceId; // will be for chrome extention and mobile apps later
|
|
86
96
|
}
|
|
87
|
-
|
|
97
|
+
|
|
98
|
+
console.log('[PKCE] Redirecting to:', loginUri);
|
|
88
99
|
window.location.href = loginUri;
|
|
89
100
|
},
|
|
90
101
|
signUp: (redirectUrl = null) => {
|
|
@@ -4,24 +4,52 @@ import querystring from "query-string";
|
|
|
4
4
|
// import Cookies from 'js-cookie';
|
|
5
5
|
|
|
6
6
|
export const signInValidator = async (queryCode) => {
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
let codeVerifier = window.localStorage.getItem("verifier");
|
|
9
|
+
|
|
10
|
+
console.log('[PKCE] signInValidator called');
|
|
11
|
+
console.log('[PKCE] queryCode present:', !!queryCode, '| value:', queryCode);
|
|
12
|
+
console.log('[PKCE] codeVerifier present:', !!codeVerifier, '| length:', codeVerifier?.length);
|
|
13
|
+
|
|
9
14
|
if (queryCode != null && codeVerifier != null)
|
|
10
15
|
{
|
|
11
16
|
const headers = {'Content-Type': 'application/x-www-form-urlencoded'}
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
const tokenParams = {
|
|
14
19
|
code: queryCode,
|
|
15
20
|
grant_type: "authorization_code",
|
|
16
21
|
redirect_uri: window.location.origin + "/signin-oidc",
|
|
17
22
|
client_id: process.env.client_id,
|
|
18
23
|
client_secret: process.env.client_secret,
|
|
19
24
|
code_verifier: codeVerifier
|
|
20
|
-
}
|
|
25
|
+
};
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
|
|
27
|
+
console.log('[PKCE] Token request params:', {
|
|
28
|
+
...tokenParams,
|
|
29
|
+
client_secret: tokenParams.client_secret ? '***' : '(missing!)',
|
|
30
|
+
code: tokenParams.code?.substring(0, 10) + '...',
|
|
31
|
+
code_verifier: tokenParams.code_verifier?.substring(0, 10) + '... (length: ' + tokenParams.code_verifier?.length + ')',
|
|
24
32
|
});
|
|
33
|
+
console.log('[PKCE] Token endpoint:', process.env.authorityUri + '/connect/token');
|
|
34
|
+
console.log('[PKCE] redirect_uri:', tokenParams.redirect_uri);
|
|
35
|
+
|
|
36
|
+
let queryString = querystring.stringify(tokenParams);
|
|
37
|
+
|
|
38
|
+
let response;
|
|
39
|
+
try {
|
|
40
|
+
response = await axios.post(process.env.authorityUri + '/connect/token', queryString, {
|
|
41
|
+
headers: headers
|
|
42
|
+
});
|
|
43
|
+
console.log('[PKCE] Token response status:', response.status);
|
|
44
|
+
console.log('[PKCE] Token response has access_token:', !!response.data?.access_token);
|
|
45
|
+
console.log('[PKCE] Token response has refresh_token:', !!response.data?.refresh_token);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
console.error('[PKCE] Token request FAILED');
|
|
48
|
+
console.error('[PKCE] Status:', err.response?.status);
|
|
49
|
+
console.error('[PKCE] Error data:', JSON.stringify(err.response?.data));
|
|
50
|
+
console.error('[PKCE] Error message:', err.message);
|
|
51
|
+
throw err;
|
|
52
|
+
}
|
|
25
53
|
|
|
26
54
|
let domainHost = window.location.hostname.split('.').slice(-2).join('.');
|
|
27
55
|
window.localStorage.removeItem("verifier");
|