@gandalan/weblibs 1.0.9 → 1.0.11
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/api/IDAS.js +15 -62
- package/api/RESTClient.js +31 -108
- package/api/authUtils.js +75 -0
- package/package.json +1 -1
package/api/IDAS.js
CHANGED
|
@@ -1,82 +1,35 @@
|
|
|
1
|
+
import { jwtTokenInvalid } from "./authUtils";
|
|
1
2
|
import { RESTClient } from "./RESTClient";
|
|
2
|
-
import jwt_decode from "jwt-decode";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
let authToken = localStorage.getItem("IDAS_AuthToken");
|
|
6
|
-
let apiBaseUrl = localStorage.getItem("IDAS_ApiBaseUrl") || "https://api.dev.idas-cloudservices.net/api/";
|
|
7
|
-
let authJwtCallbackPath = localStorage.getItem("IDAS_AuthJwtCallbackPath") || "";
|
|
8
|
-
let authJwtToken;
|
|
9
|
-
|
|
10
|
-
export let IDASFactory = {
|
|
11
|
-
async create(settings = {
|
|
4
|
+
export function IDASFactory(settings = {
|
|
12
5
|
appToken : localStorage.getItem("IDAS_AppToken"),
|
|
13
6
|
mandantGuid : localStorage.getItem("IDAS_MandantGuid"),
|
|
14
7
|
apiBaseurl : localStorage.getItem("IDAS_ApiBaseUrl"),
|
|
15
8
|
jwtRefreshToken : localStorage.getItem("IDAS_AuthJwtRefreshToken"),
|
|
16
9
|
jwtCallbackPath : localStorage.getItem("IDAS_AuthJwtCallbackPath")
|
|
17
10
|
})
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
else if (settings.jwtRefreshToken) // it is authToken
|
|
29
|
-
{
|
|
30
|
-
console.log("init: with refresh/classic token");
|
|
31
|
-
let refreshClient = new RESTClient(apiBaseUrl, "");
|
|
32
|
-
await refreshClient.refreshToken();
|
|
33
|
-
idas = new IDAS();
|
|
34
|
-
await idas.authenticateWithJwt(authJwtCallbackPath);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return idas;
|
|
38
|
-
}
|
|
11
|
+
{
|
|
12
|
+
let idas = undefined;
|
|
13
|
+
if (!jwtTokenInvalid(settings))
|
|
14
|
+
{
|
|
15
|
+
console.log("init: with JWT token");
|
|
16
|
+
idas = new IDAS(settings);
|
|
17
|
+
}
|
|
18
|
+
else throw("Invalid settings: call setup first to obtain a valid JWT token!");
|
|
19
|
+
return idas;
|
|
39
20
|
}
|
|
40
21
|
|
|
41
22
|
class IDAS
|
|
42
23
|
{
|
|
43
24
|
restClient = undefined;
|
|
25
|
+
mandantGuid = localStorage.getItem("IDAS_MandantGuid");
|
|
44
26
|
|
|
45
|
-
|
|
46
|
-
{
|
|
47
|
-
authJwtToken = jwtToken;
|
|
48
|
-
this.restClient = new RESTClient(apiBaseUrl, jwtToken, true);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async authenticateWithJwt(authPath)
|
|
27
|
+
constructor(settings)
|
|
52
28
|
{
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
authJwtToken = undefined;
|
|
56
|
-
// ... so repeat authenticate (should lead to /Session login page)
|
|
57
|
-
new IDAS().authenticateWithJwt(authPath);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// still not valid JWT -> authenticate
|
|
61
|
-
if (!refreshClient.token) {
|
|
62
|
-
localStorage.setItem("IDAS_AuthJwtCallbackPath", authPath || "");
|
|
63
|
-
const authEndpoint = (new URL(window.location.href).origin) + authPath;
|
|
64
|
-
let authUrlCallback = `${authEndpoint}?r=%target%&j=%jwt%&m=%mandant%`;
|
|
65
|
-
authUrlCallback = authUrlCallback.replace("%target%", encodeURIComponent(window.location.href));
|
|
66
|
-
|
|
67
|
-
const url = new URL(apiBaseUrl);
|
|
68
|
-
url.pathname = "/Session";
|
|
69
|
-
url.search = `?a=${appToken}&r=${encodeURIComponent(authUrlCallback)}`;
|
|
70
|
-
let jwtUrl = url.toString();
|
|
71
|
-
|
|
72
|
-
window.location = jwtUrl;
|
|
73
|
-
} else {
|
|
74
|
-
this.initWithJWTtoken(refreshClient.token);
|
|
75
|
-
}
|
|
29
|
+
this.settings = settings;
|
|
30
|
+
this.restClient = new RESTClient(settings);
|
|
76
31
|
}
|
|
77
32
|
|
|
78
|
-
mandantGuid = localStorage.getItem("IDAS_MandantGuid");
|
|
79
|
-
|
|
80
33
|
claims = {
|
|
81
34
|
hasClaim(key) {
|
|
82
35
|
if (!authJwtToken) {
|
package/api/RESTClient.js
CHANGED
|
@@ -1,126 +1,49 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
/*export let AppToken = "66B70E0B-F7C4-4829-B12A-18AD309E3970";
|
|
5
|
-
export let AuthToken = localStorage.getItem("AuthToken");
|
|
6
|
-
export let MandantGuid = localStorage.getItem("MandantGuid");
|
|
7
|
-
export let ApiBaseUrl = localStorage.getItem("ApiBaseUrl") || "https://api.dev.idas-cloudservices.net/api";
|
|
8
|
-
export let SiteBaseUrl = window.location.origin;
|
|
9
|
-
export let SSOAuthUrl = ApiBaseUrl.replace("/api", '') + "/SSO?a=" + AppToken + "&r=%target%?t=%token%%26m=%mandant%";*/
|
|
10
|
-
|
|
11
|
-
let authJwtRefreshToken = localStorage.getItem("IDAS_AuthJwtRefreshToken");
|
|
2
|
+
import { jwtTokenInvalid, jwtTokenRenew } from './authUtils';
|
|
12
3
|
|
|
13
4
|
export class RESTClient {
|
|
14
5
|
lastError = "";
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
this.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
6
|
+
settings = {};
|
|
7
|
+
|
|
8
|
+
constructor(settings)
|
|
9
|
+
{
|
|
10
|
+
this.settings = settings;
|
|
11
|
+
axios.defaults.baseURL = settings.apiBaseurl;
|
|
12
|
+
if (settings.jwtToken)
|
|
13
|
+
{
|
|
14
|
+
axios.defaults.headers.common["Authorization"] = "Bearer " + this.token;
|
|
15
|
+
axios.interceptors.request.use(async (config) => {
|
|
16
|
+
await this.checkTokenBeforeRequest(config);
|
|
17
|
+
return config;
|
|
18
|
+
});
|
|
19
|
+
} else {
|
|
20
|
+
// might contain the classic token for fallback
|
|
21
|
+
axios.defaults.headers.common["X-Gdl-AuthToken"] = settings.jwtRefreshToken;
|
|
26
22
|
}
|
|
27
|
-
|
|
28
|
-
if (this.token && isJWT) {
|
|
29
|
-
this.updateJwtToken(token);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
axios.interceptors.request.use(async (config) => {
|
|
33
|
-
await this.checkAuthorizationHeader(config);
|
|
34
|
-
return config;
|
|
35
|
-
});
|
|
36
23
|
}
|
|
37
24
|
|
|
38
|
-
async
|
|
25
|
+
async checkTokenBeforeRequest(config) {
|
|
39
26
|
let authHeader = config.headers["Authorization"];
|
|
40
|
-
if (authHeader && authHeader.toString().startsWith("Bearer "))
|
|
27
|
+
if (authHeader && authHeader.toString().startsWith("Bearer ")) // only check requests containing a Bearer token
|
|
28
|
+
{
|
|
41
29
|
let parts = authHeader.toString().split(" ");
|
|
42
30
|
let jwt = parts[1];
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// expired token - refresh
|
|
49
|
-
await this.checkRefreshToken(jwt);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async checkRefreshToken(jwt, authCallback) {
|
|
54
|
-
if (!jwt && authJwtRefreshToken) {
|
|
55
|
-
this.onError = (error, message) => {
|
|
56
|
-
// LoginJwt/Refresh failed, which means "refresh token" is expired/invalid...
|
|
57
|
-
if (message.indexOf("401") != -1 || message.indexOf("403") != -1) {
|
|
58
|
-
authJwtRefreshToken = undefined;
|
|
59
|
-
localStorage.removeItem("IDAS_AuthJwtRefreshToken");
|
|
60
|
-
// ... so repeat authenticate
|
|
61
|
-
authCallback && authCallback();
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
// fetch fresh JWT
|
|
66
|
-
await this.refreshToken();
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
this.token = jwt;
|
|
70
|
-
this.isJWT = true;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
isJwtTokenExpired(jwt) {
|
|
74
|
-
if (!jwt) {
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
let decoded = jwt_decode(jwt);
|
|
79
|
-
const utcNow = Date.parse(new Date().toUTCString()) / 1000;
|
|
80
|
-
|
|
81
|
-
if (decoded && decoded.exp >= utcNow) {
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return true;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
updateJwtToken(jwt) {
|
|
89
|
-
let decoded = jwt_decode(jwt);
|
|
90
|
-
let refreshToken = decoded["refreshToken"] || "";
|
|
91
|
-
localStorage.setItem("IDAS_AuthJwtRefreshToken", refreshToken);
|
|
92
|
-
authJwtRefreshToken = refreshToken;
|
|
93
|
-
this.token = jwt;
|
|
94
|
-
this.isJWT = true;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
async refreshToken() {
|
|
98
|
-
try {
|
|
99
|
-
await axios.put(`${this.baseurl}/LoginJwt/Refresh`, { token: localStorage.getItem("IDAS_AuthJwtRefreshToken") })
|
|
100
|
-
.then(resp => {
|
|
101
|
-
this.updateJwtToken(resp.data);
|
|
102
|
-
});
|
|
103
|
-
} catch (error) {
|
|
104
|
-
this.handleError(error);
|
|
31
|
+
if (this.settings.jwtToken === jwt && jwtTokenInvalid(this.settings)) // ignore custom/different JWT tokens
|
|
32
|
+
await jwtTokenRenew(this.settings);
|
|
105
33
|
}
|
|
106
34
|
}
|
|
107
35
|
|
|
108
|
-
updateToken(token) {
|
|
109
|
-
this.token = token;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
36
|
getUrlOptions(noJWT = false) {
|
|
113
37
|
let options = { withCredentials: false }
|
|
114
|
-
if (this.isJWT && !noJWT) {
|
|
38
|
+
/*if (this.isJWT && !noJWT) {
|
|
115
39
|
options.headers = { Authorization: `Bearer ${this.token}` }
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return options
|
|
40
|
+
}*/
|
|
41
|
+
return options;
|
|
119
42
|
}
|
|
120
43
|
|
|
121
44
|
async get(uri, noJWT = false) {
|
|
122
45
|
try {
|
|
123
|
-
const response = await axios.get(
|
|
46
|
+
const response = await axios.get(uri, this.getUrlOptions(noJWT));
|
|
124
47
|
this.lastError = "";
|
|
125
48
|
return response.data;
|
|
126
49
|
} catch (error) {
|
|
@@ -130,7 +53,7 @@ export class RESTClient {
|
|
|
130
53
|
|
|
131
54
|
async getFile(uri) {
|
|
132
55
|
try {
|
|
133
|
-
const response = await axios.get(
|
|
56
|
+
const response = await axios.get(uri, { responseType: "blob" });
|
|
134
57
|
let fileName = "1000.pdf";
|
|
135
58
|
if (response.headers["content-disposition"]) {
|
|
136
59
|
fileName = response.headers["content-disposition"].split(";")[1];
|
|
@@ -146,7 +69,7 @@ export class RESTClient {
|
|
|
146
69
|
async getRaw(uri, noJWT = false) {
|
|
147
70
|
let response = {};
|
|
148
71
|
try {
|
|
149
|
-
response = await axios.get(
|
|
72
|
+
response = await axios.get(uri, this.getUrlOptions(noJWT))
|
|
150
73
|
this.lastError = "";
|
|
151
74
|
} catch (error) {
|
|
152
75
|
this.handleError(error);
|
|
@@ -156,7 +79,7 @@ export class RESTClient {
|
|
|
156
79
|
|
|
157
80
|
async post(uri, formData, noJWT = false) {
|
|
158
81
|
try {
|
|
159
|
-
const response = await axios.post(
|
|
82
|
+
const response = await axios.post(uri, formData, this.getUrlOptions(noJWT));
|
|
160
83
|
this.lastError = "";
|
|
161
84
|
return response;
|
|
162
85
|
} catch (error) {
|
|
@@ -166,7 +89,7 @@ export class RESTClient {
|
|
|
166
89
|
|
|
167
90
|
async put(uri, formData, noJWT = false) {
|
|
168
91
|
try {
|
|
169
|
-
const response = await axios.put(
|
|
92
|
+
const response = await axios.put(uri, formData, this.getUrlOptions(noJWT));
|
|
170
93
|
this.lastError = "";
|
|
171
94
|
return response;
|
|
172
95
|
} catch (error) {
|
|
@@ -176,7 +99,7 @@ export class RESTClient {
|
|
|
176
99
|
|
|
177
100
|
async delete(uri, noJWT = false) {
|
|
178
101
|
try {
|
|
179
|
-
const response = await axios.delete(
|
|
102
|
+
const response = await axios.delete(uri, this.getUrlOptions(noJWT));
|
|
180
103
|
this.lastError = "";
|
|
181
104
|
return response;
|
|
182
105
|
} catch (error) {
|
package/api/authUtils.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { RESTClient } from "./RESTClient";
|
|
2
|
+
import jwt_decode from "jwt-decode";
|
|
3
|
+
|
|
4
|
+
export async function setup(settings)
|
|
5
|
+
{
|
|
6
|
+
console.log("Setup");
|
|
7
|
+
if (settings.jwtRefreshToken && jwtTokenInvalid(settings))
|
|
8
|
+
{
|
|
9
|
+
const payload = { "Token" : settings.jwtRefreshToken };
|
|
10
|
+
// Fetch Token from IDAS API
|
|
11
|
+
let api = new RESTClient(settings);
|
|
12
|
+
const response = await api.put("Login/Update", payload);
|
|
13
|
+
const iat = response.data;
|
|
14
|
+
console.log("Got IDAS token: ", iat);
|
|
15
|
+
|
|
16
|
+
// If valid, check roles and authenticate against JWT API
|
|
17
|
+
if (iat)
|
|
18
|
+
await jwtTokenRenew(settings);
|
|
19
|
+
|
|
20
|
+
if (jwtTokenInvalid(settings))
|
|
21
|
+
console.log("Attention: no valid JWT token!");
|
|
22
|
+
|
|
23
|
+
} else {
|
|
24
|
+
console.log("Settings already have a valid JWT token, nothing to do");
|
|
25
|
+
}
|
|
26
|
+
console.log("Setup finished", settings);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function jwtTokenInvalid(settings)
|
|
30
|
+
{
|
|
31
|
+
if (!settings.jwtToken)
|
|
32
|
+
return true;
|
|
33
|
+
let decoded = jwt_decode(settings.jwtToken);
|
|
34
|
+
const utcNow = Date.parse(new Date().toUTCString()) / 1000;
|
|
35
|
+
if (decoded && decoded.exp > utcNow)
|
|
36
|
+
return false;
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function jwtTokenRenew(settings)
|
|
41
|
+
{
|
|
42
|
+
let api = new RESTClient(settings);
|
|
43
|
+
const payload = { "Token" : settings.jwtRefreshToken };
|
|
44
|
+
const response = await api.put("LoginJwt/Refresh", payload);
|
|
45
|
+
settings.jwtToken = response.data;
|
|
46
|
+
console.log("Got JWT token:", response.data);
|
|
47
|
+
|
|
48
|
+
let decoded = jwt_decode(settings.jwtToken);
|
|
49
|
+
let refreshToken = decoded["refreshToken"] || "";
|
|
50
|
+
if (refreshToken)
|
|
51
|
+
{
|
|
52
|
+
console.log("Got new refresh token:", refreshToken);
|
|
53
|
+
settings.jwtRefreshToken = refreshToken;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (jwtTokenInvalid(settings))
|
|
57
|
+
console.log("Token is already expired!");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function jwtAuthenticateOnBackend(settings, authPath)
|
|
61
|
+
{
|
|
62
|
+
localStorage.setItem("IDAS_AuthJwtCallbackPath", authPath || "");
|
|
63
|
+
const authEndpoint = (new URL(window.location.href).origin) + authPath;
|
|
64
|
+
let authUrlCallback = `${authEndpoint}?r=%target%&j=%jwt%&m=%mandant%`;
|
|
65
|
+
authUrlCallback = authUrlCallback.replace("%target%", encodeURIComponent(window.location.href));
|
|
66
|
+
|
|
67
|
+
const url = new URL(settings.apiBaseurl);
|
|
68
|
+
url.pathname = "/Session";
|
|
69
|
+
url.search = `?a=${settings.appToken}&r=${encodeURIComponent(authUrlCallback)}`;
|
|
70
|
+
let jwtUrl = url.toString();
|
|
71
|
+
|
|
72
|
+
window.location = jwtUrl;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|