@luizleon/sf.prefeiturasp.vuecomponents 0.0.66 → 4.0.1
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/dist/sf.prefeiturasp.vuecomponents.cjs +423 -0
- package/dist/sf.prefeiturasp.vuecomponents.cjs.map +1 -0
- package/dist/sf.prefeiturasp.vuecomponents.js +8953 -0
- package/dist/sf.prefeiturasp.vuecomponents.js.map +1 -0
- package/dist/sf.prefeiturasp.vuecomponents.umd.cjs +423 -0
- package/dist/sf.prefeiturasp.vuecomponents.umd.cjs.map +1 -0
- package/dist/{axios → src/axios}/axiosClient.d.ts +7 -0
- package/dist/{components/button/Button.d.ts → src/components/button/Button.vue.d.ts} +16 -16
- package/dist/{components/content/Content.d.ts → src/components/content/Content.vue.d.ts} +7 -7
- package/dist/{components/drawer/Drawer.d.ts → src/components/drawer/Drawer.vue.d.ts} +15 -15
- package/dist/{components/icon/Icon.d.ts → src/components/icon/Icon.vue.d.ts} +23 -24
- package/dist/{components/internal/HeaderAvatar.d.ts → src/components/internal/HeaderAvatar.vue.d.ts} +2 -2
- package/dist/src/components/internal/LoadingCircle.vue.d.ts +2 -0
- package/dist/src/components/internal/MenuIcon.vue.d.ts +2 -0
- package/dist/src/components/internal/ScrollToTop.vue.d.ts +2 -0
- package/dist/src/components/internal/ThemeToggle.d.ts +10 -0
- package/dist/src/components/internal/ThemeToggle.vue.d.ts +2 -0
- package/dist/{components/layout/Layout.d.ts → src/components/layout/Layout.vue.d.ts} +9 -2
- package/dist/{components/message/Message.d.ts → src/components/message/Message.vue.d.ts} +14 -14
- package/dist/src/components/navmenu/NavMenu.vue.d.ts +15 -0
- package/dist/{components/tabnavigation/TabNavigation.d.ts → src/components/tabnavigation/TabNavigation.vue.d.ts} +9 -9
- package/dist/{components/tooltip/Tooltip.d.ts → src/components/tooltip/Tooltip.vue.d.ts} +7 -7
- package/dist/src/index.d.ts +17 -0
- package/dist/{types → src/types}/index.d.ts +11 -0
- package/dist/style.css +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +10 -9
- package/src/axios/axiosClient.ts +111 -3
- package/src/components/button/Button.vue +1 -1
- package/src/components/icon/Icon.vue +12 -16
- package/src/components/internal/getMaxZindex.ts +3 -2
- package/src/components/layout/Layout.vue +8 -1
- package/src/components/navmenu/NavMenu.vue +109 -0
- package/src/index.ts +2 -4
- package/src/keycloak.js +1485 -1890
- package/src/services/authService.ts +13 -4
- package/src/style/componentes.scss +5 -1
- package/src/style/src/_functions.scss +17 -2
- package/src/style/src/_mixins.scss +51 -29
- package/src/style/src/_variables.scss +11 -0
- package/src/style/src/components/_button.scss +8 -11
- package/src/style/src/components/_icon.scss +49 -47
- package/src/style/src/components/_tooltip.scss +6 -7
- package/src/types/index.ts +24 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +5 -3
- package/vite.config.js +2 -4
- package/dist/components/internal/LoadingCircle.d.ts +0 -2
- package/dist/components/internal/MenuIcon.d.ts +0 -2
- package/dist/components/internal/ScrollToTop.d.ts +0 -2
- package/dist/components/internal/ThemeToggle.d.ts +0 -2
- package/dist/components/navmenulink/NavMenuLink.d.ts +0 -18
- package/dist/components/panelmenu/PanelMenu.d.ts +0 -16
- package/dist/index.d.ts +0 -18
- package/dist/keycloak.d.ts +0 -671
- package/dist/sf.prefeiturasp.vuecomponents.es.js +0 -8685
- package/dist/sf.prefeiturasp.vuecomponents.es.js.map +0 -1
- package/dist/sf.prefeiturasp.vuecomponents.umd.js +0 -153
- package/dist/sf.prefeiturasp.vuecomponents.umd.js.map +0 -1
- package/src/components/button/Button.d.ts +0 -26
- package/src/components/content/Content.d.ts +0 -28
- package/src/components/drawer/Drawer.d.ts +0 -50
- package/src/components/icon/Icon.d.ts +0 -23
- package/src/components/layout/Layout.d.ts +0 -44
- package/src/components/message/Message.d.ts +0 -28
- package/src/components/navmenulink/NavMenuLink.d.ts +0 -29
- package/src/components/navmenulink/NavMenuLink.vue +0 -49
- package/src/components/panelmenu/PanelMenu.d.ts +0 -26
- package/src/components/panelmenu/PanelMenu.vue +0 -101
- package/src/components/tabnavigation/TabNavigation.d.ts +0 -34
- package/src/components/tooltip/Tooltip.d.ts +0 -23
- package/src/ts-helpers.d.ts +0 -57
- /package/dist/{common → src/common}/appResult.d.ts +0 -0
- /package/dist/{components → src/components}/internal/cssClassBuilder.d.ts +0 -0
- /package/dist/{components → src/components}/internal/getMaxZindex.d.ts +0 -0
- /package/dist/{services → src/services}/authService.d.ts +0 -0
- /package/dist/{services → src/services}/dialogService.d.ts +0 -0
- /package/dist/{services → src/services}/navMenuService.d.ts +0 -0
package/src/keycloak.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/** 04/09/2024
|
|
2
|
-
* https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-js/src/keycloak.js
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
1
|
/*
|
|
6
2
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
7
3
|
* and other contributors as indicated by the @author tags.
|
|
@@ -19,2118 +15,1717 @@
|
|
|
19
15
|
* limitations under the License.
|
|
20
16
|
*/
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
* 24/11/2023
|
|
21
|
+
*
|
|
22
|
+
* https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-js/src/keycloak.js
|
|
23
|
+
*
|
|
24
|
+
* Adaptado para expor setToken.
|
|
25
|
+
*
|
|
26
|
+
* Adpatado para usar URL absoluta em configUrl (linha 829). *
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import base64 from 'base64-js';
|
|
30
|
+
import sha256 from 'js-sha256';
|
|
31
|
+
import { jwtDecode } from 'jwt-decode';
|
|
24
32
|
|
|
25
|
-
if (typeof Promise ===
|
|
26
|
-
|
|
27
|
-
"Keycloak requires an environment that supports Promises. Make sure that you include the appropriate polyfill."
|
|
28
|
-
);
|
|
33
|
+
if (typeof Promise === 'undefined') {
|
|
34
|
+
throw Error('Keycloak requires an environment that supports Promises. Make sure that you include the appropriate polyfill.');
|
|
29
35
|
}
|
|
30
36
|
|
|
31
|
-
function Keycloak(config) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"The 'Keycloak' constructor must be invoked with 'new'."
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
var kc = this;
|
|
39
|
-
var adapter;
|
|
40
|
-
var refreshQueue = [];
|
|
41
|
-
var callbackStorage;
|
|
42
|
-
|
|
43
|
-
var loginIframe = {
|
|
44
|
-
enable: true,
|
|
45
|
-
callbackList: [],
|
|
46
|
-
interval: 5,
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
kc.didInitialize = false;
|
|
50
|
-
|
|
51
|
-
var scripts = document.getElementsByTagName("script");
|
|
52
|
-
for (var i = 0; i < scripts.length; i++) {
|
|
53
|
-
if (
|
|
54
|
-
(scripts[i].src.indexOf("keycloak.js") !== -1 ||
|
|
55
|
-
scripts[i].src.indexOf("keycloak.min.js") !== -1) &&
|
|
56
|
-
scripts[i].src.indexOf("version=") !== -1
|
|
57
|
-
) {
|
|
58
|
-
kc.iframeVersion = scripts[i].src
|
|
59
|
-
.substring(scripts[i].src.indexOf("version=") + 8)
|
|
60
|
-
.split("&")[0];
|
|
37
|
+
function Keycloak (config) {
|
|
38
|
+
if (!(this instanceof Keycloak)) {
|
|
39
|
+
throw new Error("The 'Keycloak' constructor must be invoked with 'new'.")
|
|
61
40
|
}
|
|
62
|
-
}
|
|
63
41
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
42
|
+
var kc = this;
|
|
43
|
+
var adapter;
|
|
44
|
+
var refreshQueue = [];
|
|
45
|
+
var callbackStorage;
|
|
67
46
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
47
|
+
var loginIframe = {
|
|
48
|
+
enable: true,
|
|
49
|
+
callbackList: [],
|
|
50
|
+
interval: 5
|
|
51
|
+
};
|
|
74
52
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
var adapters = ["default", "cordova", "cordova-native"];
|
|
81
|
-
|
|
82
|
-
if (initOptions && adapters.indexOf(initOptions.adapter) > -1) {
|
|
83
|
-
adapter = loadAdapter(initOptions.adapter);
|
|
84
|
-
} else if (
|
|
85
|
-
initOptions &&
|
|
86
|
-
typeof initOptions.adapter === "object"
|
|
87
|
-
) {
|
|
88
|
-
adapter = initOptions.adapter;
|
|
89
|
-
} else {
|
|
90
|
-
if (window.Cordova || window.cordova) {
|
|
91
|
-
adapter = loadAdapter("cordova");
|
|
92
|
-
} else {
|
|
93
|
-
adapter = loadAdapter();
|
|
94
|
-
}
|
|
53
|
+
var scripts = document.getElementsByTagName('script');
|
|
54
|
+
for (var i = 0; i < scripts.length; i++) {
|
|
55
|
+
if ((scripts[i].src.indexOf('keycloak.js') !== -1 || scripts[i].src.indexOf('keycloak.min.js') !== -1) && scripts[i].src.indexOf('version=') !== -1) {
|
|
56
|
+
kc.iframeVersion = scripts[i].src.substring(scripts[i].src.indexOf('version=') + 8).split('&')[0];
|
|
57
|
+
}
|
|
95
58
|
}
|
|
96
59
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
-
initOptions.responseMode === "fragment"
|
|
118
|
-
) {
|
|
119
|
-
kc.responseMode = initOptions.responseMode;
|
|
60
|
+
var useNonce = true;
|
|
61
|
+
var logInfo = createLogger(console.info);
|
|
62
|
+
var logWarn = createLogger(console.warn);
|
|
63
|
+
|
|
64
|
+
kc.init = function (initOptions) {
|
|
65
|
+
if (kc.didInitialize) {
|
|
66
|
+
throw new Error("A 'Keycloak' instance can only be initialized once.");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
kc.didInitialize = true;
|
|
70
|
+
|
|
71
|
+
kc.authenticated = false;
|
|
72
|
+
|
|
73
|
+
callbackStorage = createCallbackStorage();
|
|
74
|
+
var adapters = ['default', 'cordova', 'cordova-native'];
|
|
75
|
+
|
|
76
|
+
if (initOptions && adapters.indexOf(initOptions.adapter) > -1) {
|
|
77
|
+
adapter = loadAdapter(initOptions.adapter);
|
|
78
|
+
} else if (initOptions && typeof initOptions.adapter === "object") {
|
|
79
|
+
adapter = initOptions.adapter;
|
|
120
80
|
} else {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
case "standard":
|
|
128
|
-
kc.responseType = "code";
|
|
129
|
-
break;
|
|
130
|
-
case "implicit":
|
|
131
|
-
kc.responseType = "id_token token";
|
|
132
|
-
break;
|
|
133
|
-
case "hybrid":
|
|
134
|
-
kc.responseType = "code id_token token";
|
|
135
|
-
break;
|
|
136
|
-
default:
|
|
137
|
-
throw "Invalid value for flow";
|
|
138
|
-
}
|
|
139
|
-
kc.flow = initOptions.flow;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (initOptions.timeSkew != null) {
|
|
143
|
-
kc.timeSkew = initOptions.timeSkew;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (initOptions.redirectUri) {
|
|
147
|
-
kc.redirectUri = initOptions.redirectUri;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (initOptions.silentCheckSsoRedirectUri) {
|
|
151
|
-
kc.silentCheckSsoRedirectUri =
|
|
152
|
-
initOptions.silentCheckSsoRedirectUri;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (typeof initOptions.silentCheckSsoFallback === "boolean") {
|
|
156
|
-
kc.silentCheckSsoFallback =
|
|
157
|
-
initOptions.silentCheckSsoFallback;
|
|
158
|
-
} else {
|
|
159
|
-
kc.silentCheckSsoFallback = true;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (typeof initOptions.pkceMethod !== "undefined") {
|
|
163
|
-
if (
|
|
164
|
-
initOptions.pkceMethod !== "S256" &&
|
|
165
|
-
initOptions.pkceMethod !== false
|
|
166
|
-
) {
|
|
167
|
-
throw new TypeError(
|
|
168
|
-
`Invalid value for pkceMethod', expected 'S256' or false but got ${initOptions.pkceMethod}.`
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
kc.pkceMethod = initOptions.pkceMethod;
|
|
173
|
-
} else {
|
|
174
|
-
kc.pkceMethod = "S256";
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (typeof initOptions.enableLogging === "boolean") {
|
|
178
|
-
kc.enableLogging = initOptions.enableLogging;
|
|
179
|
-
} else {
|
|
180
|
-
kc.enableLogging = false;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (initOptions.logoutMethod === "POST") {
|
|
184
|
-
kc.logoutMethod = "POST";
|
|
185
|
-
} else {
|
|
186
|
-
kc.logoutMethod = "GET";
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (typeof initOptions.scope === "string") {
|
|
190
|
-
kc.scope = initOptions.scope;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if (typeof initOptions.acrValues === "string") {
|
|
194
|
-
kc.acrValues = initOptions.acrValues;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (
|
|
198
|
-
typeof initOptions.messageReceiveTimeout === "number" &&
|
|
199
|
-
initOptions.messageReceiveTimeout > 0
|
|
200
|
-
) {
|
|
201
|
-
kc.messageReceiveTimeout = initOptions.messageReceiveTimeout;
|
|
202
|
-
} else {
|
|
203
|
-
kc.messageReceiveTimeout = 10000;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
81
|
+
if (window.Cordova || window.cordova) {
|
|
82
|
+
adapter = loadAdapter('cordova');
|
|
83
|
+
} else {
|
|
84
|
+
adapter = loadAdapter();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
206
87
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
kc.responseType = "code";
|
|
212
|
-
kc.flow = "standard";
|
|
213
|
-
}
|
|
88
|
+
if (initOptions) {
|
|
89
|
+
if (typeof initOptions.useNonce !== 'undefined') {
|
|
90
|
+
useNonce = initOptions.useNonce;
|
|
91
|
+
}
|
|
214
92
|
|
|
215
|
-
|
|
93
|
+
if (typeof initOptions.checkLoginIframe !== 'undefined') {
|
|
94
|
+
loginIframe.enable = initOptions.checkLoginIframe;
|
|
95
|
+
}
|
|
216
96
|
|
|
217
|
-
|
|
97
|
+
if (initOptions.checkLoginIframeInterval) {
|
|
98
|
+
loginIframe.interval = initOptions.checkLoginIframeInterval;
|
|
99
|
+
}
|
|
218
100
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
promise.setSuccess(kc.authenticated);
|
|
223
|
-
})
|
|
224
|
-
.catch(function (error) {
|
|
225
|
-
promise.setError(error);
|
|
226
|
-
});
|
|
101
|
+
if (initOptions.onLoad === 'login-required') {
|
|
102
|
+
kc.loginRequired = true;
|
|
103
|
+
}
|
|
227
104
|
|
|
228
|
-
|
|
105
|
+
if (initOptions.responseMode) {
|
|
106
|
+
if (initOptions.responseMode === 'query' || initOptions.responseMode === 'fragment') {
|
|
107
|
+
kc.responseMode = initOptions.responseMode;
|
|
108
|
+
} else {
|
|
109
|
+
throw 'Invalid value for responseMode';
|
|
110
|
+
}
|
|
111
|
+
}
|
|
229
112
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
113
|
+
if (initOptions.flow) {
|
|
114
|
+
switch (initOptions.flow) {
|
|
115
|
+
case 'standard':
|
|
116
|
+
kc.responseType = 'code';
|
|
117
|
+
break;
|
|
118
|
+
case 'implicit':
|
|
119
|
+
kc.responseType = 'id_token token';
|
|
120
|
+
break;
|
|
121
|
+
case 'hybrid':
|
|
122
|
+
kc.responseType = 'code id_token token';
|
|
123
|
+
break;
|
|
124
|
+
default:
|
|
125
|
+
throw 'Invalid value for flow';
|
|
126
|
+
}
|
|
127
|
+
kc.flow = initOptions.flow;
|
|
128
|
+
}
|
|
235
129
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
kc.login(options)
|
|
240
|
-
.then(function () {
|
|
241
|
-
initPromise.setSuccess();
|
|
242
|
-
})
|
|
243
|
-
.catch(function (error) {
|
|
244
|
-
initPromise.setError(error);
|
|
245
|
-
});
|
|
246
|
-
};
|
|
130
|
+
if (initOptions.timeSkew != null) {
|
|
131
|
+
kc.timeSkew = initOptions.timeSkew;
|
|
132
|
+
}
|
|
247
133
|
|
|
248
|
-
|
|
249
|
-
|
|
134
|
+
if(initOptions.redirectUri) {
|
|
135
|
+
kc.redirectUri = initOptions.redirectUri;
|
|
136
|
+
}
|
|
250
137
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
});
|
|
138
|
+
if (initOptions.silentCheckSsoRedirectUri) {
|
|
139
|
+
kc.silentCheckSsoRedirectUri = initOptions.silentCheckSsoRedirectUri;
|
|
140
|
+
}
|
|
255
141
|
|
|
256
|
-
|
|
142
|
+
if (typeof initOptions.silentCheckSsoFallback === 'boolean') {
|
|
143
|
+
kc.silentCheckSsoFallback = initOptions.silentCheckSsoFallback;
|
|
144
|
+
} else {
|
|
145
|
+
kc.silentCheckSsoFallback = true;
|
|
146
|
+
}
|
|
257
147
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
148
|
+
if (initOptions.pkceMethod) {
|
|
149
|
+
if (initOptions.pkceMethod !== "S256") {
|
|
150
|
+
throw 'Invalid value for pkceMethod';
|
|
151
|
+
}
|
|
152
|
+
kc.pkceMethod = initOptions.pkceMethod;
|
|
153
|
+
}
|
|
262
154
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
155
|
+
if (typeof initOptions.enableLogging === 'boolean') {
|
|
156
|
+
kc.enableLogging = initOptions.enableLogging;
|
|
157
|
+
} else {
|
|
158
|
+
kc.enableLogging = false;
|
|
159
|
+
}
|
|
266
160
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
ifrm.contentWindow !== event.source
|
|
271
|
-
) {
|
|
272
|
-
return;
|
|
273
|
-
}
|
|
161
|
+
if (typeof initOptions.scope === 'string') {
|
|
162
|
+
kc.scope = initOptions.scope;
|
|
163
|
+
}
|
|
274
164
|
|
|
275
|
-
|
|
276
|
-
|
|
165
|
+
if (typeof initOptions.acrValues === 'string') {
|
|
166
|
+
kc.acrValues = initOptions.acrValues;
|
|
167
|
+
}
|
|
277
168
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
169
|
+
if (typeof initOptions.messageReceiveTimeout === 'number' && initOptions.messageReceiveTimeout > 0) {
|
|
170
|
+
kc.messageReceiveTimeout = initOptions.messageReceiveTimeout;
|
|
171
|
+
} else {
|
|
172
|
+
kc.messageReceiveTimeout = 10000;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (!kc.responseMode) {
|
|
177
|
+
kc.responseMode = 'fragment';
|
|
178
|
+
}
|
|
179
|
+
if (!kc.responseType) {
|
|
180
|
+
kc.responseType = 'code';
|
|
181
|
+
kc.flow = 'standard';
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
var promise = createPromise();
|
|
185
|
+
|
|
186
|
+
var initPromise = createPromise();
|
|
187
|
+
initPromise.promise.then(function() {
|
|
188
|
+
kc.onReady && kc.onReady(kc.authenticated);
|
|
189
|
+
promise.setSuccess(kc.authenticated);
|
|
190
|
+
}).catch(function(error) {
|
|
191
|
+
promise.setError(error);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
var configPromise = loadConfig(config);
|
|
195
|
+
|
|
196
|
+
function onLoad() {
|
|
197
|
+
var doLogin = function(prompt) {
|
|
198
|
+
if (!prompt) {
|
|
199
|
+
options.prompt = 'none';
|
|
200
|
+
}
|
|
281
201
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
switch (initOptions.onLoad) {
|
|
287
|
-
case "check-sso":
|
|
288
|
-
if (loginIframe.enable) {
|
|
289
|
-
setupCheckLoginIframe().then(function () {
|
|
290
|
-
checkLoginIframe()
|
|
291
|
-
.then(function (unchanged) {
|
|
292
|
-
if (!unchanged) {
|
|
293
|
-
kc.silentCheckSsoRedirectUri
|
|
294
|
-
? checkSsoSilently()
|
|
295
|
-
: doLogin(false);
|
|
296
|
-
} else {
|
|
202
|
+
if (initOptions && initOptions.locale) {
|
|
203
|
+
options.locale = initOptions.locale;
|
|
204
|
+
}
|
|
205
|
+
kc.login(options).then(function () {
|
|
297
206
|
initPromise.setSuccess();
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
.catch(function (error) {
|
|
301
|
-
initPromise.setError(error);
|
|
207
|
+
}).catch(function (error) {
|
|
208
|
+
initPromise.setError(error);
|
|
302
209
|
});
|
|
303
|
-
}
|
|
304
|
-
} else {
|
|
305
|
-
kc.silentCheckSsoRedirectUri
|
|
306
|
-
? checkSsoSilently()
|
|
307
|
-
: doLogin(false);
|
|
308
|
-
}
|
|
309
|
-
break;
|
|
310
|
-
case "login-required":
|
|
311
|
-
doLogin(true);
|
|
312
|
-
break;
|
|
313
|
-
default:
|
|
314
|
-
throw "Invalid value for onLoad";
|
|
315
|
-
}
|
|
316
|
-
}
|
|
210
|
+
}
|
|
317
211
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
212
|
+
var checkSsoSilently = function() {
|
|
213
|
+
var ifrm = document.createElement("iframe");
|
|
214
|
+
var src = kc.createLoginUrl({prompt: 'none', redirectUri: kc.silentCheckSsoRedirectUri});
|
|
215
|
+
ifrm.setAttribute("src", src);
|
|
216
|
+
ifrm.setAttribute("sandbox", "allow-scripts allow-same-origin");
|
|
217
|
+
ifrm.setAttribute("title", "keycloak-silent-check-sso");
|
|
218
|
+
ifrm.style.display = "none";
|
|
219
|
+
document.body.appendChild(ifrm);
|
|
220
|
+
|
|
221
|
+
var messageCallback = function(event) {
|
|
222
|
+
if (event.origin !== window.location.origin || ifrm.contentWindow !== event.source) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
var oauth = parseCallback(event.data);
|
|
227
|
+
processCallback(oauth, initPromise);
|
|
228
|
+
|
|
229
|
+
document.body.removeChild(ifrm);
|
|
230
|
+
window.removeEventListener("message", messageCallback);
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
window.addEventListener("message", messageCallback);
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
var options = {};
|
|
237
|
+
switch (initOptions.onLoad) {
|
|
238
|
+
case 'check-sso':
|
|
239
|
+
if (loginIframe.enable) {
|
|
240
|
+
setupCheckLoginIframe().then(function() {
|
|
241
|
+
checkLoginIframe().then(function (unchanged) {
|
|
242
|
+
if (!unchanged) {
|
|
243
|
+
kc.silentCheckSsoRedirectUri ? checkSsoSilently() : doLogin(false);
|
|
244
|
+
} else {
|
|
245
|
+
initPromise.setSuccess();
|
|
246
|
+
}
|
|
247
|
+
}).catch(function (error) {
|
|
248
|
+
initPromise.setError(error);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
} else {
|
|
252
|
+
kc.silentCheckSsoRedirectUri ? checkSsoSilently() : doLogin(false);
|
|
253
|
+
}
|
|
254
|
+
break;
|
|
255
|
+
case 'login-required':
|
|
256
|
+
doLogin(true);
|
|
257
|
+
break;
|
|
258
|
+
default:
|
|
259
|
+
throw 'Invalid value for onLoad';
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function processInit() {
|
|
264
|
+
var callback = parseCallback(window.location.href);
|
|
265
|
+
|
|
266
|
+
if (callback) {
|
|
267
|
+
window.history.replaceState(window.history.state, null, callback.newUrl);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (callback && callback.valid) {
|
|
271
|
+
return setupCheckLoginIframe().then(function() {
|
|
272
|
+
processCallback(callback, initPromise);
|
|
273
|
+
}).catch(function (error) {
|
|
274
|
+
initPromise.setError(error);
|
|
359
275
|
});
|
|
360
|
-
})
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
276
|
+
} else if (initOptions) {
|
|
277
|
+
if (initOptions.token && initOptions.refreshToken) {
|
|
278
|
+
setToken(initOptions.token, initOptions.refreshToken, initOptions.idToken);
|
|
279
|
+
|
|
280
|
+
if (loginIframe.enable) {
|
|
281
|
+
setupCheckLoginIframe().then(function() {
|
|
282
|
+
checkLoginIframe().then(function (unchanged) {
|
|
283
|
+
if (unchanged) {
|
|
284
|
+
kc.onAuthSuccess && kc.onAuthSuccess();
|
|
285
|
+
initPromise.setSuccess();
|
|
286
|
+
scheduleCheckIframe();
|
|
287
|
+
} else {
|
|
288
|
+
initPromise.setSuccess();
|
|
289
|
+
}
|
|
290
|
+
}).catch(function (error) {
|
|
291
|
+
initPromise.setError(error);
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
} else {
|
|
295
|
+
kc.updateToken(-1).then(function() {
|
|
296
|
+
kc.onAuthSuccess && kc.onAuthSuccess();
|
|
297
|
+
initPromise.setSuccess();
|
|
298
|
+
}).catch(function(error) {
|
|
299
|
+
kc.onAuthError && kc.onAuthError();
|
|
300
|
+
if (initOptions.onLoad) {
|
|
301
|
+
onLoad();
|
|
302
|
+
} else {
|
|
303
|
+
initPromise.setError(error);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
} else if (initOptions.onLoad) {
|
|
308
|
+
onLoad();
|
|
371
309
|
} else {
|
|
372
|
-
|
|
310
|
+
initPromise.setSuccess();
|
|
373
311
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
onLoad();
|
|
378
|
-
} else {
|
|
379
|
-
initPromise.setSuccess();
|
|
312
|
+
} else {
|
|
313
|
+
initPromise.setSuccess();
|
|
314
|
+
}
|
|
380
315
|
}
|
|
381
|
-
} else {
|
|
382
|
-
initPromise.setSuccess();
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
316
|
|
|
386
|
-
|
|
387
|
-
|
|
317
|
+
function domReady() {
|
|
318
|
+
var promise = createPromise();
|
|
319
|
+
|
|
320
|
+
var checkReadyState = function () {
|
|
321
|
+
if (document.readyState === 'interactive' || document.readyState === 'complete') {
|
|
322
|
+
document.removeEventListener('readystatechange', checkReadyState);
|
|
323
|
+
promise.setSuccess();
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
document.addEventListener('readystatechange', checkReadyState);
|
|
388
327
|
|
|
389
|
-
|
|
390
|
-
if (
|
|
391
|
-
document.readyState === "interactive" ||
|
|
392
|
-
document.readyState === "complete"
|
|
393
|
-
) {
|
|
394
|
-
document.removeEventListener(
|
|
395
|
-
"readystatechange",
|
|
396
|
-
checkReadyState
|
|
397
|
-
);
|
|
328
|
+
checkReadyState(); // just in case the event was already fired and we missed it (in case the init is done later than at the load time, i.e. it's done from code)
|
|
398
329
|
|
|
399
|
-
|
|
330
|
+
return promise.promise;
|
|
400
331
|
}
|
|
401
|
-
};
|
|
402
332
|
|
|
403
|
-
|
|
333
|
+
configPromise.then(function () {
|
|
334
|
+
domReady()
|
|
335
|
+
.then(check3pCookiesSupported)
|
|
336
|
+
.then(processInit)
|
|
337
|
+
.catch(function (error) {
|
|
338
|
+
promise.setError(error);
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
configPromise.catch(function (error) {
|
|
342
|
+
promise.setError(error);
|
|
343
|
+
});
|
|
404
344
|
|
|
405
|
-
|
|
345
|
+
return promise.promise;
|
|
346
|
+
}
|
|
406
347
|
|
|
407
|
-
|
|
348
|
+
kc.login = function (options) {
|
|
349
|
+
return adapter.login(options);
|
|
408
350
|
}
|
|
409
351
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
.
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
return adapter.login(options);
|
|
427
|
-
};
|
|
428
|
-
|
|
429
|
-
function generateRandomData(len) {
|
|
430
|
-
// use web crypto APIs if possible
|
|
431
|
-
var array = null;
|
|
432
|
-
var crypto = window.crypto || window.msCrypto;
|
|
433
|
-
if (crypto && crypto.getRandomValues && window.Uint8Array) {
|
|
434
|
-
array = new Uint8Array(len);
|
|
435
|
-
crypto.getRandomValues(array);
|
|
436
|
-
return array;
|
|
352
|
+
function generateRandomData(len) {
|
|
353
|
+
// use web crypto APIs if possible
|
|
354
|
+
var array = null;
|
|
355
|
+
var crypto = window.crypto || window.msCrypto;
|
|
356
|
+
if (crypto && crypto.getRandomValues && window.Uint8Array) {
|
|
357
|
+
array = new Uint8Array(len);
|
|
358
|
+
crypto.getRandomValues(array);
|
|
359
|
+
return array;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// fallback to Math random
|
|
363
|
+
array = new Array(len);
|
|
364
|
+
for (var j = 0; j < array.length; j++) {
|
|
365
|
+
array[j] = Math.floor(256 * Math.random());
|
|
366
|
+
}
|
|
367
|
+
return array;
|
|
437
368
|
}
|
|
438
369
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
for (var j = 0; j < array.length; j++) {
|
|
442
|
-
array[j] = Math.floor(256 * Math.random());
|
|
370
|
+
function generateCodeVerifier(len) {
|
|
371
|
+
return generateRandomString(len, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789');
|
|
443
372
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
373
|
+
|
|
374
|
+
function generateRandomString(len, alphabet){
|
|
375
|
+
var randomData = generateRandomData(len);
|
|
376
|
+
var chars = new Array(len);
|
|
377
|
+
for (var i = 0; i < len; i++) {
|
|
378
|
+
chars[i] = alphabet.charCodeAt(randomData[i] % alphabet.length);
|
|
379
|
+
}
|
|
380
|
+
return String.fromCharCode.apply(null, chars);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function generatePkceChallenge(pkceMethod, codeVerifier) {
|
|
384
|
+
switch (pkceMethod) {
|
|
385
|
+
// The use of the "plain" method is considered insecure and therefore not supported.
|
|
386
|
+
case "S256":
|
|
387
|
+
// hash codeVerifier, then encode as url-safe base64 without padding
|
|
388
|
+
var hashBytes = new Uint8Array(sha256.arrayBuffer(codeVerifier));
|
|
389
|
+
var encodedHash = base64.fromByteArray(hashBytes)
|
|
390
|
+
.replace(/\+/g, '-')
|
|
391
|
+
.replace(/\//g, '_')
|
|
392
|
+
.replace(/\=/g, '');
|
|
393
|
+
return encodedHash;
|
|
394
|
+
default:
|
|
395
|
+
throw 'Invalid value for pkceMethod';
|
|
396
|
+
}
|
|
459
397
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
398
|
+
|
|
399
|
+
function buildClaimsParameter(requestedAcr){
|
|
400
|
+
var claims = {
|
|
401
|
+
id_token: {
|
|
402
|
+
acr: requestedAcr
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return JSON.stringify(claims);
|
|
468
406
|
}
|
|
469
407
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
.replace(/\+/g, "-")
|
|
474
|
-
.replace(/\//g, "_")
|
|
475
|
-
.replace(/\=/g, "");
|
|
476
|
-
|
|
477
|
-
return encodedHash;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
function buildClaimsParameter(requestedAcr) {
|
|
481
|
-
var claims = {
|
|
482
|
-
id_token: {
|
|
483
|
-
acr: requestedAcr,
|
|
484
|
-
},
|
|
485
|
-
};
|
|
486
|
-
return JSON.stringify(claims);
|
|
487
|
-
}
|
|
408
|
+
kc.createLoginUrl = function(options) {
|
|
409
|
+
var state = createUUID();
|
|
410
|
+
var nonce = createUUID();
|
|
488
411
|
|
|
489
|
-
|
|
490
|
-
var state = createUUID();
|
|
491
|
-
var nonce = createUUID();
|
|
412
|
+
var redirectUri = adapter.redirectUri(options);
|
|
492
413
|
|
|
493
|
-
|
|
414
|
+
var callbackState = {
|
|
415
|
+
state: state,
|
|
416
|
+
nonce: nonce,
|
|
417
|
+
redirectUri: encodeURIComponent(redirectUri)
|
|
418
|
+
};
|
|
494
419
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
redirectUri: encodeURIComponent(redirectUri),
|
|
499
|
-
loginOptions: options,
|
|
500
|
-
};
|
|
420
|
+
if (options && options.prompt) {
|
|
421
|
+
callbackState.prompt = options.prompt;
|
|
422
|
+
}
|
|
501
423
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
424
|
+
var baseUrl;
|
|
425
|
+
if (options && options.action == 'register') {
|
|
426
|
+
baseUrl = kc.endpoints.register();
|
|
427
|
+
} else {
|
|
428
|
+
baseUrl = kc.endpoints.authorize();
|
|
429
|
+
}
|
|
505
430
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
431
|
+
var scope = options && options.scope || kc.scope;
|
|
432
|
+
if (!scope) {
|
|
433
|
+
// if scope is not set, default to "openid"
|
|
434
|
+
scope = "openid";
|
|
435
|
+
} else if (scope.indexOf("openid") === -1) {
|
|
436
|
+
// if openid scope is missing, prefix the given scopes with it
|
|
437
|
+
scope = "openid " + scope;
|
|
438
|
+
}
|
|
512
439
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
440
|
+
var url = baseUrl
|
|
441
|
+
+ '?client_id=' + encodeURIComponent(kc.clientId)
|
|
442
|
+
+ '&redirect_uri=' + encodeURIComponent(redirectUri)
|
|
443
|
+
+ '&state=' + encodeURIComponent(state)
|
|
444
|
+
+ '&response_mode=' + encodeURIComponent(kc.responseMode)
|
|
445
|
+
+ '&response_type=' + encodeURIComponent(kc.responseType)
|
|
446
|
+
+ '&scope=' + encodeURIComponent(scope);
|
|
447
|
+
if (useNonce) {
|
|
448
|
+
url = url + '&nonce=' + encodeURIComponent(nonce);
|
|
449
|
+
}
|
|
521
450
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
encodeURIComponent(kc.clientId) +
|
|
526
|
-
"&redirect_uri=" +
|
|
527
|
-
encodeURIComponent(redirectUri) +
|
|
528
|
-
"&state=" +
|
|
529
|
-
encodeURIComponent(state) +
|
|
530
|
-
"&response_mode=" +
|
|
531
|
-
encodeURIComponent(kc.responseMode) +
|
|
532
|
-
"&response_type=" +
|
|
533
|
-
encodeURIComponent(kc.responseType) +
|
|
534
|
-
"&scope=" +
|
|
535
|
-
encodeURIComponent(scope);
|
|
536
|
-
if (useNonce) {
|
|
537
|
-
url = url + "&nonce=" + encodeURIComponent(nonce);
|
|
538
|
-
}
|
|
451
|
+
if (options && options.prompt) {
|
|
452
|
+
url += '&prompt=' + encodeURIComponent(options.prompt);
|
|
453
|
+
}
|
|
539
454
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
455
|
+
if (options && options.maxAge) {
|
|
456
|
+
url += '&max_age=' + encodeURIComponent(options.maxAge);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (options && options.loginHint) {
|
|
460
|
+
url += '&login_hint=' + encodeURIComponent(options.loginHint);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if (options && options.idpHint) {
|
|
464
|
+
url += '&kc_idp_hint=' + encodeURIComponent(options.idpHint);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (options && options.action && options.action != 'register') {
|
|
468
|
+
url += '&kc_action=' + encodeURIComponent(options.action);
|
|
469
|
+
}
|
|
543
470
|
|
|
544
|
-
|
|
545
|
-
|
|
471
|
+
if (options && options.locale) {
|
|
472
|
+
url += '&ui_locales=' + encodeURIComponent(options.locale);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if (options && options.acr) {
|
|
476
|
+
var claimsParameter = buildClaimsParameter(options.acr);
|
|
477
|
+
url += '&claims=' + encodeURIComponent(claimsParameter);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if ((options && options.acrValues) || kc.acrValues) {
|
|
481
|
+
url += '&acr_values=' + encodeURIComponent(options.acrValues || kc.acrValues);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (kc.pkceMethod) {
|
|
485
|
+
var codeVerifier = generateCodeVerifier(96);
|
|
486
|
+
callbackState.pkceCodeVerifier = codeVerifier;
|
|
487
|
+
var pkceChallenge = generatePkceChallenge(kc.pkceMethod, codeVerifier);
|
|
488
|
+
url += '&code_challenge=' + pkceChallenge;
|
|
489
|
+
url += '&code_challenge_method=' + kc.pkceMethod;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
callbackStorage.add(callbackState);
|
|
493
|
+
|
|
494
|
+
return url;
|
|
546
495
|
}
|
|
547
496
|
|
|
548
|
-
|
|
549
|
-
|
|
497
|
+
kc.logout = function(options) {
|
|
498
|
+
return adapter.logout(options);
|
|
550
499
|
}
|
|
551
500
|
|
|
552
|
-
|
|
553
|
-
|
|
501
|
+
kc.createLogoutUrl = function(options) {
|
|
502
|
+
var url = kc.endpoints.logout()
|
|
503
|
+
+ '?client_id=' + encodeURIComponent(kc.clientId)
|
|
504
|
+
+ '&post_logout_redirect_uri=' + encodeURIComponent(adapter.redirectUri(options, false));
|
|
505
|
+
|
|
506
|
+
if (kc.idToken) {
|
|
507
|
+
url += '&id_token_hint=' + encodeURIComponent(kc.idToken);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
return url;
|
|
554
511
|
}
|
|
555
512
|
|
|
556
|
-
|
|
557
|
-
|
|
513
|
+
kc.register = function (options) {
|
|
514
|
+
return adapter.register(options);
|
|
558
515
|
}
|
|
559
516
|
|
|
560
|
-
|
|
561
|
-
|
|
517
|
+
kc.createRegisterUrl = function(options) {
|
|
518
|
+
if (!options) {
|
|
519
|
+
options = {};
|
|
520
|
+
}
|
|
521
|
+
options.action = 'register';
|
|
522
|
+
return kc.createLoginUrl(options);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
kc.createAccountUrl = function(options) {
|
|
526
|
+
var realm = getRealmUrl();
|
|
527
|
+
var url = undefined;
|
|
528
|
+
if (typeof realm !== 'undefined') {
|
|
529
|
+
url = realm
|
|
530
|
+
+ '/account'
|
|
531
|
+
+ '?referrer=' + encodeURIComponent(kc.clientId)
|
|
532
|
+
+ '&referrer_uri=' + encodeURIComponent(adapter.redirectUri(options));
|
|
533
|
+
}
|
|
534
|
+
return url;
|
|
562
535
|
}
|
|
563
536
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
url += "&claims=" + encodeURIComponent(claimsParameter);
|
|
537
|
+
kc.accountManagement = function() {
|
|
538
|
+
return adapter.accountManagement();
|
|
567
539
|
}
|
|
568
540
|
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
encodeURIComponent(options.acrValues || kc.acrValues);
|
|
541
|
+
kc.hasRealmRole = function (role) {
|
|
542
|
+
var access = kc.realmAccess;
|
|
543
|
+
return !!access && access.roles.indexOf(role) >= 0;
|
|
573
544
|
}
|
|
574
545
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
kc.pkceMethod,
|
|
580
|
-
codeVerifier
|
|
581
|
-
);
|
|
546
|
+
kc.hasResourceRole = function(role, resource) {
|
|
547
|
+
if (!kc.resourceAccess) {
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
582
550
|
|
|
583
|
-
|
|
584
|
-
|
|
551
|
+
var access = kc.resourceAccess[resource || kc.clientId];
|
|
552
|
+
return !!access && access.roles.indexOf(role) >= 0;
|
|
585
553
|
}
|
|
586
554
|
|
|
587
|
-
|
|
555
|
+
kc.loadUserProfile = function() {
|
|
556
|
+
var url = getRealmUrl() + '/account';
|
|
557
|
+
var req = new XMLHttpRequest();
|
|
558
|
+
req.open('GET', url, true);
|
|
559
|
+
req.setRequestHeader('Accept', 'application/json');
|
|
560
|
+
req.setRequestHeader('Authorization', 'bearer ' + kc.token);
|
|
588
561
|
|
|
589
|
-
|
|
590
|
-
|
|
562
|
+
var promise = createPromise();
|
|
563
|
+
|
|
564
|
+
req.onreadystatechange = function () {
|
|
565
|
+
if (req.readyState == 4) {
|
|
566
|
+
if (req.status == 200) {
|
|
567
|
+
kc.profile = JSON.parse(req.responseText);
|
|
568
|
+
promise.setSuccess(kc.profile);
|
|
569
|
+
} else {
|
|
570
|
+
promise.setError();
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
591
574
|
|
|
592
|
-
|
|
593
|
-
return adapter.logout(options);
|
|
594
|
-
};
|
|
575
|
+
req.send();
|
|
595
576
|
|
|
596
|
-
|
|
597
|
-
const logoutMethod = options?.logoutMethod ?? kc.logoutMethod;
|
|
598
|
-
if (logoutMethod === "POST") {
|
|
599
|
-
return kc.endpoints.logout();
|
|
577
|
+
return promise.promise;
|
|
600
578
|
}
|
|
601
579
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
580
|
+
kc.loadUserInfo = function() {
|
|
581
|
+
var url = kc.endpoints.userinfo();
|
|
582
|
+
var req = new XMLHttpRequest();
|
|
583
|
+
req.open('GET', url, true);
|
|
584
|
+
req.setRequestHeader('Accept', 'application/json');
|
|
585
|
+
req.setRequestHeader('Authorization', 'bearer ' + kc.token);
|
|
608
586
|
|
|
609
|
-
|
|
610
|
-
url += "&id_token_hint=" + encodeURIComponent(kc.idToken);
|
|
611
|
-
}
|
|
587
|
+
var promise = createPromise();
|
|
612
588
|
|
|
613
|
-
|
|
614
|
-
|
|
589
|
+
req.onreadystatechange = function () {
|
|
590
|
+
if (req.readyState == 4) {
|
|
591
|
+
if (req.status == 200) {
|
|
592
|
+
kc.userInfo = JSON.parse(req.responseText);
|
|
593
|
+
promise.setSuccess(kc.userInfo);
|
|
594
|
+
} else {
|
|
595
|
+
promise.setError();
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
615
599
|
|
|
616
|
-
|
|
617
|
-
return adapter.register(options);
|
|
618
|
-
};
|
|
600
|
+
req.send();
|
|
619
601
|
|
|
620
|
-
|
|
621
|
-
if (!options) {
|
|
622
|
-
options = {};
|
|
602
|
+
return promise.promise;
|
|
623
603
|
}
|
|
624
|
-
options.action = "register";
|
|
625
|
-
return kc.createLoginUrl(options);
|
|
626
|
-
};
|
|
627
|
-
|
|
628
|
-
kc.createAccountUrl = function (options) {
|
|
629
|
-
var realm = getRealmUrl();
|
|
630
|
-
var url = undefined;
|
|
631
|
-
if (typeof realm !== "undefined") {
|
|
632
|
-
url =
|
|
633
|
-
realm +
|
|
634
|
-
"/account" +
|
|
635
|
-
"?referrer=" +
|
|
636
|
-
encodeURIComponent(kc.clientId) +
|
|
637
|
-
"&referrer_uri=" +
|
|
638
|
-
encodeURIComponent(adapter.redirectUri(options));
|
|
639
|
-
}
|
|
640
|
-
return url;
|
|
641
|
-
};
|
|
642
604
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
605
|
+
kc.isTokenExpired = function(minValidity) {
|
|
606
|
+
if (!kc.tokenParsed || (!kc.refreshToken && kc.flow != 'implicit' )) {
|
|
607
|
+
throw 'Not authenticated';
|
|
608
|
+
}
|
|
646
609
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
610
|
+
if (kc.timeSkew == null) {
|
|
611
|
+
logInfo('[KEYCLOAK] Unable to determine if token is expired as timeskew is not set');
|
|
612
|
+
return true;
|
|
613
|
+
}
|
|
651
614
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
615
|
+
var expiresIn = kc.tokenParsed['exp'] - Math.ceil(new Date().getTime() / 1000) + kc.timeSkew;
|
|
616
|
+
if (minValidity) {
|
|
617
|
+
if (isNaN(minValidity)) {
|
|
618
|
+
throw 'Invalid minValidity';
|
|
619
|
+
}
|
|
620
|
+
expiresIn -= minValidity;
|
|
621
|
+
}
|
|
622
|
+
return expiresIn < 0;
|
|
655
623
|
}
|
|
656
624
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
};
|
|
625
|
+
kc.updateToken = function(minValidity) {
|
|
626
|
+
var promise = createPromise();
|
|
660
627
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
req.setRequestHeader("Accept", "application/json");
|
|
666
|
-
req.setRequestHeader("Authorization", "bearer " + kc.token);
|
|
628
|
+
if (!kc.refreshToken) {
|
|
629
|
+
promise.setError();
|
|
630
|
+
return promise.promise;
|
|
631
|
+
}
|
|
667
632
|
|
|
668
|
-
|
|
633
|
+
minValidity = minValidity || 5;
|
|
669
634
|
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
};
|
|
635
|
+
var exec = function() {
|
|
636
|
+
var refreshToken = false;
|
|
637
|
+
if (minValidity == -1) {
|
|
638
|
+
refreshToken = true;
|
|
639
|
+
logInfo('[KEYCLOAK] Refreshing token: forced refresh');
|
|
640
|
+
} else if (!kc.tokenParsed || kc.isTokenExpired(minValidity)) {
|
|
641
|
+
refreshToken = true;
|
|
642
|
+
logInfo('[KEYCLOAK] Refreshing token: token expired');
|
|
643
|
+
}
|
|
680
644
|
|
|
681
|
-
|
|
645
|
+
if (!refreshToken) {
|
|
646
|
+
promise.setSuccess(false);
|
|
647
|
+
} else {
|
|
648
|
+
var params = 'grant_type=refresh_token&' + 'refresh_token=' + kc.refreshToken;
|
|
649
|
+
var url = kc.endpoints.token();
|
|
682
650
|
|
|
683
|
-
|
|
684
|
-
};
|
|
651
|
+
refreshQueue.push(promise);
|
|
685
652
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
req.setRequestHeader("Authorization", "bearer " + kc.token);
|
|
653
|
+
if (refreshQueue.length == 1) {
|
|
654
|
+
var req = new XMLHttpRequest();
|
|
655
|
+
req.open('POST', url, true);
|
|
656
|
+
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
|
657
|
+
req.withCredentials = true;
|
|
692
658
|
|
|
693
|
-
|
|
659
|
+
params += '&client_id=' + encodeURIComponent(kc.clientId);
|
|
694
660
|
|
|
695
|
-
|
|
696
|
-
if (req.readyState == 4) {
|
|
697
|
-
if (req.status == 200) {
|
|
698
|
-
kc.userInfo = JSON.parse(req.responseText);
|
|
699
|
-
promise.setSuccess(kc.userInfo);
|
|
700
|
-
} else {
|
|
701
|
-
promise.setError();
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
};
|
|
661
|
+
var timeLocal = new Date().getTime();
|
|
705
662
|
|
|
706
|
-
|
|
663
|
+
req.onreadystatechange = function () {
|
|
664
|
+
if (req.readyState == 4) {
|
|
665
|
+
if (req.status == 200) {
|
|
666
|
+
logInfo('[KEYCLOAK] Token refreshed');
|
|
707
667
|
|
|
708
|
-
|
|
709
|
-
};
|
|
668
|
+
timeLocal = (timeLocal + new Date().getTime()) / 2;
|
|
710
669
|
|
|
711
|
-
|
|
712
|
-
if (
|
|
713
|
-
!kc.tokenParsed ||
|
|
714
|
-
(!kc.refreshToken && kc.flow != "implicit")
|
|
715
|
-
) {
|
|
716
|
-
throw "Not authenticated";
|
|
717
|
-
}
|
|
670
|
+
var tokenResponse = JSON.parse(req.responseText);
|
|
718
671
|
|
|
719
|
-
|
|
720
|
-
logInfo(
|
|
721
|
-
"[KEYCLOAK] Unable to determine if token is expired as timeskew is not set"
|
|
722
|
-
);
|
|
672
|
+
setToken(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token'], timeLocal);
|
|
723
673
|
|
|
724
|
-
|
|
725
|
-
|
|
674
|
+
kc.onAuthRefreshSuccess && kc.onAuthRefreshSuccess();
|
|
675
|
+
for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {
|
|
676
|
+
p.setSuccess(true);
|
|
677
|
+
}
|
|
678
|
+
} else {
|
|
679
|
+
logWarn('[KEYCLOAK] Failed to refresh token');
|
|
680
|
+
|
|
681
|
+
if (req.status == 400) {
|
|
682
|
+
kc.clearToken();
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
kc.onAuthRefreshError && kc.onAuthRefreshError();
|
|
686
|
+
for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {
|
|
687
|
+
p.setError(true);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
req.send(params);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
if (loginIframe.enable) {
|
|
699
|
+
var iframePromise = checkLoginIframe();
|
|
700
|
+
iframePromise.then(function() {
|
|
701
|
+
exec();
|
|
702
|
+
}).catch(function(error) {
|
|
703
|
+
promise.setError(error);
|
|
704
|
+
});
|
|
705
|
+
} else {
|
|
706
|
+
exec();
|
|
707
|
+
}
|
|
726
708
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
Math.ceil(new Date().getTime() / 1000) +
|
|
730
|
-
kc.timeSkew;
|
|
709
|
+
return promise.promise;
|
|
710
|
+
}
|
|
731
711
|
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
712
|
+
kc.clearToken = function() {
|
|
713
|
+
if (kc.token) {
|
|
714
|
+
setToken(null, null, null);
|
|
715
|
+
kc.onAuthLogout && kc.onAuthLogout();
|
|
716
|
+
if (kc.loginRequired) {
|
|
717
|
+
kc.login();
|
|
718
|
+
}
|
|
719
|
+
}
|
|
737
720
|
}
|
|
738
|
-
return expiresIn < 0;
|
|
739
|
-
};
|
|
740
721
|
|
|
741
|
-
|
|
742
|
-
|
|
722
|
+
kc.setToken = setToken;
|
|
723
|
+
|
|
724
|
+
function getRealmUrl() {
|
|
725
|
+
if (typeof kc.authServerUrl !== 'undefined') {
|
|
726
|
+
if (kc.authServerUrl.charAt(kc.authServerUrl.length - 1) == '/') {
|
|
727
|
+
return kc.authServerUrl + 'realms/' + encodeURIComponent(kc.realm);
|
|
728
|
+
} else {
|
|
729
|
+
return kc.authServerUrl + '/realms/' + encodeURIComponent(kc.realm);
|
|
730
|
+
}
|
|
731
|
+
} else {
|
|
732
|
+
return undefined;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
743
735
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
736
|
+
function getOrigin() {
|
|
737
|
+
if (!window.location.origin) {
|
|
738
|
+
return window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
|
|
739
|
+
} else {
|
|
740
|
+
return window.location.origin;
|
|
741
|
+
}
|
|
747
742
|
}
|
|
748
743
|
|
|
749
|
-
|
|
744
|
+
function processCallback(oauth, promise) {
|
|
745
|
+
var code = oauth.code;
|
|
746
|
+
var error = oauth.error;
|
|
747
|
+
var prompt = oauth.prompt;
|
|
750
748
|
|
|
751
|
-
|
|
752
|
-
var refreshToken = false;
|
|
753
|
-
if (minValidity == -1) {
|
|
754
|
-
refreshToken = true;
|
|
755
|
-
logInfo("[KEYCLOAK] Refreshing token: forced refresh");
|
|
756
|
-
} else if (!kc.tokenParsed || kc.isTokenExpired(minValidity)) {
|
|
757
|
-
refreshToken = true;
|
|
758
|
-
logInfo("[KEYCLOAK] Refreshing token: token expired");
|
|
759
|
-
}
|
|
749
|
+
var timeLocal = new Date().getTime();
|
|
760
750
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
var params =
|
|
765
|
-
"grant_type=refresh_token&" +
|
|
766
|
-
"refresh_token=" +
|
|
767
|
-
kc.refreshToken;
|
|
751
|
+
if (oauth['kc_action_status']) {
|
|
752
|
+
kc.onActionUpdate && kc.onActionUpdate(oauth['kc_action_status']);
|
|
753
|
+
}
|
|
768
754
|
|
|
769
|
-
|
|
755
|
+
if (error) {
|
|
756
|
+
if (prompt != 'none') {
|
|
757
|
+
var errorData = { error: error, error_description: oauth.error_description };
|
|
758
|
+
kc.onAuthError && kc.onAuthError(errorData);
|
|
759
|
+
promise && promise.setError(errorData);
|
|
760
|
+
} else {
|
|
761
|
+
promise && promise.setSuccess();
|
|
762
|
+
}
|
|
763
|
+
return;
|
|
764
|
+
} else if ((kc.flow != 'standard') && (oauth.access_token || oauth.id_token)) {
|
|
765
|
+
authSuccess(oauth.access_token, null, oauth.id_token, true);
|
|
766
|
+
}
|
|
770
767
|
|
|
771
|
-
|
|
768
|
+
if ((kc.flow != 'implicit') && code) {
|
|
769
|
+
var params = 'code=' + code + '&grant_type=authorization_code';
|
|
770
|
+
var url = kc.endpoints.token();
|
|
772
771
|
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
772
|
+
var req = new XMLHttpRequest();
|
|
773
|
+
req.open('POST', url, true);
|
|
774
|
+
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
|
776
775
|
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
"application/x-www-form-urlencoded"
|
|
780
|
-
);
|
|
776
|
+
params += '&client_id=' + encodeURIComponent(kc.clientId);
|
|
777
|
+
params += '&redirect_uri=' + oauth.redirectUri;
|
|
781
778
|
|
|
782
|
-
|
|
779
|
+
if (oauth.pkceCodeVerifier) {
|
|
780
|
+
params += '&code_verifier=' + oauth.pkceCodeVerifier;
|
|
781
|
+
}
|
|
783
782
|
|
|
784
|
-
|
|
783
|
+
req.withCredentials = true;
|
|
785
784
|
|
|
786
|
-
|
|
785
|
+
req.onreadystatechange = function() {
|
|
786
|
+
if (req.readyState == 4) {
|
|
787
|
+
if (req.status == 200) {
|
|
787
788
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
789
|
+
var tokenResponse = JSON.parse(req.responseText);
|
|
790
|
+
authSuccess(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token'], kc.flow === 'standard');
|
|
791
|
+
scheduleCheckIframe();
|
|
792
|
+
} else {
|
|
793
|
+
kc.onAuthError && kc.onAuthError();
|
|
794
|
+
promise && promise.setError();
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
};
|
|
792
798
|
|
|
793
|
-
|
|
799
|
+
req.send(params);
|
|
800
|
+
}
|
|
794
801
|
|
|
795
|
-
|
|
802
|
+
function authSuccess(accessToken, refreshToken, idToken, fulfillPromise) {
|
|
803
|
+
timeLocal = (timeLocal + new Date().getTime()) / 2;
|
|
796
804
|
|
|
797
|
-
|
|
798
|
-
tokenResponse["access_token"],
|
|
799
|
-
tokenResponse["refresh_token"],
|
|
800
|
-
tokenResponse["id_token"],
|
|
801
|
-
timeLocal
|
|
802
|
-
);
|
|
805
|
+
setToken(accessToken, refreshToken, idToken, timeLocal);
|
|
803
806
|
|
|
804
|
-
|
|
807
|
+
if (useNonce && ((kc.tokenParsed && kc.tokenParsed.nonce != oauth.storedNonce) ||
|
|
808
|
+
(kc.refreshTokenParsed && kc.refreshTokenParsed.nonce != oauth.storedNonce) ||
|
|
809
|
+
(kc.idTokenParsed && kc.idTokenParsed.nonce != oauth.storedNonce))) {
|
|
805
810
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
) {
|
|
811
|
-
|
|
811
|
+
logInfo('[KEYCLOAK] Invalid nonce, clearing token');
|
|
812
|
+
kc.clearToken();
|
|
813
|
+
promise && promise.setError();
|
|
814
|
+
} else {
|
|
815
|
+
if (fulfillPromise) {
|
|
816
|
+
kc.onAuthSuccess && kc.onAuthSuccess();
|
|
817
|
+
promise && promise.setSuccess();
|
|
812
818
|
}
|
|
813
|
-
|
|
814
|
-
|
|
819
|
+
}
|
|
820
|
+
}
|
|
815
821
|
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
function loadConfig(url) {
|
|
825
|
+
var promise = createPromise();
|
|
826
|
+
var configUrl;
|
|
819
827
|
|
|
820
|
-
|
|
828
|
+
if (!config) {
|
|
829
|
+
configUrl = location.origin + '/keycloak.json';
|
|
830
|
+
} else if (typeof config === 'string') {
|
|
831
|
+
configUrl = config;
|
|
832
|
+
}
|
|
821
833
|
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
834
|
+
function setupOidcEndoints(oidcConfiguration) {
|
|
835
|
+
if (! oidcConfiguration) {
|
|
836
|
+
kc.endpoints = {
|
|
837
|
+
authorize: function() {
|
|
838
|
+
return getRealmUrl() + '/protocol/openid-connect/auth';
|
|
839
|
+
},
|
|
840
|
+
token: function() {
|
|
841
|
+
return getRealmUrl() + '/protocol/openid-connect/token';
|
|
842
|
+
},
|
|
843
|
+
logout: function() {
|
|
844
|
+
return getRealmUrl() + '/protocol/openid-connect/logout';
|
|
845
|
+
},
|
|
846
|
+
checkSessionIframe: function() {
|
|
847
|
+
var src = getRealmUrl() + '/protocol/openid-connect/login-status-iframe.html';
|
|
848
|
+
if (kc.iframeVersion) {
|
|
849
|
+
src = src + '?version=' + kc.iframeVersion;
|
|
850
|
+
}
|
|
851
|
+
return src;
|
|
852
|
+
},
|
|
853
|
+
thirdPartyCookiesIframe: function() {
|
|
854
|
+
var src = getRealmUrl() + '/protocol/openid-connect/3p-cookies/step1.html';
|
|
855
|
+
if (kc.iframeVersion) {
|
|
856
|
+
src = src + '?version=' + kc.iframeVersion;
|
|
857
|
+
}
|
|
858
|
+
return src;
|
|
859
|
+
},
|
|
860
|
+
register: function() {
|
|
861
|
+
return getRealmUrl() + '/protocol/openid-connect/registrations';
|
|
862
|
+
},
|
|
863
|
+
userinfo: function() {
|
|
864
|
+
return getRealmUrl() + '/protocol/openid-connect/userinfo';
|
|
865
|
+
}
|
|
866
|
+
};
|
|
867
|
+
} else {
|
|
868
|
+
kc.endpoints = {
|
|
869
|
+
authorize: function() {
|
|
870
|
+
return oidcConfiguration.authorization_endpoint;
|
|
871
|
+
},
|
|
872
|
+
token: function() {
|
|
873
|
+
return oidcConfiguration.token_endpoint;
|
|
874
|
+
},
|
|
875
|
+
logout: function() {
|
|
876
|
+
if (!oidcConfiguration.end_session_endpoint) {
|
|
877
|
+
throw "Not supported by the OIDC server";
|
|
878
|
+
}
|
|
879
|
+
return oidcConfiguration.end_session_endpoint;
|
|
880
|
+
},
|
|
881
|
+
checkSessionIframe: function() {
|
|
882
|
+
if (!oidcConfiguration.check_session_iframe) {
|
|
883
|
+
throw "Not supported by the OIDC server";
|
|
884
|
+
}
|
|
885
|
+
return oidcConfiguration.check_session_iframe;
|
|
886
|
+
},
|
|
887
|
+
register: function() {
|
|
888
|
+
throw 'Redirection to "Register user" page not supported in standard OIDC mode';
|
|
889
|
+
},
|
|
890
|
+
userinfo: function() {
|
|
891
|
+
if (!oidcConfiguration.userinfo_endpoint) {
|
|
892
|
+
throw "Not supported by the OIDC server";
|
|
893
|
+
}
|
|
894
|
+
return oidcConfiguration.userinfo_endpoint;
|
|
895
|
+
}
|
|
828
896
|
}
|
|
829
|
-
}
|
|
830
897
|
}
|
|
831
|
-
};
|
|
832
|
-
|
|
833
|
-
req.send(params);
|
|
834
898
|
}
|
|
835
|
-
}
|
|
836
|
-
};
|
|
837
899
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
900
|
+
if (configUrl) {
|
|
901
|
+
var req = new XMLHttpRequest();
|
|
902
|
+
req.open('GET', configUrl, true);
|
|
903
|
+
req.setRequestHeader('Accept', 'application/json');
|
|
904
|
+
|
|
905
|
+
req.onreadystatechange = function () {
|
|
906
|
+
if (req.readyState == 4) {
|
|
907
|
+
if (req.status == 200 || fileLoaded(req)) {
|
|
908
|
+
var config = JSON.parse(req.responseText);
|
|
909
|
+
|
|
910
|
+
kc.authServerUrl = config['auth-server-url'];
|
|
911
|
+
kc.realm = config['realm'];
|
|
912
|
+
kc.clientId = config['resource'];
|
|
913
|
+
setupOidcEndoints(null);
|
|
914
|
+
promise.setSuccess();
|
|
915
|
+
} else {
|
|
916
|
+
promise.setError();
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
};
|
|
850
920
|
|
|
851
|
-
|
|
852
|
-
|
|
921
|
+
req.send();
|
|
922
|
+
} else {
|
|
923
|
+
if (!config.clientId) {
|
|
924
|
+
throw 'clientId missing';
|
|
925
|
+
}
|
|
853
926
|
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
kc.authServerUrl + "realms/" + encodeURIComponent(kc.realm)
|
|
871
|
-
);
|
|
872
|
-
} else {
|
|
873
|
-
return (
|
|
874
|
-
kc.authServerUrl + "/realms/" + encodeURIComponent(kc.realm)
|
|
875
|
-
);
|
|
876
|
-
}
|
|
877
|
-
} else {
|
|
878
|
-
return undefined;
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
function getOrigin() {
|
|
883
|
-
if (!window.location.origin) {
|
|
884
|
-
return (
|
|
885
|
-
window.location.protocol +
|
|
886
|
-
"//" +
|
|
887
|
-
window.location.hostname +
|
|
888
|
-
(window.location.port ? ":" + window.location.port : "")
|
|
889
|
-
);
|
|
890
|
-
} else {
|
|
891
|
-
return window.location.origin;
|
|
892
|
-
}
|
|
893
|
-
}
|
|
927
|
+
kc.clientId = config.clientId;
|
|
928
|
+
|
|
929
|
+
var oidcProvider = config['oidcProvider'];
|
|
930
|
+
if (!oidcProvider) {
|
|
931
|
+
if (!config['url']) {
|
|
932
|
+
var scripts = document.getElementsByTagName('script');
|
|
933
|
+
for (var i = 0; i < scripts.length; i++) {
|
|
934
|
+
if (scripts[i].src.match(/.*keycloak\.js/)) {
|
|
935
|
+
config.url = scripts[i].src.substr(0, scripts[i].src.indexOf('/js/keycloak.js'));
|
|
936
|
+
break;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
if (!config.realm) {
|
|
941
|
+
throw 'realm missing';
|
|
942
|
+
}
|
|
894
943
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
944
|
+
kc.authServerUrl = config.url;
|
|
945
|
+
kc.realm = config.realm;
|
|
946
|
+
setupOidcEndoints(null);
|
|
947
|
+
promise.setSuccess();
|
|
948
|
+
} else {
|
|
949
|
+
if (typeof oidcProvider === 'string') {
|
|
950
|
+
var oidcProviderConfigUrl;
|
|
951
|
+
if (oidcProvider.charAt(oidcProvider.length - 1) == '/') {
|
|
952
|
+
oidcProviderConfigUrl = oidcProvider + '.well-known/openid-configuration';
|
|
953
|
+
} else {
|
|
954
|
+
oidcProviderConfigUrl = oidcProvider + '/.well-known/openid-configuration';
|
|
955
|
+
}
|
|
956
|
+
var req = new XMLHttpRequest();
|
|
957
|
+
req.open('GET', oidcProviderConfigUrl, true);
|
|
958
|
+
req.setRequestHeader('Accept', 'application/json');
|
|
959
|
+
|
|
960
|
+
req.onreadystatechange = function () {
|
|
961
|
+
if (req.readyState == 4) {
|
|
962
|
+
if (req.status == 200 || fileLoaded(req)) {
|
|
963
|
+
var oidcProviderConfig = JSON.parse(req.responseText);
|
|
964
|
+
setupOidcEndoints(oidcProviderConfig);
|
|
965
|
+
promise.setSuccess();
|
|
966
|
+
} else {
|
|
967
|
+
promise.setError();
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
|
|
972
|
+
req.send();
|
|
973
|
+
} else {
|
|
974
|
+
setupOidcEndoints(oidcProvider);
|
|
975
|
+
promise.setSuccess();
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
899
979
|
|
|
900
|
-
|
|
980
|
+
return promise.promise;
|
|
981
|
+
}
|
|
901
982
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
kc.onActionUpdate(
|
|
905
|
-
oauth["kc_action_status"],
|
|
906
|
-
oauth["kc_action"]
|
|
907
|
-
);
|
|
983
|
+
function fileLoaded(xhr) {
|
|
984
|
+
return xhr.status == 0 && xhr.responseText && xhr.responseURL.startsWith('file:');
|
|
908
985
|
}
|
|
909
986
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
987
|
+
function setToken(token, refreshToken, idToken, timeLocal) {
|
|
988
|
+
if (kc.tokenTimeoutHandle) {
|
|
989
|
+
clearTimeout(kc.tokenTimeoutHandle);
|
|
990
|
+
kc.tokenTimeoutHandle = null;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
if (refreshToken) {
|
|
994
|
+
kc.refreshToken = refreshToken;
|
|
995
|
+
kc.refreshTokenParsed = jwtDecode(refreshToken);
|
|
917
996
|
} else {
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
};
|
|
922
|
-
|
|
923
|
-
kc.onAuthError && kc.onAuthError(errorData);
|
|
924
|
-
promise && promise.setError(errorData);
|
|
925
|
-
}
|
|
926
|
-
} else {
|
|
927
|
-
promise && promise.setSuccess();
|
|
928
|
-
}
|
|
929
|
-
return;
|
|
930
|
-
} else if (
|
|
931
|
-
kc.flow != "standard" &&
|
|
932
|
-
(oauth.access_token || oauth.id_token)
|
|
933
|
-
) {
|
|
934
|
-
authSuccess(oauth.access_token, null, oauth.id_token, true);
|
|
935
|
-
}
|
|
997
|
+
delete kc.refreshToken;
|
|
998
|
+
delete kc.refreshTokenParsed;
|
|
999
|
+
}
|
|
936
1000
|
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
1001
|
+
if (idToken) {
|
|
1002
|
+
kc.idToken = idToken;
|
|
1003
|
+
kc.idTokenParsed = jwtDecode(idToken);
|
|
1004
|
+
} else {
|
|
1005
|
+
delete kc.idToken;
|
|
1006
|
+
delete kc.idTokenParsed;
|
|
1007
|
+
}
|
|
940
1008
|
|
|
941
|
-
|
|
942
|
-
|
|
1009
|
+
if (token) {
|
|
1010
|
+
kc.token = token;
|
|
1011
|
+
kc.tokenParsed = jwtDecode(token);
|
|
1012
|
+
kc.sessionId = kc.tokenParsed.session_state;
|
|
1013
|
+
kc.authenticated = true;
|
|
1014
|
+
kc.subject = kc.tokenParsed.sub;
|
|
1015
|
+
kc.realmAccess = kc.tokenParsed.realm_access;
|
|
1016
|
+
kc.resourceAccess = kc.tokenParsed.resource_access;
|
|
1017
|
+
|
|
1018
|
+
if (timeLocal) {
|
|
1019
|
+
kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;
|
|
1020
|
+
}
|
|
943
1021
|
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
1022
|
+
if (kc.timeSkew != null) {
|
|
1023
|
+
logInfo('[KEYCLOAK] Estimated time difference between browser and server is ' + kc.timeSkew + ' seconds');
|
|
1024
|
+
|
|
1025
|
+
if (kc.onTokenExpired) {
|
|
1026
|
+
var expiresIn = (kc.tokenParsed['exp'] - (new Date().getTime() / 1000) + kc.timeSkew) * 1000;
|
|
1027
|
+
logInfo('[KEYCLOAK] Token expires in ' + Math.round(expiresIn / 1000) + ' s');
|
|
1028
|
+
if (expiresIn <= 0) {
|
|
1029
|
+
kc.onTokenExpired();
|
|
1030
|
+
} else {
|
|
1031
|
+
kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
} else {
|
|
1036
|
+
delete kc.token;
|
|
1037
|
+
delete kc.tokenParsed;
|
|
1038
|
+
delete kc.subject;
|
|
1039
|
+
delete kc.realmAccess;
|
|
1040
|
+
delete kc.resourceAccess;
|
|
948
1041
|
|
|
949
|
-
|
|
950
|
-
|
|
1042
|
+
kc.authenticated = false;
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
951
1045
|
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1046
|
+
function createUUID() {
|
|
1047
|
+
var hexDigits = '0123456789abcdef';
|
|
1048
|
+
var s = generateRandomString(36, hexDigits).split("");
|
|
1049
|
+
s[14] = '4';
|
|
1050
|
+
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
|
|
1051
|
+
s[8] = s[13] = s[18] = s[23] = '-';
|
|
1052
|
+
var uuid = s.join('');
|
|
1053
|
+
return uuid;
|
|
1054
|
+
}
|
|
955
1055
|
|
|
956
|
-
|
|
1056
|
+
function parseCallback(url) {
|
|
1057
|
+
var oauth = parseCallbackUrl(url);
|
|
1058
|
+
if (!oauth) {
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
957
1061
|
|
|
958
|
-
|
|
959
|
-
if (req.readyState == 4) {
|
|
960
|
-
if (req.status == 200) {
|
|
961
|
-
var tokenResponse = JSON.parse(req.responseText);
|
|
962
|
-
authSuccess(
|
|
963
|
-
tokenResponse["access_token"],
|
|
964
|
-
tokenResponse["refresh_token"],
|
|
965
|
-
tokenResponse["id_token"],
|
|
966
|
-
kc.flow === "standard"
|
|
967
|
-
);
|
|
1062
|
+
var oauthState = callbackStorage.get(oauth.state);
|
|
968
1063
|
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
1064
|
+
if (oauthState) {
|
|
1065
|
+
oauth.valid = true;
|
|
1066
|
+
oauth.redirectUri = oauthState.redirectUri;
|
|
1067
|
+
oauth.storedNonce = oauthState.nonce;
|
|
1068
|
+
oauth.prompt = oauthState.prompt;
|
|
1069
|
+
oauth.pkceCodeVerifier = oauthState.pkceCodeVerifier;
|
|
974
1070
|
}
|
|
975
|
-
};
|
|
976
1071
|
|
|
977
|
-
|
|
978
|
-
}
|
|
1072
|
+
return oauth;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
function parseCallbackUrl(url) {
|
|
1076
|
+
var supportedParams;
|
|
1077
|
+
switch (kc.flow) {
|
|
1078
|
+
case 'standard':
|
|
1079
|
+
supportedParams = ['code', 'state', 'session_state', 'kc_action_status', 'iss'];
|
|
1080
|
+
break;
|
|
1081
|
+
case 'implicit':
|
|
1082
|
+
supportedParams = ['access_token', 'token_type', 'id_token', 'state', 'session_state', 'expires_in', 'kc_action_status', 'iss'];
|
|
1083
|
+
break;
|
|
1084
|
+
case 'hybrid':
|
|
1085
|
+
supportedParams = ['access_token', 'token_type', 'id_token', 'code', 'state', 'session_state', 'expires_in', 'kc_action_status', 'iss'];
|
|
1086
|
+
break;
|
|
1087
|
+
}
|
|
979
1088
|
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
idToken,
|
|
984
|
-
fulfillPromise
|
|
985
|
-
) {
|
|
986
|
-
timeLocal = (timeLocal + new Date().getTime()) / 2;
|
|
987
|
-
|
|
988
|
-
setToken(accessToken, refreshToken, idToken, timeLocal);
|
|
989
|
-
|
|
990
|
-
if (
|
|
991
|
-
useNonce &&
|
|
992
|
-
kc.idTokenParsed &&
|
|
993
|
-
kc.idTokenParsed.nonce != oauth.storedNonce
|
|
994
|
-
) {
|
|
995
|
-
logInfo("[KEYCLOAK] Invalid nonce, clearing token");
|
|
996
|
-
kc.clearToken();
|
|
997
|
-
promise && promise.setError();
|
|
998
|
-
} else {
|
|
999
|
-
if (fulfillPromise) {
|
|
1000
|
-
kc.onAuthSuccess && kc.onAuthSuccess();
|
|
1001
|
-
promise && promise.setSuccess();
|
|
1002
|
-
}
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1089
|
+
supportedParams.push('error');
|
|
1090
|
+
supportedParams.push('error_description');
|
|
1091
|
+
supportedParams.push('error_uri');
|
|
1006
1092
|
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
var configUrl;
|
|
1093
|
+
var queryIndex = url.indexOf('?');
|
|
1094
|
+
var fragmentIndex = url.indexOf('#');
|
|
1010
1095
|
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
} else if (typeof config === "string") {
|
|
1014
|
-
configUrl = config;
|
|
1015
|
-
}
|
|
1096
|
+
var newUrl;
|
|
1097
|
+
var parsed;
|
|
1016
1098
|
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
},
|
|
1023
|
-
token: function () {
|
|
1024
|
-
return getRealmUrl() + "/protocol/openid-connect/token";
|
|
1025
|
-
},
|
|
1026
|
-
logout: function () {
|
|
1027
|
-
return getRealmUrl() + "/protocol/openid-connect/logout";
|
|
1028
|
-
},
|
|
1029
|
-
checkSessionIframe: function () {
|
|
1030
|
-
var src =
|
|
1031
|
-
getRealmUrl() +
|
|
1032
|
-
"/protocol/openid-connect/login-status-iframe.html";
|
|
1033
|
-
if (kc.iframeVersion) {
|
|
1034
|
-
src = src + "?version=" + kc.iframeVersion;
|
|
1035
|
-
}
|
|
1036
|
-
return src;
|
|
1037
|
-
},
|
|
1038
|
-
thirdPartyCookiesIframe: function () {
|
|
1039
|
-
var src =
|
|
1040
|
-
getRealmUrl() +
|
|
1041
|
-
"/protocol/openid-connect/3p-cookies/step1.html";
|
|
1042
|
-
if (kc.iframeVersion) {
|
|
1043
|
-
src = src + "?version=" + kc.iframeVersion;
|
|
1044
|
-
}
|
|
1045
|
-
return src;
|
|
1046
|
-
},
|
|
1047
|
-
register: function () {
|
|
1048
|
-
return (
|
|
1049
|
-
getRealmUrl() + "/protocol/openid-connect/registrations"
|
|
1050
|
-
);
|
|
1051
|
-
},
|
|
1052
|
-
userinfo: function () {
|
|
1053
|
-
return (
|
|
1054
|
-
getRealmUrl() + "/protocol/openid-connect/userinfo"
|
|
1055
|
-
);
|
|
1056
|
-
},
|
|
1057
|
-
};
|
|
1058
|
-
} else {
|
|
1059
|
-
kc.endpoints = {
|
|
1060
|
-
authorize: function () {
|
|
1061
|
-
return oidcConfiguration.authorization_endpoint;
|
|
1062
|
-
},
|
|
1063
|
-
token: function () {
|
|
1064
|
-
return oidcConfiguration.token_endpoint;
|
|
1065
|
-
},
|
|
1066
|
-
logout: function () {
|
|
1067
|
-
if (!oidcConfiguration.end_session_endpoint) {
|
|
1068
|
-
throw "Not supported by the OIDC server";
|
|
1099
|
+
if (kc.responseMode === 'query' && queryIndex !== -1) {
|
|
1100
|
+
newUrl = url.substring(0, queryIndex);
|
|
1101
|
+
parsed = parseCallbackParams(url.substring(queryIndex + 1, fragmentIndex !== -1 ? fragmentIndex : url.length), supportedParams);
|
|
1102
|
+
if (parsed.paramsString !== '') {
|
|
1103
|
+
newUrl += '?' + parsed.paramsString;
|
|
1069
1104
|
}
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
checkSessionIframe: function () {
|
|
1073
|
-
if (!oidcConfiguration.check_session_iframe) {
|
|
1074
|
-
throw "Not supported by the OIDC server";
|
|
1105
|
+
if (fragmentIndex !== -1) {
|
|
1106
|
+
newUrl += url.substring(fragmentIndex);
|
|
1075
1107
|
}
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
userinfo: function () {
|
|
1082
|
-
if (!oidcConfiguration.userinfo_endpoint) {
|
|
1083
|
-
throw "Not supported by the OIDC server";
|
|
1108
|
+
} else if (kc.responseMode === 'fragment' && fragmentIndex !== -1) {
|
|
1109
|
+
newUrl = url.substring(0, fragmentIndex);
|
|
1110
|
+
parsed = parseCallbackParams(url.substring(fragmentIndex + 1), supportedParams);
|
|
1111
|
+
if (parsed.paramsString !== '') {
|
|
1112
|
+
newUrl += '#' + parsed.paramsString;
|
|
1084
1113
|
}
|
|
1085
|
-
|
|
1086
|
-
},
|
|
1087
|
-
};
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
if (configUrl) {
|
|
1092
|
-
var req = new XMLHttpRequest();
|
|
1093
|
-
req.open("GET", configUrl, true);
|
|
1094
|
-
req.setRequestHeader("Accept", "application/json");
|
|
1095
|
-
|
|
1096
|
-
req.onreadystatechange = function () {
|
|
1097
|
-
if (req.readyState == 4) {
|
|
1098
|
-
if (req.status == 200 || fileLoaded(req)) {
|
|
1099
|
-
var config = JSON.parse(req.responseText);
|
|
1114
|
+
}
|
|
1100
1115
|
|
|
1101
|
-
|
|
1102
|
-
kc.
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
req.send();
|
|
1113
|
-
} else {
|
|
1114
|
-
if (!config.clientId) {
|
|
1115
|
-
throw "clientId missing";
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
kc.clientId = config.clientId;
|
|
1119
|
-
|
|
1120
|
-
var oidcProvider = config["oidcProvider"];
|
|
1121
|
-
if (!oidcProvider) {
|
|
1122
|
-
if (!config["url"]) {
|
|
1123
|
-
var scripts = document.getElementsByTagName("script");
|
|
1124
|
-
for (var i = 0; i < scripts.length; i++) {
|
|
1125
|
-
if (scripts[i].src.match(/.*keycloak\.js/)) {
|
|
1126
|
-
config.url = scripts[i].src.substr(
|
|
1127
|
-
0,
|
|
1128
|
-
scripts[i].src.indexOf("/js/keycloak.js")
|
|
1129
|
-
);
|
|
1130
|
-
|
|
1131
|
-
break;
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
if (!config.realm) {
|
|
1136
|
-
throw "realm missing";
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
|
-
kc.authServerUrl = config.url;
|
|
1140
|
-
kc.realm = config.realm;
|
|
1141
|
-
setupOidcEndoints(null);
|
|
1142
|
-
promise.setSuccess();
|
|
1143
|
-
} else {
|
|
1144
|
-
if (typeof oidcProvider === "string") {
|
|
1145
|
-
var oidcProviderConfigUrl;
|
|
1146
|
-
if (oidcProvider.charAt(oidcProvider.length - 1) == "/") {
|
|
1147
|
-
oidcProviderConfigUrl =
|
|
1148
|
-
oidcProvider + ".well-known/openid-configuration";
|
|
1149
|
-
} else {
|
|
1150
|
-
oidcProviderConfigUrl =
|
|
1151
|
-
oidcProvider + "/.well-known/openid-configuration";
|
|
1152
|
-
}
|
|
1153
|
-
var req = new XMLHttpRequest();
|
|
1154
|
-
req.open("GET", oidcProviderConfigUrl, true);
|
|
1155
|
-
req.setRequestHeader("Accept", "application/json");
|
|
1156
|
-
|
|
1157
|
-
req.onreadystatechange = function () {
|
|
1158
|
-
if (req.readyState == 4) {
|
|
1159
|
-
if (req.status == 200 || fileLoaded(req)) {
|
|
1160
|
-
var oidcProviderConfig = JSON.parse(req.responseText);
|
|
1161
|
-
setupOidcEndoints(oidcProviderConfig);
|
|
1162
|
-
promise.setSuccess();
|
|
1163
|
-
} else {
|
|
1164
|
-
promise.setError();
|
|
1165
|
-
}
|
|
1116
|
+
if (parsed && parsed.oauthParams) {
|
|
1117
|
+
if (kc.flow === 'standard' || kc.flow === 'hybrid') {
|
|
1118
|
+
if ((parsed.oauthParams.code || parsed.oauthParams.error) && parsed.oauthParams.state) {
|
|
1119
|
+
parsed.oauthParams.newUrl = newUrl;
|
|
1120
|
+
return parsed.oauthParams;
|
|
1121
|
+
}
|
|
1122
|
+
} else if (kc.flow === 'implicit') {
|
|
1123
|
+
if ((parsed.oauthParams.access_token || parsed.oauthParams.error) && parsed.oauthParams.state) {
|
|
1124
|
+
parsed.oauthParams.newUrl = newUrl;
|
|
1125
|
+
return parsed.oauthParams;
|
|
1126
|
+
}
|
|
1166
1127
|
}
|
|
1167
|
-
};
|
|
1168
|
-
|
|
1169
|
-
req.send();
|
|
1170
|
-
} else {
|
|
1171
|
-
setupOidcEndoints(oidcProvider);
|
|
1172
|
-
promise.setSuccess();
|
|
1173
1128
|
}
|
|
1174
|
-
}
|
|
1175
1129
|
}
|
|
1176
1130
|
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1131
|
+
function parseCallbackParams(paramsString, supportedParams) {
|
|
1132
|
+
var p = paramsString.split('&');
|
|
1133
|
+
var result = {
|
|
1134
|
+
paramsString: '',
|
|
1135
|
+
oauthParams: {}
|
|
1136
|
+
}
|
|
1137
|
+
for (var i = 0; i < p.length; i++) {
|
|
1138
|
+
var split = p[i].indexOf("=");
|
|
1139
|
+
var key = p[i].slice(0, split);
|
|
1140
|
+
if (supportedParams.indexOf(key) !== -1) {
|
|
1141
|
+
result.oauthParams[key] = p[i].slice(split + 1);
|
|
1142
|
+
} else {
|
|
1143
|
+
if (result.paramsString !== '') {
|
|
1144
|
+
result.paramsString += '&';
|
|
1145
|
+
}
|
|
1146
|
+
result.paramsString += p[i];
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
return result;
|
|
1192
1150
|
}
|
|
1193
1151
|
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1152
|
+
function createPromise() {
|
|
1153
|
+
// Need to create a native Promise which also preserves the
|
|
1154
|
+
// interface of the custom promise type previously used by the API
|
|
1155
|
+
var p = {
|
|
1156
|
+
setSuccess: function(result) {
|
|
1157
|
+
p.resolve(result);
|
|
1158
|
+
},
|
|
1201
1159
|
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1160
|
+
setError: function(result) {
|
|
1161
|
+
p.reject(result);
|
|
1162
|
+
}
|
|
1163
|
+
};
|
|
1164
|
+
p.promise = new Promise(function(resolve, reject) {
|
|
1165
|
+
p.resolve = resolve;
|
|
1166
|
+
p.reject = reject;
|
|
1167
|
+
});
|
|
1209
1168
|
|
|
1210
|
-
|
|
1211
|
-
kc.token = token;
|
|
1212
|
-
kc.tokenParsed = jwtDecode(token);
|
|
1213
|
-
kc.sessionId = kc.tokenParsed.sid;
|
|
1214
|
-
kc.authenticated = true;
|
|
1215
|
-
kc.subject = kc.tokenParsed.sub;
|
|
1216
|
-
kc.realmAccess = kc.tokenParsed.realm_access;
|
|
1217
|
-
kc.resourceAccess = kc.tokenParsed.resource_access;
|
|
1218
|
-
|
|
1219
|
-
if (timeLocal) {
|
|
1220
|
-
kc.timeSkew =
|
|
1221
|
-
Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;
|
|
1222
|
-
}
|
|
1223
|
-
|
|
1224
|
-
if (kc.timeSkew != null) {
|
|
1225
|
-
logInfo(
|
|
1226
|
-
"[KEYCLOAK] Estimated time difference between browser and server is " +
|
|
1227
|
-
kc.timeSkew +
|
|
1228
|
-
" seconds"
|
|
1229
|
-
);
|
|
1230
|
-
|
|
1231
|
-
if (kc.onTokenExpired) {
|
|
1232
|
-
var expiresIn =
|
|
1233
|
-
(kc.tokenParsed["exp"] -
|
|
1234
|
-
new Date().getTime() / 1000 +
|
|
1235
|
-
kc.timeSkew) *
|
|
1236
|
-
1000;
|
|
1237
|
-
|
|
1238
|
-
logInfo(
|
|
1239
|
-
"[KEYCLOAK] Token expires in " +
|
|
1240
|
-
Math.round(expiresIn / 1000) +
|
|
1241
|
-
" s"
|
|
1242
|
-
);
|
|
1243
|
-
|
|
1244
|
-
if (expiresIn <= 0) {
|
|
1245
|
-
kc.onTokenExpired();
|
|
1246
|
-
} else {
|
|
1247
|
-
kc.tokenTimeoutHandle = setTimeout(
|
|
1248
|
-
kc.onTokenExpired,
|
|
1249
|
-
expiresIn
|
|
1250
|
-
);
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
} else {
|
|
1255
|
-
delete kc.token;
|
|
1256
|
-
delete kc.tokenParsed;
|
|
1257
|
-
delete kc.subject;
|
|
1258
|
-
delete kc.realmAccess;
|
|
1259
|
-
delete kc.resourceAccess;
|
|
1260
|
-
|
|
1261
|
-
kc.authenticated = false;
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1264
|
-
|
|
1265
|
-
function createUUID() {
|
|
1266
|
-
var hexDigits = "0123456789abcdef";
|
|
1267
|
-
var s = generateRandomString(36, hexDigits).split("");
|
|
1268
|
-
s[14] = "4";
|
|
1269
|
-
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
|
|
1270
|
-
s[8] = s[13] = s[18] = s[23] = "-";
|
|
1271
|
-
var uuid = s.join("");
|
|
1272
|
-
return uuid;
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
function parseCallback(url) {
|
|
1276
|
-
var oauth = parseCallbackUrl(url);
|
|
1277
|
-
if (!oauth) {
|
|
1278
|
-
return;
|
|
1169
|
+
return p;
|
|
1279
1170
|
}
|
|
1280
1171
|
|
|
1281
|
-
|
|
1172
|
+
// Function to extend existing native Promise with timeout
|
|
1173
|
+
function applyTimeoutToPromise(promise, timeout, errorMessage) {
|
|
1174
|
+
var timeoutHandle = null;
|
|
1175
|
+
var timeoutPromise = new Promise(function (resolve, reject) {
|
|
1176
|
+
timeoutHandle = setTimeout(function () {
|
|
1177
|
+
reject({ "error": errorMessage || "Promise is not settled within timeout of " + timeout + "ms" });
|
|
1178
|
+
}, timeout);
|
|
1179
|
+
});
|
|
1282
1180
|
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
oauth.storedNonce = oauthState.nonce;
|
|
1287
|
-
oauth.prompt = oauthState.prompt;
|
|
1288
|
-
oauth.pkceCodeVerifier = oauthState.pkceCodeVerifier;
|
|
1289
|
-
oauth.loginOptions = oauthState.loginOptions;
|
|
1181
|
+
return Promise.race([promise, timeoutPromise]).finally(function () {
|
|
1182
|
+
clearTimeout(timeoutHandle);
|
|
1183
|
+
});
|
|
1290
1184
|
}
|
|
1291
1185
|
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
function parseCallbackUrl(url) {
|
|
1296
|
-
var supportedParams;
|
|
1297
|
-
switch (kc.flow) {
|
|
1298
|
-
case "standard":
|
|
1299
|
-
supportedParams = [
|
|
1300
|
-
"code",
|
|
1301
|
-
"state",
|
|
1302
|
-
"session_state",
|
|
1303
|
-
"kc_action_status",
|
|
1304
|
-
"kc_action",
|
|
1305
|
-
"iss",
|
|
1306
|
-
];
|
|
1307
|
-
|
|
1308
|
-
break;
|
|
1309
|
-
case "implicit":
|
|
1310
|
-
supportedParams = [
|
|
1311
|
-
"access_token",
|
|
1312
|
-
"token_type",
|
|
1313
|
-
"id_token",
|
|
1314
|
-
"state",
|
|
1315
|
-
"session_state",
|
|
1316
|
-
"expires_in",
|
|
1317
|
-
"kc_action_status",
|
|
1318
|
-
"kc_action",
|
|
1319
|
-
"iss",
|
|
1320
|
-
];
|
|
1321
|
-
|
|
1322
|
-
break;
|
|
1323
|
-
case "hybrid":
|
|
1324
|
-
supportedParams = [
|
|
1325
|
-
"access_token",
|
|
1326
|
-
"token_type",
|
|
1327
|
-
"id_token",
|
|
1328
|
-
"code",
|
|
1329
|
-
"state",
|
|
1330
|
-
"session_state",
|
|
1331
|
-
"expires_in",
|
|
1332
|
-
"kc_action_status",
|
|
1333
|
-
"kc_action",
|
|
1334
|
-
"iss",
|
|
1335
|
-
];
|
|
1336
|
-
|
|
1337
|
-
break;
|
|
1338
|
-
}
|
|
1186
|
+
function setupCheckLoginIframe() {
|
|
1187
|
+
var promise = createPromise();
|
|
1339
1188
|
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
var queryIndex = url.indexOf("?");
|
|
1345
|
-
var fragmentIndex = url.indexOf("#");
|
|
1346
|
-
|
|
1347
|
-
var newUrl;
|
|
1348
|
-
var parsed;
|
|
1349
|
-
|
|
1350
|
-
if (kc.responseMode === "query" && queryIndex !== -1) {
|
|
1351
|
-
newUrl = url.substring(0, queryIndex);
|
|
1352
|
-
|
|
1353
|
-
parsed = parseCallbackParams(
|
|
1354
|
-
url.substring(
|
|
1355
|
-
queryIndex + 1,
|
|
1356
|
-
fragmentIndex !== -1 ? fragmentIndex : url.length
|
|
1357
|
-
),
|
|
1358
|
-
supportedParams
|
|
1359
|
-
);
|
|
1360
|
-
|
|
1361
|
-
if (parsed.paramsString !== "") {
|
|
1362
|
-
newUrl += "?" + parsed.paramsString;
|
|
1363
|
-
}
|
|
1364
|
-
if (fragmentIndex !== -1) {
|
|
1365
|
-
newUrl += url.substring(fragmentIndex);
|
|
1366
|
-
}
|
|
1367
|
-
} else if (
|
|
1368
|
-
kc.responseMode === "fragment" &&
|
|
1369
|
-
fragmentIndex !== -1
|
|
1370
|
-
) {
|
|
1371
|
-
newUrl = url.substring(0, fragmentIndex);
|
|
1372
|
-
|
|
1373
|
-
parsed = parseCallbackParams(
|
|
1374
|
-
url.substring(fragmentIndex + 1),
|
|
1375
|
-
supportedParams
|
|
1376
|
-
);
|
|
1377
|
-
|
|
1378
|
-
if (parsed.paramsString !== "") {
|
|
1379
|
-
newUrl += "#" + parsed.paramsString;
|
|
1380
|
-
}
|
|
1381
|
-
}
|
|
1189
|
+
if (!loginIframe.enable) {
|
|
1190
|
+
promise.setSuccess();
|
|
1191
|
+
return promise.promise;
|
|
1192
|
+
}
|
|
1382
1193
|
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
parsed.oauthParams.state
|
|
1388
|
-
) {
|
|
1389
|
-
parsed.oauthParams.newUrl = newUrl;
|
|
1390
|
-
return parsed.oauthParams;
|
|
1391
|
-
}
|
|
1392
|
-
} else if (kc.flow === "implicit") {
|
|
1393
|
-
if (
|
|
1394
|
-
(parsed.oauthParams.access_token ||
|
|
1395
|
-
parsed.oauthParams.error) &&
|
|
1396
|
-
parsed.oauthParams.state
|
|
1397
|
-
) {
|
|
1398
|
-
parsed.oauthParams.newUrl = newUrl;
|
|
1399
|
-
return parsed.oauthParams;
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1402
|
-
}
|
|
1403
|
-
}
|
|
1194
|
+
if (loginIframe.iframe) {
|
|
1195
|
+
promise.setSuccess();
|
|
1196
|
+
return promise.promise;
|
|
1197
|
+
}
|
|
1404
1198
|
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
var result = {
|
|
1408
|
-
paramsString: "",
|
|
1409
|
-
oauthParams: {},
|
|
1410
|
-
};
|
|
1411
|
-
for (var i = 0; i < p.length; i++) {
|
|
1412
|
-
var split = p[i].indexOf("=");
|
|
1413
|
-
var key = p[i].slice(0, split);
|
|
1414
|
-
if (supportedParams.indexOf(key) !== -1) {
|
|
1415
|
-
result.oauthParams[key] = p[i].slice(split + 1);
|
|
1416
|
-
} else {
|
|
1417
|
-
if (result.paramsString !== "") {
|
|
1418
|
-
result.paramsString += "&";
|
|
1419
|
-
}
|
|
1420
|
-
result.paramsString += p[i];
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
|
-
return result;
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
function createPromise() {
|
|
1427
|
-
// Need to create a native Promise which also preserves the
|
|
1428
|
-
// interface of the custom promise type previously used by the API
|
|
1429
|
-
var p = {
|
|
1430
|
-
setSuccess: function (result) {
|
|
1431
|
-
p.resolve(result);
|
|
1432
|
-
},
|
|
1433
|
-
|
|
1434
|
-
setError: function (result) {
|
|
1435
|
-
p.reject(result);
|
|
1436
|
-
},
|
|
1437
|
-
};
|
|
1438
|
-
p.promise = new Promise(function (resolve, reject) {
|
|
1439
|
-
p.resolve = resolve;
|
|
1440
|
-
p.reject = reject;
|
|
1441
|
-
});
|
|
1442
|
-
|
|
1443
|
-
return p;
|
|
1444
|
-
}
|
|
1445
|
-
|
|
1446
|
-
// Function to extend existing native Promise with timeout
|
|
1447
|
-
function applyTimeoutToPromise(promise, timeout, errorMessage) {
|
|
1448
|
-
var timeoutHandle = null;
|
|
1449
|
-
var timeoutPromise = new Promise(function (resolve, reject) {
|
|
1450
|
-
timeoutHandle = setTimeout(function () {
|
|
1451
|
-
reject({
|
|
1452
|
-
error:
|
|
1453
|
-
errorMessage ||
|
|
1454
|
-
"Promise is not settled within timeout of " +
|
|
1455
|
-
timeout +
|
|
1456
|
-
"ms",
|
|
1457
|
-
});
|
|
1458
|
-
}, timeout);
|
|
1459
|
-
});
|
|
1460
|
-
|
|
1461
|
-
return Promise.race([promise, timeoutPromise]).finally(
|
|
1462
|
-
function () {
|
|
1463
|
-
clearTimeout(timeoutHandle);
|
|
1464
|
-
}
|
|
1465
|
-
);
|
|
1466
|
-
}
|
|
1467
|
-
|
|
1468
|
-
function setupCheckLoginIframe() {
|
|
1469
|
-
var promise = createPromise();
|
|
1470
|
-
|
|
1471
|
-
if (!loginIframe.enable) {
|
|
1472
|
-
promise.setSuccess();
|
|
1473
|
-
return promise.promise;
|
|
1474
|
-
}
|
|
1199
|
+
var iframe = document.createElement('iframe');
|
|
1200
|
+
loginIframe.iframe = iframe;
|
|
1475
1201
|
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1202
|
+
iframe.onload = function() {
|
|
1203
|
+
var authUrl = kc.endpoints.authorize();
|
|
1204
|
+
if (authUrl.charAt(0) === '/') {
|
|
1205
|
+
loginIframe.iframeOrigin = getOrigin();
|
|
1206
|
+
} else {
|
|
1207
|
+
loginIframe.iframeOrigin = authUrl.substring(0, authUrl.indexOf('/', 8));
|
|
1208
|
+
}
|
|
1209
|
+
promise.setSuccess();
|
|
1210
|
+
}
|
|
1480
1211
|
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
loginIframe.iframeOrigin = getOrigin();
|
|
1488
|
-
} else {
|
|
1489
|
-
loginIframe.iframeOrigin = authUrl.substring(
|
|
1490
|
-
0,
|
|
1491
|
-
authUrl.indexOf("/", 8)
|
|
1492
|
-
);
|
|
1493
|
-
}
|
|
1494
|
-
promise.setSuccess();
|
|
1495
|
-
};
|
|
1212
|
+
var src = kc.endpoints.checkSessionIframe();
|
|
1213
|
+
iframe.setAttribute('src', src );
|
|
1214
|
+
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
|
|
1215
|
+
iframe.setAttribute('title', 'keycloak-session-iframe' );
|
|
1216
|
+
iframe.style.display = 'none';
|
|
1217
|
+
document.body.appendChild(iframe);
|
|
1496
1218
|
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
"sandbox",
|
|
1502
|
-
"allow-storage-access-by-user-activation allow-scripts allow-same-origin"
|
|
1503
|
-
);
|
|
1504
|
-
|
|
1505
|
-
iframe.setAttribute("title", "keycloak-session-iframe");
|
|
1506
|
-
iframe.style.display = "none";
|
|
1507
|
-
document.body.appendChild(iframe);
|
|
1508
|
-
|
|
1509
|
-
var messageCallback = function (event) {
|
|
1510
|
-
if (
|
|
1511
|
-
event.origin !== loginIframe.iframeOrigin ||
|
|
1512
|
-
loginIframe.iframe.contentWindow !== event.source
|
|
1513
|
-
) {
|
|
1514
|
-
return;
|
|
1515
|
-
}
|
|
1516
|
-
|
|
1517
|
-
if (
|
|
1518
|
-
!(
|
|
1519
|
-
event.data == "unchanged" ||
|
|
1520
|
-
event.data == "changed" ||
|
|
1521
|
-
event.data == "error"
|
|
1522
|
-
)
|
|
1523
|
-
) {
|
|
1524
|
-
return;
|
|
1525
|
-
}
|
|
1526
|
-
|
|
1527
|
-
if (event.data != "unchanged") {
|
|
1528
|
-
kc.clearToken();
|
|
1529
|
-
}
|
|
1530
|
-
|
|
1531
|
-
var callbacks = loginIframe.callbackList.splice(
|
|
1532
|
-
0,
|
|
1533
|
-
loginIframe.callbackList.length
|
|
1534
|
-
);
|
|
1535
|
-
|
|
1536
|
-
for (var i = callbacks.length - 1; i >= 0; --i) {
|
|
1537
|
-
var promise = callbacks[i];
|
|
1538
|
-
if (event.data == "error") {
|
|
1539
|
-
promise.setError();
|
|
1540
|
-
} else {
|
|
1541
|
-
promise.setSuccess(event.data == "unchanged");
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
};
|
|
1219
|
+
var messageCallback = function(event) {
|
|
1220
|
+
if ((event.origin !== loginIframe.iframeOrigin) || (loginIframe.iframe.contentWindow !== event.source)) {
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1545
1223
|
|
|
1546
|
-
|
|
1224
|
+
if (!(event.data == 'unchanged' || event.data == 'changed' || event.data == 'error')) {
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1547
1227
|
|
|
1548
|
-
return promise.promise;
|
|
1549
|
-
}
|
|
1550
1228
|
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
if (kc.token) {
|
|
1554
|
-
setTimeout(function () {
|
|
1555
|
-
checkLoginIframe().then(function (unchanged) {
|
|
1556
|
-
if (unchanged) {
|
|
1557
|
-
scheduleCheckIframe();
|
|
1229
|
+
if (event.data != 'unchanged') {
|
|
1230
|
+
kc.clearToken();
|
|
1558
1231
|
}
|
|
1559
|
-
});
|
|
1560
|
-
}, loginIframe.interval * 1000);
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
}
|
|
1564
|
-
|
|
1565
|
-
function checkLoginIframe() {
|
|
1566
|
-
var promise = createPromise();
|
|
1567
|
-
|
|
1568
|
-
if (loginIframe.iframe && loginIframe.iframeOrigin) {
|
|
1569
|
-
var msg =
|
|
1570
|
-
kc.clientId + " " + (kc.sessionId ? kc.sessionId : "");
|
|
1571
|
-
loginIframe.callbackList.push(promise);
|
|
1572
|
-
var origin = loginIframe.iframeOrigin;
|
|
1573
|
-
if (loginIframe.callbackList.length == 1) {
|
|
1574
|
-
loginIframe.iframe.contentWindow.postMessage(msg, origin);
|
|
1575
|
-
}
|
|
1576
|
-
} else {
|
|
1577
|
-
promise.setSuccess();
|
|
1578
|
-
}
|
|
1579
1232
|
|
|
1580
|
-
|
|
1581
|
-
}
|
|
1582
|
-
|
|
1583
|
-
function check3pCookiesSupported() {
|
|
1584
|
-
var promise = createPromise();
|
|
1585
|
-
|
|
1586
|
-
if (loginIframe.enable || kc.silentCheckSsoRedirectUri) {
|
|
1587
|
-
var iframe = document.createElement("iframe");
|
|
1588
|
-
|
|
1589
|
-
iframe.setAttribute(
|
|
1590
|
-
"src",
|
|
1591
|
-
kc.endpoints.thirdPartyCookiesIframe()
|
|
1592
|
-
);
|
|
1593
|
-
|
|
1594
|
-
iframe.setAttribute(
|
|
1595
|
-
"sandbox",
|
|
1596
|
-
"allow-storage-access-by-user-activation allow-scripts allow-same-origin"
|
|
1597
|
-
);
|
|
1598
|
-
|
|
1599
|
-
iframe.setAttribute("title", "keycloak-3p-check-iframe");
|
|
1600
|
-
iframe.style.display = "none";
|
|
1601
|
-
document.body.appendChild(iframe);
|
|
1602
|
-
|
|
1603
|
-
var messageCallback = function (event) {
|
|
1604
|
-
if (iframe.contentWindow !== event.source) {
|
|
1605
|
-
return;
|
|
1606
|
-
}
|
|
1607
|
-
|
|
1608
|
-
if (
|
|
1609
|
-
event.data !== "supported" &&
|
|
1610
|
-
event.data !== "unsupported"
|
|
1611
|
-
) {
|
|
1612
|
-
return;
|
|
1613
|
-
} else if (event.data === "unsupported") {
|
|
1614
|
-
logWarn(
|
|
1615
|
-
"[KEYCLOAK] Your browser is blocking access to 3rd-party cookies, this means:\n\n" +
|
|
1616
|
-
" - It is not possible to retrieve tokens without redirecting to the Keycloak server (a.k.a. no support for silent authentication).\n" +
|
|
1617
|
-
" - It is not possible to automatically detect changes to the session status (such as the user logging out in another tab).\n\n" +
|
|
1618
|
-
"For more information see: https://www.keycloak.org/docs/latest/securing_apps/#_modern_browsers"
|
|
1619
|
-
);
|
|
1620
|
-
|
|
1621
|
-
loginIframe.enable = false;
|
|
1622
|
-
if (kc.silentCheckSsoFallback) {
|
|
1623
|
-
kc.silentCheckSsoRedirectUri = false;
|
|
1624
|
-
}
|
|
1625
|
-
}
|
|
1626
|
-
|
|
1627
|
-
document.body.removeChild(iframe);
|
|
1628
|
-
window.removeEventListener("message", messageCallback);
|
|
1629
|
-
promise.setSuccess();
|
|
1630
|
-
};
|
|
1631
|
-
|
|
1632
|
-
window.addEventListener("message", messageCallback, false);
|
|
1633
|
-
} else {
|
|
1634
|
-
promise.setSuccess();
|
|
1635
|
-
}
|
|
1233
|
+
var callbacks = loginIframe.callbackList.splice(0, loginIframe.callbackList.length);
|
|
1636
1234
|
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
return {
|
|
1647
|
-
login: function (options) {
|
|
1648
|
-
window.location.assign(kc.createLoginUrl(options));
|
|
1649
|
-
return createPromise().promise;
|
|
1650
|
-
},
|
|
1651
|
-
|
|
1652
|
-
logout: async function (options) {
|
|
1653
|
-
const logoutMethod =
|
|
1654
|
-
options?.logoutMethod ?? kc.logoutMethod;
|
|
1655
|
-
if (logoutMethod === "GET") {
|
|
1656
|
-
window.location.replace(kc.createLogoutUrl(options));
|
|
1657
|
-
return;
|
|
1658
|
-
}
|
|
1235
|
+
for (var i = callbacks.length - 1; i >= 0; --i) {
|
|
1236
|
+
var promise = callbacks[i];
|
|
1237
|
+
if (event.data == 'error') {
|
|
1238
|
+
promise.setError();
|
|
1239
|
+
} else {
|
|
1240
|
+
promise.setSuccess(event.data == 'unchanged');
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
};
|
|
1659
1244
|
|
|
1660
|
-
|
|
1661
|
-
const response = await fetch(logoutUrl, {
|
|
1662
|
-
method: "POST",
|
|
1663
|
-
headers: {
|
|
1664
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
1665
|
-
},
|
|
1666
|
-
body: new URLSearchParams({
|
|
1667
|
-
id_token_hint: kc.idToken,
|
|
1668
|
-
client_id: kc.clientId,
|
|
1669
|
-
post_logout_redirect_uri: adapter.redirectUri(
|
|
1670
|
-
options,
|
|
1671
|
-
false
|
|
1672
|
-
),
|
|
1673
|
-
}),
|
|
1674
|
-
});
|
|
1675
|
-
|
|
1676
|
-
if (response.redirected) {
|
|
1677
|
-
window.location.href = response.url;
|
|
1678
|
-
return;
|
|
1679
|
-
}
|
|
1245
|
+
window.addEventListener('message', messageCallback, false);
|
|
1680
1246
|
|
|
1681
|
-
|
|
1682
|
-
window.location.reload();
|
|
1683
|
-
return;
|
|
1684
|
-
}
|
|
1685
|
-
|
|
1686
|
-
throw new Error(
|
|
1687
|
-
"Logout failed, request returned an error code."
|
|
1688
|
-
);
|
|
1689
|
-
},
|
|
1690
|
-
|
|
1691
|
-
register: function (options) {
|
|
1692
|
-
window.location.assign(kc.createRegisterUrl(options));
|
|
1693
|
-
return createPromise().promise;
|
|
1694
|
-
},
|
|
1695
|
-
|
|
1696
|
-
accountManagement: function () {
|
|
1697
|
-
var accountUrl = kc.createAccountUrl();
|
|
1698
|
-
if (typeof accountUrl !== "undefined") {
|
|
1699
|
-
window.location.href = accountUrl;
|
|
1700
|
-
} else {
|
|
1701
|
-
throw "Not supported by the OIDC server";
|
|
1702
|
-
}
|
|
1703
|
-
return createPromise().promise;
|
|
1704
|
-
},
|
|
1705
|
-
|
|
1706
|
-
redirectUri: function (options, encodeHash) {
|
|
1707
|
-
if (arguments.length == 1) {
|
|
1708
|
-
encodeHash = true;
|
|
1709
|
-
}
|
|
1710
|
-
|
|
1711
|
-
if (options && options.redirectUri) {
|
|
1712
|
-
return options.redirectUri;
|
|
1713
|
-
} else if (kc.redirectUri) {
|
|
1714
|
-
return kc.redirectUri;
|
|
1715
|
-
} else {
|
|
1716
|
-
return location.href;
|
|
1717
|
-
}
|
|
1718
|
-
},
|
|
1719
|
-
};
|
|
1247
|
+
return promise.promise;
|
|
1720
1248
|
}
|
|
1721
1249
|
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
target,
|
|
1734
|
-
options
|
|
1735
|
-
);
|
|
1736
|
-
} else {
|
|
1737
|
-
return window.open(loginUrl, target, options);
|
|
1250
|
+
function scheduleCheckIframe() {
|
|
1251
|
+
if (loginIframe.enable) {
|
|
1252
|
+
if (kc.token) {
|
|
1253
|
+
setTimeout(function() {
|
|
1254
|
+
checkLoginIframe().then(function(unchanged) {
|
|
1255
|
+
if (unchanged) {
|
|
1256
|
+
scheduleCheckIframe();
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1259
|
+
}, loginIframe.interval * 1000);
|
|
1260
|
+
}
|
|
1738
1261
|
}
|
|
1739
|
-
|
|
1262
|
+
}
|
|
1740
1263
|
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
return Object.keys(userOptions.cordovaOptions).reduce(
|
|
1744
|
-
function (options, optionName) {
|
|
1745
|
-
options[optionName] =
|
|
1746
|
-
userOptions.cordovaOptions[optionName];
|
|
1264
|
+
function checkLoginIframe() {
|
|
1265
|
+
var promise = createPromise();
|
|
1747
1266
|
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
}
|
|
1755
|
-
};
|
|
1756
|
-
|
|
1757
|
-
var formatCordovaOptions = function (cordovaOptions) {
|
|
1758
|
-
return Object.keys(cordovaOptions)
|
|
1759
|
-
.reduce(function (options, optionName) {
|
|
1760
|
-
options.push(
|
|
1761
|
-
optionName + "=" + cordovaOptions[optionName]
|
|
1762
|
-
);
|
|
1763
|
-
|
|
1764
|
-
return options;
|
|
1765
|
-
}, [])
|
|
1766
|
-
.join(",");
|
|
1767
|
-
};
|
|
1768
|
-
|
|
1769
|
-
var createCordovaOptions = function (userOptions) {
|
|
1770
|
-
var cordovaOptions = shallowCloneCordovaOptions(userOptions);
|
|
1771
|
-
cordovaOptions.location = "no";
|
|
1772
|
-
if (userOptions && userOptions.prompt == "none") {
|
|
1773
|
-
cordovaOptions.hidden = "yes";
|
|
1774
|
-
}
|
|
1775
|
-
return formatCordovaOptions(cordovaOptions);
|
|
1776
|
-
};
|
|
1777
|
-
|
|
1778
|
-
var getCordovaRedirectUri = function () {
|
|
1779
|
-
return kc.redirectUri || "http://localhost";
|
|
1780
|
-
};
|
|
1781
|
-
|
|
1782
|
-
return {
|
|
1783
|
-
login: function (options) {
|
|
1784
|
-
var promise = createPromise();
|
|
1785
|
-
|
|
1786
|
-
var cordovaOptions = createCordovaOptions(options);
|
|
1787
|
-
var loginUrl = kc.createLoginUrl(options);
|
|
1788
|
-
var ref = cordovaOpenWindowWrapper(
|
|
1789
|
-
loginUrl,
|
|
1790
|
-
"_blank",
|
|
1791
|
-
cordovaOptions
|
|
1792
|
-
);
|
|
1793
|
-
|
|
1794
|
-
var completed = false;
|
|
1795
|
-
|
|
1796
|
-
var closed = false;
|
|
1797
|
-
var closeBrowser = function () {
|
|
1798
|
-
closed = true;
|
|
1799
|
-
ref.close();
|
|
1800
|
-
};
|
|
1801
|
-
|
|
1802
|
-
ref.addEventListener("loadstart", function (event) {
|
|
1803
|
-
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1804
|
-
var callback = parseCallback(event.url);
|
|
1805
|
-
processCallback(callback, promise);
|
|
1806
|
-
closeBrowser();
|
|
1807
|
-
completed = true;
|
|
1808
|
-
}
|
|
1809
|
-
});
|
|
1810
|
-
|
|
1811
|
-
ref.addEventListener("loaderror", function (event) {
|
|
1812
|
-
if (!completed) {
|
|
1813
|
-
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1814
|
-
var callback = parseCallback(event.url);
|
|
1815
|
-
processCallback(callback, promise);
|
|
1816
|
-
closeBrowser();
|
|
1817
|
-
completed = true;
|
|
1818
|
-
} else {
|
|
1819
|
-
promise.setError();
|
|
1820
|
-
closeBrowser();
|
|
1821
|
-
}
|
|
1267
|
+
if (loginIframe.iframe && loginIframe.iframeOrigin ) {
|
|
1268
|
+
var msg = kc.clientId + ' ' + (kc.sessionId ? kc.sessionId : '');
|
|
1269
|
+
loginIframe.callbackList.push(promise);
|
|
1270
|
+
var origin = loginIframe.iframeOrigin;
|
|
1271
|
+
if (loginIframe.callbackList.length == 1) {
|
|
1272
|
+
loginIframe.iframe.contentWindow.postMessage(msg, origin);
|
|
1822
1273
|
}
|
|
1823
|
-
|
|
1274
|
+
} else {
|
|
1275
|
+
promise.setSuccess();
|
|
1276
|
+
}
|
|
1824
1277
|
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
promise.setError({
|
|
1828
|
-
reason: "closed_by_user",
|
|
1829
|
-
});
|
|
1830
|
-
}
|
|
1831
|
-
});
|
|
1278
|
+
return promise.promise;
|
|
1279
|
+
}
|
|
1832
1280
|
|
|
1833
|
-
|
|
1834
|
-
|
|
1281
|
+
function check3pCookiesSupported() {
|
|
1282
|
+
var promise = createPromise();
|
|
1835
1283
|
|
|
1836
|
-
|
|
1837
|
-
|
|
1284
|
+
if (loginIframe.enable || kc.silentCheckSsoRedirectUri) {
|
|
1285
|
+
var iframe = document.createElement('iframe');
|
|
1286
|
+
iframe.setAttribute('src', kc.endpoints.thirdPartyCookiesIframe());
|
|
1287
|
+
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
|
|
1288
|
+
iframe.setAttribute('title', 'keycloak-3p-check-iframe' );
|
|
1289
|
+
iframe.style.display = 'none';
|
|
1290
|
+
document.body.appendChild(iframe);
|
|
1838
1291
|
|
|
1839
|
-
|
|
1292
|
+
var messageCallback = function(event) {
|
|
1293
|
+
if (iframe.contentWindow !== event.source) {
|
|
1294
|
+
return;
|
|
1295
|
+
}
|
|
1840
1296
|
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1297
|
+
if (event.data !== "supported" && event.data !== "unsupported") {
|
|
1298
|
+
return;
|
|
1299
|
+
} else if (event.data === "unsupported") {
|
|
1300
|
+
logWarn(
|
|
1301
|
+
"[KEYCLOAK] Your browser is blocking access to 3rd-party cookies, this means:\n\n" +
|
|
1302
|
+
" - It is not possible to retrieve tokens without redirecting to the Keycloak server (a.k.a. no support for silent authentication).\n" +
|
|
1303
|
+
" - It is not possible to automatically detect changes to the session status (such as the user logging out in another tab).\n\n" +
|
|
1304
|
+
"For more information see: https://www.keycloak.org/docs/latest/securing_apps/#_modern_browsers"
|
|
1305
|
+
);
|
|
1306
|
+
|
|
1307
|
+
loginIframe.enable = false;
|
|
1308
|
+
if (kc.silentCheckSsoFallback) {
|
|
1309
|
+
kc.silentCheckSsoRedirectUri = false;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1846
1312
|
|
|
1847
|
-
|
|
1313
|
+
document.body.removeChild(iframe);
|
|
1314
|
+
window.removeEventListener("message", messageCallback);
|
|
1315
|
+
promise.setSuccess();
|
|
1316
|
+
};
|
|
1848
1317
|
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
});
|
|
1318
|
+
window.addEventListener('message', messageCallback, false);
|
|
1319
|
+
} else {
|
|
1320
|
+
promise.setSuccess();
|
|
1321
|
+
}
|
|
1854
1322
|
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1323
|
+
return applyTimeoutToPromise(promise.promise, kc.messageReceiveTimeout, "Timeout when waiting for 3rd party check iframe message.");
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
function loadAdapter(type) {
|
|
1327
|
+
if (!type || type == 'default') {
|
|
1328
|
+
return {
|
|
1329
|
+
login: function(options) {
|
|
1330
|
+
window.location.assign(kc.createLoginUrl(options));
|
|
1331
|
+
return createPromise().promise;
|
|
1332
|
+
},
|
|
1333
|
+
|
|
1334
|
+
logout: function(options) {
|
|
1335
|
+
window.location.replace(kc.createLogoutUrl(options));
|
|
1336
|
+
return createPromise().promise;
|
|
1337
|
+
},
|
|
1338
|
+
|
|
1339
|
+
register: function(options) {
|
|
1340
|
+
window.location.assign(kc.createRegisterUrl(options));
|
|
1341
|
+
return createPromise().promise;
|
|
1342
|
+
},
|
|
1343
|
+
|
|
1344
|
+
accountManagement : function() {
|
|
1345
|
+
var accountUrl = kc.createAccountUrl();
|
|
1346
|
+
if (typeof accountUrl !== 'undefined') {
|
|
1347
|
+
window.location.href = accountUrl;
|
|
1348
|
+
} else {
|
|
1349
|
+
throw "Not supported by the OIDC server";
|
|
1350
|
+
}
|
|
1351
|
+
return createPromise().promise;
|
|
1352
|
+
},
|
|
1353
|
+
|
|
1354
|
+
redirectUri: function(options, encodeHash) {
|
|
1355
|
+
if (arguments.length == 1) {
|
|
1356
|
+
encodeHash = true;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
if (options && options.redirectUri) {
|
|
1360
|
+
return options.redirectUri;
|
|
1361
|
+
} else if (kc.redirectUri) {
|
|
1362
|
+
return kc.redirectUri;
|
|
1363
|
+
} else {
|
|
1364
|
+
return location.href;
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1863
1369
|
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1370
|
+
if (type == 'cordova') {
|
|
1371
|
+
loginIframe.enable = false;
|
|
1372
|
+
var cordovaOpenWindowWrapper = function(loginUrl, target, options) {
|
|
1373
|
+
if (window.cordova && window.cordova.InAppBrowser) {
|
|
1374
|
+
// Use inappbrowser for IOS and Android if available
|
|
1375
|
+
return window.cordova.InAppBrowser.open(loginUrl, target, options);
|
|
1376
|
+
} else {
|
|
1377
|
+
return window.open(loginUrl, target, options);
|
|
1378
|
+
}
|
|
1379
|
+
};
|
|
1380
|
+
|
|
1381
|
+
var shallowCloneCordovaOptions = function (userOptions) {
|
|
1382
|
+
if (userOptions && userOptions.cordovaOptions) {
|
|
1383
|
+
return Object.keys(userOptions.cordovaOptions).reduce(function (options, optionName) {
|
|
1384
|
+
options[optionName] = userOptions.cordovaOptions[optionName];
|
|
1385
|
+
return options;
|
|
1386
|
+
}, {});
|
|
1387
|
+
} else {
|
|
1388
|
+
return {};
|
|
1389
|
+
}
|
|
1390
|
+
};
|
|
1391
|
+
|
|
1392
|
+
var formatCordovaOptions = function (cordovaOptions) {
|
|
1393
|
+
return Object.keys(cordovaOptions).reduce(function (options, optionName) {
|
|
1394
|
+
options.push(optionName+"="+cordovaOptions[optionName]);
|
|
1395
|
+
return options;
|
|
1396
|
+
}, []).join(",");
|
|
1397
|
+
};
|
|
1398
|
+
|
|
1399
|
+
var createCordovaOptions = function (userOptions) {
|
|
1400
|
+
var cordovaOptions = shallowCloneCordovaOptions(userOptions);
|
|
1401
|
+
cordovaOptions.location = 'no';
|
|
1402
|
+
if (userOptions && userOptions.prompt == 'none') {
|
|
1403
|
+
cordovaOptions.hidden = 'yes';
|
|
1404
|
+
}
|
|
1405
|
+
return formatCordovaOptions(cordovaOptions);
|
|
1406
|
+
};
|
|
1407
|
+
|
|
1408
|
+
var getCordovaRedirectUri = function() {
|
|
1409
|
+
return kc.redirectUri || 'http://localhost';
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
return {
|
|
1413
|
+
login: function(options) {
|
|
1414
|
+
var promise = createPromise();
|
|
1415
|
+
|
|
1416
|
+
var cordovaOptions = createCordovaOptions(options);
|
|
1417
|
+
var loginUrl = kc.createLoginUrl(options);
|
|
1418
|
+
var ref = cordovaOpenWindowWrapper(loginUrl, '_blank', cordovaOptions);
|
|
1419
|
+
var completed = false;
|
|
1420
|
+
|
|
1421
|
+
var closed = false;
|
|
1422
|
+
var closeBrowser = function() {
|
|
1423
|
+
closed = true;
|
|
1424
|
+
ref.close();
|
|
1425
|
+
};
|
|
1426
|
+
|
|
1427
|
+
ref.addEventListener('loadstart', function(event) {
|
|
1428
|
+
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1429
|
+
var callback = parseCallback(event.url);
|
|
1430
|
+
processCallback(callback, promise);
|
|
1431
|
+
closeBrowser();
|
|
1432
|
+
completed = true;
|
|
1433
|
+
}
|
|
1434
|
+
});
|
|
1435
|
+
|
|
1436
|
+
ref.addEventListener('loaderror', function(event) {
|
|
1437
|
+
if (!completed) {
|
|
1438
|
+
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1439
|
+
var callback = parseCallback(event.url);
|
|
1440
|
+
processCallback(callback, promise);
|
|
1441
|
+
closeBrowser();
|
|
1442
|
+
completed = true;
|
|
1443
|
+
} else {
|
|
1444
|
+
promise.setError();
|
|
1445
|
+
closeBrowser();
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
});
|
|
1449
|
+
|
|
1450
|
+
ref.addEventListener('exit', function(event) {
|
|
1451
|
+
if (!closed) {
|
|
1452
|
+
promise.setError({
|
|
1453
|
+
reason: "closed_by_user"
|
|
1454
|
+
});
|
|
1455
|
+
}
|
|
1456
|
+
});
|
|
1457
|
+
|
|
1458
|
+
return promise.promise;
|
|
1459
|
+
},
|
|
1460
|
+
|
|
1461
|
+
logout: function(options) {
|
|
1462
|
+
var promise = createPromise();
|
|
1463
|
+
|
|
1464
|
+
var logoutUrl = kc.createLogoutUrl(options);
|
|
1465
|
+
var ref = cordovaOpenWindowWrapper(logoutUrl, '_blank', 'location=no,hidden=yes,clearcache=yes');
|
|
1466
|
+
|
|
1467
|
+
var error;
|
|
1468
|
+
|
|
1469
|
+
ref.addEventListener('loadstart', function(event) {
|
|
1470
|
+
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1471
|
+
ref.close();
|
|
1472
|
+
}
|
|
1473
|
+
});
|
|
1474
|
+
|
|
1475
|
+
ref.addEventListener('loaderror', function(event) {
|
|
1476
|
+
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1477
|
+
ref.close();
|
|
1478
|
+
} else {
|
|
1479
|
+
error = true;
|
|
1480
|
+
ref.close();
|
|
1481
|
+
}
|
|
1482
|
+
});
|
|
1483
|
+
|
|
1484
|
+
ref.addEventListener('exit', function(event) {
|
|
1485
|
+
if (error) {
|
|
1486
|
+
promise.setError();
|
|
1487
|
+
} else {
|
|
1488
|
+
kc.clearToken();
|
|
1489
|
+
promise.setSuccess();
|
|
1490
|
+
}
|
|
1491
|
+
});
|
|
1492
|
+
|
|
1493
|
+
return promise.promise;
|
|
1494
|
+
},
|
|
1495
|
+
|
|
1496
|
+
register : function(options) {
|
|
1497
|
+
var promise = createPromise();
|
|
1498
|
+
var registerUrl = kc.createRegisterUrl();
|
|
1499
|
+
var cordovaOptions = createCordovaOptions(options);
|
|
1500
|
+
var ref = cordovaOpenWindowWrapper(registerUrl, '_blank', cordovaOptions);
|
|
1501
|
+
ref.addEventListener('loadstart', function(event) {
|
|
1502
|
+
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1503
|
+
ref.close();
|
|
1504
|
+
var oauth = parseCallback(event.url);
|
|
1505
|
+
processCallback(oauth, promise);
|
|
1506
|
+
}
|
|
1507
|
+
});
|
|
1508
|
+
return promise.promise;
|
|
1509
|
+
},
|
|
1510
|
+
|
|
1511
|
+
accountManagement : function() {
|
|
1512
|
+
var accountUrl = kc.createAccountUrl();
|
|
1513
|
+
if (typeof accountUrl !== 'undefined') {
|
|
1514
|
+
var ref = cordovaOpenWindowWrapper(accountUrl, '_blank', 'location=no');
|
|
1515
|
+
ref.addEventListener('loadstart', function(event) {
|
|
1516
|
+
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1517
|
+
ref.close();
|
|
1518
|
+
}
|
|
1519
|
+
});
|
|
1520
|
+
} else {
|
|
1521
|
+
throw "Not supported by the OIDC server";
|
|
1522
|
+
}
|
|
1523
|
+
},
|
|
1524
|
+
|
|
1525
|
+
redirectUri: function(options) {
|
|
1526
|
+
return getCordovaRedirectUri();
|
|
1527
|
+
}
|
|
1870
1528
|
}
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
if (type == 'cordova-native') {
|
|
1532
|
+
loginIframe.enable = false;
|
|
1533
|
+
|
|
1534
|
+
return {
|
|
1535
|
+
login: function(options) {
|
|
1536
|
+
var promise = createPromise();
|
|
1537
|
+
var loginUrl = kc.createLoginUrl(options);
|
|
1538
|
+
|
|
1539
|
+
universalLinks.subscribe('keycloak', function(event) {
|
|
1540
|
+
universalLinks.unsubscribe('keycloak');
|
|
1541
|
+
window.cordova.plugins.browsertab.close();
|
|
1542
|
+
var oauth = parseCallback(event.url);
|
|
1543
|
+
processCallback(oauth, promise);
|
|
1544
|
+
});
|
|
1545
|
+
|
|
1546
|
+
window.cordova.plugins.browsertab.openUrl(loginUrl);
|
|
1547
|
+
return promise.promise;
|
|
1548
|
+
},
|
|
1549
|
+
|
|
1550
|
+
logout: function(options) {
|
|
1551
|
+
var promise = createPromise();
|
|
1552
|
+
var logoutUrl = kc.createLogoutUrl(options);
|
|
1553
|
+
|
|
1554
|
+
universalLinks.subscribe('keycloak', function(event) {
|
|
1555
|
+
universalLinks.unsubscribe('keycloak');
|
|
1556
|
+
window.cordova.plugins.browsertab.close();
|
|
1557
|
+
kc.clearToken();
|
|
1558
|
+
promise.setSuccess();
|
|
1559
|
+
});
|
|
1560
|
+
|
|
1561
|
+
window.cordova.plugins.browsertab.openUrl(logoutUrl);
|
|
1562
|
+
return promise.promise;
|
|
1563
|
+
},
|
|
1564
|
+
|
|
1565
|
+
register : function(options) {
|
|
1566
|
+
var promise = createPromise();
|
|
1567
|
+
var registerUrl = kc.createRegisterUrl(options);
|
|
1568
|
+
universalLinks.subscribe('keycloak' , function(event) {
|
|
1569
|
+
universalLinks.unsubscribe('keycloak');
|
|
1570
|
+
window.cordova.plugins.browsertab.close();
|
|
1571
|
+
var oauth = parseCallback(event.url);
|
|
1572
|
+
processCallback(oauth, promise);
|
|
1573
|
+
});
|
|
1574
|
+
window.cordova.plugins.browsertab.openUrl(registerUrl);
|
|
1575
|
+
return promise.promise;
|
|
1576
|
+
|
|
1577
|
+
},
|
|
1578
|
+
|
|
1579
|
+
accountManagement : function() {
|
|
1580
|
+
var accountUrl = kc.createAccountUrl();
|
|
1581
|
+
if (typeof accountUrl !== 'undefined') {
|
|
1582
|
+
window.cordova.plugins.browsertab.openUrl(accountUrl);
|
|
1583
|
+
} else {
|
|
1584
|
+
throw "Not supported by the OIDC server";
|
|
1585
|
+
}
|
|
1586
|
+
},
|
|
1587
|
+
|
|
1588
|
+
redirectUri: function(options) {
|
|
1589
|
+
if (options && options.redirectUri) {
|
|
1590
|
+
return options.redirectUri;
|
|
1591
|
+
} else if (kc.redirectUri) {
|
|
1592
|
+
return kc.redirectUri;
|
|
1593
|
+
} else {
|
|
1594
|
+
return "http://localhost";
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1891
1597
|
}
|
|
1892
|
-
|
|
1893
|
-
return promise.promise;
|
|
1894
|
-
},
|
|
1895
|
-
|
|
1896
|
-
accountManagement: function () {
|
|
1897
|
-
var accountUrl = kc.createAccountUrl();
|
|
1898
|
-
if (typeof accountUrl !== "undefined") {
|
|
1899
|
-
var ref = cordovaOpenWindowWrapper(
|
|
1900
|
-
accountUrl,
|
|
1901
|
-
"_blank",
|
|
1902
|
-
"location=no"
|
|
1903
|
-
);
|
|
1904
|
-
|
|
1905
|
-
ref.addEventListener("loadstart", function (event) {
|
|
1906
|
-
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1907
|
-
ref.close();
|
|
1908
|
-
}
|
|
1909
|
-
});
|
|
1910
|
-
} else {
|
|
1911
|
-
throw "Not supported by the OIDC server";
|
|
1912
|
-
}
|
|
1913
|
-
},
|
|
1914
|
-
|
|
1915
|
-
redirectUri: function (options) {
|
|
1916
|
-
return getCordovaRedirectUri();
|
|
1917
|
-
},
|
|
1918
|
-
};
|
|
1919
|
-
}
|
|
1598
|
+
}
|
|
1920
1599
|
|
|
1921
|
-
|
|
1922
|
-
loginIframe.enable = false;
|
|
1923
|
-
|
|
1924
|
-
return {
|
|
1925
|
-
login: function (options) {
|
|
1926
|
-
var promise = createPromise();
|
|
1927
|
-
var loginUrl = kc.createLoginUrl(options);
|
|
1928
|
-
|
|
1929
|
-
universalLinks.subscribe("keycloak", function (event) {
|
|
1930
|
-
universalLinks.unsubscribe("keycloak");
|
|
1931
|
-
window.cordova.plugins.browsertab.close();
|
|
1932
|
-
var oauth = parseCallback(event.url);
|
|
1933
|
-
processCallback(oauth, promise);
|
|
1934
|
-
});
|
|
1935
|
-
|
|
1936
|
-
window.cordova.plugins.browsertab.openUrl(loginUrl);
|
|
1937
|
-
return promise.promise;
|
|
1938
|
-
},
|
|
1939
|
-
|
|
1940
|
-
logout: function (options) {
|
|
1941
|
-
var promise = createPromise();
|
|
1942
|
-
var logoutUrl = kc.createLogoutUrl(options);
|
|
1943
|
-
|
|
1944
|
-
universalLinks.subscribe("keycloak", function (event) {
|
|
1945
|
-
universalLinks.unsubscribe("keycloak");
|
|
1946
|
-
window.cordova.plugins.browsertab.close();
|
|
1947
|
-
kc.clearToken();
|
|
1948
|
-
promise.setSuccess();
|
|
1949
|
-
});
|
|
1950
|
-
|
|
1951
|
-
window.cordova.plugins.browsertab.openUrl(logoutUrl);
|
|
1952
|
-
return promise.promise;
|
|
1953
|
-
},
|
|
1954
|
-
|
|
1955
|
-
register: function (options) {
|
|
1956
|
-
var promise = createPromise();
|
|
1957
|
-
var registerUrl = kc.createRegisterUrl(options);
|
|
1958
|
-
universalLinks.subscribe("keycloak", function (event) {
|
|
1959
|
-
universalLinks.unsubscribe("keycloak");
|
|
1960
|
-
window.cordova.plugins.browsertab.close();
|
|
1961
|
-
var oauth = parseCallback(event.url);
|
|
1962
|
-
processCallback(oauth, promise);
|
|
1963
|
-
});
|
|
1964
|
-
window.cordova.plugins.browsertab.openUrl(registerUrl);
|
|
1965
|
-
return promise.promise;
|
|
1966
|
-
},
|
|
1967
|
-
|
|
1968
|
-
accountManagement: function () {
|
|
1969
|
-
var accountUrl = kc.createAccountUrl();
|
|
1970
|
-
if (typeof accountUrl !== "undefined") {
|
|
1971
|
-
window.cordova.plugins.browsertab.openUrl(accountUrl);
|
|
1972
|
-
} else {
|
|
1973
|
-
throw "Not supported by the OIDC server";
|
|
1974
|
-
}
|
|
1975
|
-
},
|
|
1976
|
-
|
|
1977
|
-
redirectUri: function (options) {
|
|
1978
|
-
if (options && options.redirectUri) {
|
|
1979
|
-
return options.redirectUri;
|
|
1980
|
-
} else if (kc.redirectUri) {
|
|
1981
|
-
return kc.redirectUri;
|
|
1982
|
-
} else {
|
|
1983
|
-
return "http://localhost";
|
|
1984
|
-
}
|
|
1985
|
-
},
|
|
1986
|
-
};
|
|
1600
|
+
throw 'invalid adapter type: ' + type;
|
|
1987
1601
|
}
|
|
1988
1602
|
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
if (!(this instanceof LocalStorage)) {
|
|
1994
|
-
return new LocalStorage();
|
|
1995
|
-
}
|
|
1603
|
+
var LocalStorage = function() {
|
|
1604
|
+
if (!(this instanceof LocalStorage)) {
|
|
1605
|
+
return new LocalStorage();
|
|
1606
|
+
}
|
|
1996
1607
|
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
1608
|
+
localStorage.setItem('kc-test', 'test');
|
|
1609
|
+
localStorage.removeItem('kc-test');
|
|
1610
|
+
|
|
1611
|
+
var cs = this;
|
|
1612
|
+
|
|
1613
|
+
function clearExpired() {
|
|
1614
|
+
var time = new Date().getTime();
|
|
1615
|
+
for (var i = 0; i < localStorage.length; i++) {
|
|
1616
|
+
var key = localStorage.key(i);
|
|
1617
|
+
if (key && key.indexOf('kc-callback-') == 0) {
|
|
1618
|
+
var value = localStorage.getItem(key);
|
|
1619
|
+
if (value) {
|
|
1620
|
+
try {
|
|
1621
|
+
var expires = JSON.parse(value).expires;
|
|
1622
|
+
if (!expires || expires < time) {
|
|
1623
|
+
localStorage.removeItem(key);
|
|
1624
|
+
}
|
|
1625
|
+
} catch (err) {
|
|
1626
|
+
localStorage.removeItem(key);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
2016
1630
|
}
|
|
2017
|
-
}
|
|
2018
1631
|
}
|
|
2019
|
-
}
|
|
2020
|
-
}
|
|
2021
1632
|
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
1633
|
+
cs.get = function(state) {
|
|
1634
|
+
if (!state) {
|
|
1635
|
+
return;
|
|
1636
|
+
}
|
|
2026
1637
|
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
1638
|
+
var key = 'kc-callback-' + state;
|
|
1639
|
+
var value = localStorage.getItem(key);
|
|
1640
|
+
if (value) {
|
|
1641
|
+
localStorage.removeItem(key);
|
|
1642
|
+
value = JSON.parse(value);
|
|
1643
|
+
}
|
|
2033
1644
|
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
1645
|
+
clearExpired();
|
|
1646
|
+
return value;
|
|
1647
|
+
};
|
|
2037
1648
|
|
|
2038
|
-
|
|
2039
|
-
|
|
1649
|
+
cs.add = function(state) {
|
|
1650
|
+
clearExpired();
|
|
2040
1651
|
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
1652
|
+
var key = 'kc-callback-' + state.state;
|
|
1653
|
+
state.expires = new Date().getTime() + (60 * 60 * 1000);
|
|
1654
|
+
localStorage.setItem(key, JSON.stringify(state));
|
|
1655
|
+
};
|
|
2044
1656
|
};
|
|
2045
|
-
};
|
|
2046
1657
|
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
1658
|
+
var CookieStorage = function() {
|
|
1659
|
+
if (!(this instanceof CookieStorage)) {
|
|
1660
|
+
return new CookieStorage();
|
|
1661
|
+
}
|
|
2051
1662
|
|
|
2052
|
-
|
|
1663
|
+
var cs = this;
|
|
2053
1664
|
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
1665
|
+
cs.get = function(state) {
|
|
1666
|
+
if (!state) {
|
|
1667
|
+
return;
|
|
1668
|
+
}
|
|
2058
1669
|
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
1670
|
+
var value = getCookie('kc-callback-' + state);
|
|
1671
|
+
setCookie('kc-callback-' + state, '', cookieExpiration(-100));
|
|
1672
|
+
if (value) {
|
|
1673
|
+
return JSON.parse(value);
|
|
1674
|
+
}
|
|
1675
|
+
};
|
|
2065
1676
|
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
JSON.stringify(state),
|
|
2070
|
-
cookieExpiration(60)
|
|
2071
|
-
);
|
|
2072
|
-
};
|
|
1677
|
+
cs.add = function(state) {
|
|
1678
|
+
setCookie('kc-callback-' + state.state, JSON.stringify(state), cookieExpiration(60));
|
|
1679
|
+
};
|
|
2073
1680
|
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
1681
|
+
cs.removeItem = function(key) {
|
|
1682
|
+
setCookie(key, '', cookieExpiration(-100));
|
|
1683
|
+
};
|
|
2077
1684
|
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
1685
|
+
var cookieExpiration = function (minutes) {
|
|
1686
|
+
var exp = new Date();
|
|
1687
|
+
exp.setTime(exp.getTime() + (minutes*60*1000));
|
|
1688
|
+
return exp;
|
|
1689
|
+
};
|
|
2083
1690
|
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
1691
|
+
var getCookie = function (key) {
|
|
1692
|
+
var name = key + '=';
|
|
1693
|
+
var ca = document.cookie.split(';');
|
|
1694
|
+
for (var i = 0; i < ca.length; i++) {
|
|
1695
|
+
var c = ca[i];
|
|
1696
|
+
while (c.charAt(0) == ' ') {
|
|
1697
|
+
c = c.substring(1);
|
|
1698
|
+
}
|
|
1699
|
+
if (c.indexOf(name) == 0) {
|
|
1700
|
+
return c.substring(name.length, c.length);
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
return '';
|
|
1704
|
+
};
|
|
2098
1705
|
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
"; " +
|
|
2105
|
-
"expires=" +
|
|
2106
|
-
expirationDate.toUTCString() +
|
|
2107
|
-
"; ";
|
|
2108
|
-
|
|
2109
|
-
document.cookie = cookie;
|
|
1706
|
+
var setCookie = function (key, value, expirationDate) {
|
|
1707
|
+
var cookie = key + '=' + value + '; '
|
|
1708
|
+
+ 'expires=' + expirationDate.toUTCString() + '; ';
|
|
1709
|
+
document.cookie = cookie;
|
|
1710
|
+
}
|
|
2110
1711
|
};
|
|
2111
|
-
};
|
|
2112
1712
|
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
1713
|
+
function createCallbackStorage() {
|
|
1714
|
+
try {
|
|
1715
|
+
return new LocalStorage();
|
|
1716
|
+
} catch (err) {
|
|
1717
|
+
}
|
|
2117
1718
|
|
|
2118
|
-
|
|
2119
|
-
|
|
1719
|
+
return new CookieStorage();
|
|
1720
|
+
}
|
|
2120
1721
|
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
1722
|
+
function createLogger(fn) {
|
|
1723
|
+
return function() {
|
|
1724
|
+
if (kc.enableLogging) {
|
|
1725
|
+
fn.apply(console, Array.prototype.slice.call(arguments));
|
|
1726
|
+
}
|
|
1727
|
+
};
|
|
1728
|
+
}
|
|
2128
1729
|
}
|
|
2129
1730
|
|
|
2130
|
-
export default Keycloak;
|
|
2131
|
-
|
|
2132
|
-
// See: https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem
|
|
2133
|
-
function bytesToBase64(bytes) {
|
|
2134
|
-
const binString = String.fromCodePoint(...bytes);
|
|
2135
|
-
return btoa(binString);
|
|
2136
|
-
}
|
|
1731
|
+
export default Keycloak;
|