@gandalan/weblibs 1.0.10 → 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,123 +1,44 @@
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
- axios.defaults.baseURL = url;
25
-
26
- if (this.token && !isJWT) {
27
- 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;
28
22
  }
29
-
30
- if (this.token && isJWT) {
31
- this.updateJwtToken(token);
32
- }
33
-
34
- axios.interceptors.request.use(async (config) => {
35
- await this.checkAuthorizationHeader(config);
36
- return config;
37
- });
38
23
  }
39
24
 
40
- async checkAuthorizationHeader(config) {
25
+ async checkTokenBeforeRequest(config) {
41
26
  let authHeader = config.headers["Authorization"];
42
- if (authHeader && authHeader.toString().startsWith("Bearer ")) {
27
+ if (authHeader && authHeader.toString().startsWith("Bearer ")) // only check requests containing a Bearer token
28
+ {
43
29
  let parts = authHeader.toString().split(" ");
44
30
  let jwt = parts[1];
45
- if (!this.isJwtTokenExpired(jwt)) {
46
- // JWT token is not expired
47
- return;
48
- }
49
-
50
- // expired token - refresh
51
- await this.checkRefreshToken(jwt);
52
- }
53
- }
54
-
55
- async checkRefreshToken(jwt, authCallback) {
56
- if (!jwt && authJwtRefreshToken) {
57
- this.onError = (error, message) => {
58
- // LoginJwt/Refresh failed, which means "refresh token" is expired/invalid...
59
- if (message.indexOf("401") != -1 || message.indexOf("403") != -1) {
60
- authJwtRefreshToken = undefined;
61
- localStorage.removeItem("IDAS_AuthJwtRefreshToken");
62
- // ... so repeat authenticate
63
- authCallback && authCallback();
64
- }
65
- };
66
-
67
- // fetch fresh JWT
68
- await this.refreshToken();
69
- return;
31
+ if (this.settings.jwtToken === jwt && jwtTokenInvalid(this.settings)) // ignore custom/different JWT tokens
32
+ await jwtTokenRenew(this.settings);
70
33
  }
71
- this.token = jwt;
72
- this.isJWT = true;
73
- }
74
-
75
- isJwtTokenExpired(jwt) {
76
- if (!jwt) {
77
- return true;
78
- }
79
-
80
- let decoded = jwt_decode(jwt);
81
- const utcNow = Date.parse(new Date().toUTCString()) / 1000;
82
-
83
- if (decoded && decoded.exp >= utcNow) {
84
- return false;
85
- }
86
-
87
- return true;
88
- }
89
-
90
- updateJwtToken(jwt) {
91
- let decoded = jwt_decode(jwt);
92
- let refreshToken = decoded["refreshToken"] || "";
93
- localStorage.setItem("IDAS_AuthJwtRefreshToken", refreshToken);
94
- authJwtRefreshToken = refreshToken;
95
- this.token = jwt;
96
- this.isJWT = true;
97
- }
98
-
99
- async refreshToken() {
100
- try {
101
- await this.put("/LoginJwt/Refresh", { token: localStorage.getItem("IDAS_AuthJwtRefreshToken") })
102
- .then(resp => {
103
- this.updateJwtToken(resp.data);
104
- });
105
- } catch (error) {
106
- this.handleError(error);
107
- }
108
- }
109
-
110
- updateToken(token) {
111
- this.token = token;
112
34
  }
113
35
 
114
36
  getUrlOptions(noJWT = false) {
115
37
  let options = { withCredentials: false }
116
- if (this.isJWT && !noJWT) {
38
+ /*if (this.isJWT && !noJWT) {
117
39
  options.headers = { Authorization: `Bearer ${this.token}` }
118
- }
119
-
120
- return options
40
+ }*/
41
+ return options;
121
42
  }
122
43
 
123
44
  async get(uri, noJWT = false) {
@@ -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.10",
3
+ "version": "1.0.11",
4
4
  "description": "WebLibs for Gandalan JS/TS/Svelte projects",
5
5
  "keywords": [
6
6
  "gandalan"