@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 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
- let appToken = localStorage.getItem("IDAS_AppToken") || "66B70E0B-F7C4-4829-B12A-18AD309E3970";
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
- apiBaseUrl = settings.apiBaseurl;
20
- let idas = undefined;
21
-
22
- if (settings.jwtToken) // it is JWT
23
- {
24
- console.log("init: with JWT token");
25
- idas = new IDAS();
26
- idas.initWithJWTtoken(settings.jwtToken);
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
- initWithJWTtoken(jwtToken)
46
- {
47
- authJwtToken = jwtToken;
48
- this.restClient = new RESTClient(apiBaseUrl, jwtToken, true);
49
- }
50
-
51
- async authenticateWithJwt(authPath)
27
+ constructor(settings)
52
28
  {
53
- let refreshClient = new RESTClient(apiBaseUrl, "");
54
- await refreshClient.checkRefreshToken(authJwtToken, () => {
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 jwt_decode from "jwt-decode";
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
- token = "";
16
- baseurl = "";
17
-
18
- constructor(url, token, isJWT = false) {
19
- this.lastError = "";
20
- this.baseurl = url;
21
- this.token = token;
22
- this.isJWT = isJWT;
23
-
24
- if (this.token && !isJWT) {
25
- axios.defaults.headers.common["X-Gdl-AuthToken"] = this.token;
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 checkAuthorizationHeader(config) {
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 (!this.isJwtTokenExpired(jwt)) {
44
- // JWT token is not expired
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(this.baseurl + uri, this.getUrlOptions(noJWT));
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(this.baseurl + uri, { responseType: "blob" });
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(this.baseurl + uri, this.getUrlOptions(noJWT))
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(this.baseurl + uri, formData, this.getUrlOptions(noJWT));
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(this.baseurl + uri, formData, this.getUrlOptions(noJWT));
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(this.baseurl + uri, this.getUrlOptions(noJWT));
102
+ const response = await axios.delete(uri, this.getUrlOptions(noJWT));
180
103
  this.lastError = "";
181
104
  return response;
182
105
  } catch (error) {
@@ -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
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gandalan/weblibs",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "WebLibs for Gandalan JS/TS/Svelte projects",
5
5
  "keywords": [
6
6
  "gandalan"