@tapni/auth 0.0.169 → 0.0.171
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/README.md +2 -0
- package/dist/.vite/manifest.json +18 -10
- package/dist/.well-known/assetlinks.json +10 -12
- package/dist/.well-known/microsoft-identity-association.json +5 -5
- package/dist/{Account-ja1hZJy5.js → Account-BB71UmF3.js} +31 -32
- package/dist/{QR-ybXT1KGe.js → QR-BJnR_0ci.js} +3 -3
- package/dist/TapniAuth.es.js +1 -1
- package/dist/TapniAuth.umd.js +9 -9
- package/dist/blank.html +31 -0
- package/dist/{install-4aK3Wz63.js → install-Cx9Gi17U.js} +753 -997
- package/dist/site.webmanifest +11 -1
- package/dist/style.css +1 -1
- package/dist/{web-NrPZl3qD.js → web-XbruGdlD.js} +2 -5
- package/package.json +64 -55
- package/src/.prettierrc.json +16 -0
- package/src/App.vue +249 -265
- package/src/components/Language.vue +66 -143
- package/src/components/LinkIcon.vue +174 -225
- package/src/components/ModalOverlay.vue +47 -50
- package/src/components/OTP.vue +64 -94
- package/src/components/SSO.vue +80 -111
- package/src/components/SSOPick.vue +93 -148
- package/src/eslint.config.js +15 -0
- package/src/install.js +9 -10
- package/src/main.js +54 -57
- package/src/mixins/apple.mixin.js +56 -54
- package/src/mixins/auth.mixin.js +21 -74
- package/src/mixins/facebook.mixin.js +67 -66
- package/src/mixins/global.mixin.js +107 -109
- package/src/mixins/google.mixin.js +53 -54
- package/src/mixins/mfa-auth.mixin.js +68 -68
- package/src/mixins/microsoft.mixin.js +67 -75
- package/src/mixins/okta.mixin.js +50 -57
- package/src/mixins/qr-auth.mixin.js +111 -107
- package/src/mixins/saml.mixin.js +97 -48
- package/src/router/index.js +6 -6
- package/src/routes.js +60 -66
- package/src/services/Api.js +55 -57
- package/src/services/AuthService.js +75 -75
- package/src/services/CompanyService.js +10 -10
- package/src/services/DeviceService.js +3 -3
- package/src/services/UserService.js +45 -45
- package/src/services/UtilService.js +256 -218
- package/src/store/auth.js +471 -543
- package/src/store/constants.js +1 -1
- package/src/store/event-bus.js +22 -22
- package/src/store/locales/cn.js +442 -458
- package/src/store/locales/de.js +438 -517
- package/src/store/locales/en.js +449 -510
- package/src/store/locales/es.js +442 -524
- package/src/store/locales/fr.js +442 -516
- package/src/store/locales/it.js +442 -514
- package/src/store/locales/kr.js +442 -491
- package/src/store/locales/lang.js +43 -43
- package/src/store/locales/sr.js +439 -492
- package/src/store/locales/tr.js +436 -487
- package/src/store/store.js +6 -6
- package/src/views/Account.vue +169 -207
- package/src/views/Callback.vue +36 -33
- package/src/views/Login.vue +220 -392
- package/src/views/MFA.vue +89 -103
- package/src/views/QR.vue +25 -28
- package/src/views/Register.vue +201 -205
- package/src/views/Reset.vue +132 -135
- package/src/views/Verify.vue +153 -151
- package/src/views/Welcome.vue +61 -60
- /package/dist/{web-L3jORB19.js → web-AXRKjAOB.js} +0 -0
- /package/dist/{web-5VtGcKeU.js → web-IFGkBi0t.js} +0 -0
- /package/dist/{web-AImUTDQQ.js → web-LIfHmYL2.js} +0 -0
package/src/mixins/okta.mixin.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import to from 'await-to-js'
|
|
2
|
-
import AuthService from '../services/AuthService'
|
|
3
|
-
import UtilService from '../services/UtilService'
|
|
4
|
-
import { EventBus } from
|
|
1
|
+
import to from 'await-to-js';
|
|
2
|
+
import AuthService from '../services/AuthService';
|
|
3
|
+
import UtilService from '../services/UtilService';
|
|
4
|
+
import { EventBus } from '../store/event-bus';
|
|
5
5
|
import { Capacitor } from '@capacitor/core';
|
|
6
6
|
import axios from 'axios';
|
|
7
7
|
import { Browser } from '@capacitor/browser';
|
|
@@ -9,13 +9,12 @@ import { Browser } from '@capacitor/browser';
|
|
|
9
9
|
// this tutorial was used for plain okta javascript implementation
|
|
10
10
|
// https://developer.okta.com/blog/2019/05/01/is-the-oauth-implicit-flow-dead
|
|
11
11
|
export default {
|
|
12
|
-
data
|
|
12
|
+
data() {
|
|
13
13
|
return {
|
|
14
|
-
oktaAuth: null
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
computed: {
|
|
14
|
+
oktaAuth: null
|
|
15
|
+
};
|
|
18
16
|
},
|
|
17
|
+
computed: {},
|
|
19
18
|
watch: {
|
|
20
19
|
/*
|
|
21
20
|
'$route.path': async function(routePath) {
|
|
@@ -24,48 +23,45 @@ export default {
|
|
|
24
23
|
*/
|
|
25
24
|
},
|
|
26
25
|
methods: {
|
|
27
|
-
async exchangeCode
|
|
28
|
-
let [err, response] = await to(axios.post(data.domain
|
|
26
|
+
async exchangeCode(data) {
|
|
27
|
+
let [err, response] = await to(axios.post(data.domain + '/v1/token', new URLSearchParams({ code: data.code, client_id: data.clientID, grant_type: 'authorization_code', redirect_uri: this.isNative ? 'tapni://t.link/callback/okta' : location.origin + '/callback/okta', code_verifier: localStorage.getItem('pkce_code_verifier') })));
|
|
29
28
|
if (err) return this.errorHandler(err);
|
|
30
|
-
localStorage.removeItem(
|
|
29
|
+
localStorage.removeItem('pkce_code_verifier');
|
|
31
30
|
|
|
32
|
-
let user = {accessToken: response.data?.access_token, domain: data.domain}
|
|
31
|
+
let user = { accessToken: response.data?.access_token, domain: data.domain };
|
|
33
32
|
if (this.display === 'popup') user.response_type = 'code';
|
|
34
33
|
|
|
35
34
|
[err, response] = await to(AuthService.oktaSDK(user, this.$storex));
|
|
36
35
|
if (err) {
|
|
37
|
-
this.oktaLoad = false
|
|
38
|
-
EventBus.$emit('ssoEvent', {name: 'setLoading', data: false})
|
|
39
|
-
return this.errorHandler(err)
|
|
36
|
+
this.oktaLoad = false;
|
|
37
|
+
EventBus.$emit('ssoEvent', { name: 'setLoading', data: false });
|
|
38
|
+
return this.errorHandler(err);
|
|
40
39
|
}
|
|
41
40
|
if (response.data.success) {
|
|
42
41
|
if (this.display === 'popup') {
|
|
43
42
|
return window.parent?.postMessage({ code: response.data.auth_code, state: this.$route.query.state }, '*');
|
|
44
43
|
}
|
|
45
|
-
await this.loginSetup(response)
|
|
46
|
-
await this.getLoggedInAccounts()
|
|
47
|
-
this.$router.push('/' + response.data.data.username + '#edit')
|
|
44
|
+
await this.loginSetup(response);
|
|
45
|
+
await this.getLoggedInAccounts();
|
|
46
|
+
this.$router.push('/' + response.data.data.username + '#edit');
|
|
48
47
|
setTimeout(() => {
|
|
49
|
-
this.appleLoad = false
|
|
50
|
-
EventBus.$emit('ssoEvent', {name: 'setLoading', data: false})
|
|
51
|
-
}, 1000)
|
|
52
|
-
} else this.errorSnack(this.ssoLang[this.appLanguage].unexpected_err)
|
|
48
|
+
this.appleLoad = false;
|
|
49
|
+
EventBus.$emit('ssoEvent', { name: 'setLoading', data: false });
|
|
50
|
+
}, 1000);
|
|
51
|
+
} else this.errorSnack(this.ssoLang[this.appLanguage].unexpected_err);
|
|
53
52
|
},
|
|
54
|
-
async oktaLogin
|
|
55
|
-
const platform =
|
|
53
|
+
async oktaLogin(data) {
|
|
54
|
+
const platform = Capacitor.getPlatform() || 'web';
|
|
56
55
|
//const state = btoa(`email=${email}&platform=${platform}`);
|
|
57
56
|
//const state = btoa(`platform=${platform}`);
|
|
58
57
|
|
|
59
58
|
// Create and store a random "state" value
|
|
60
59
|
//localStorage.setItem("pkce_state", state);
|
|
61
|
-
let state = btoa(
|
|
62
|
-
+ "&client_id="+data.clientID
|
|
63
|
-
+ "&platform="+platform
|
|
64
|
-
+ "&rand="+UtilService.generateRandomString(28));
|
|
60
|
+
let state = btoa('domain=' + data.domain + '&client_id=' + data.clientID + '&platform=' + platform + '&rand=' + UtilService.generateRandomString(28));
|
|
65
61
|
|
|
66
62
|
// Create and store a new PKCE code_verifier (the plaintext random secret)
|
|
67
63
|
let code_verifier = UtilService.generateRandomString(28);
|
|
68
|
-
localStorage.setItem(
|
|
64
|
+
localStorage.setItem('pkce_code_verifier', code_verifier);
|
|
69
65
|
|
|
70
66
|
// Hash and base64-urlencode the secret to use as the challenge
|
|
71
67
|
let code_challenge = await UtilService.pkceChallengeFromVerifier(code_verifier);
|
|
@@ -76,30 +72,27 @@ export default {
|
|
|
76
72
|
if (this.isNative) redirectURI = 'tapni://t.link/callback/okta';
|
|
77
73
|
else redirectURI = location.origin + '/callback/okta';
|
|
78
74
|
|
|
79
|
-
let url = authorization_endpoint
|
|
80
|
-
+ "?response_type=code"
|
|
81
|
-
+ "&client_id="+encodeURIComponent(data.clientID)
|
|
82
|
-
+ "&state="+encodeURIComponent(state)
|
|
83
|
-
+ "&scope="+encodeURIComponent('openid email profile')
|
|
84
|
-
+ "&redirect_uri="+encodeURIComponent(redirectURI)
|
|
85
|
-
+ "&code_challenge="+encodeURIComponent(code_challenge)
|
|
86
|
-
+ "&code_challenge_method=S256";
|
|
75
|
+
let url = authorization_endpoint + '?response_type=code' + '&client_id=' + encodeURIComponent(data.clientID) + '&state=' + encodeURIComponent(state) + '&scope=' + encodeURIComponent('openid email profile') + '&redirect_uri=' + encodeURIComponent(redirectURI) + '&code_challenge=' + encodeURIComponent(code_challenge) + '&code_challenge_method=S256';
|
|
87
76
|
|
|
88
77
|
let self = this;
|
|
89
78
|
//if (response && response.data && response.data.url) {
|
|
90
79
|
let code;
|
|
91
|
-
window.addEventListener(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
80
|
+
window.addEventListener(
|
|
81
|
+
'message',
|
|
82
|
+
async (message) => {
|
|
83
|
+
if (!this.allowedOriginsAuth.includes(message.origin)) return console.log('Origin is not allowed!');
|
|
84
|
+
if (message.data.type === 'okta') {
|
|
85
|
+
code = message.data.code;
|
|
86
|
+
await self.exchangeCode({ domain: data.domain, code, clientID: data.clientID });
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{ once: true }
|
|
90
|
+
);
|
|
98
91
|
|
|
99
92
|
let popupWindow;
|
|
100
|
-
if(this.isNative) {
|
|
101
|
-
popupWindow = await Browser.open({ url, presentationStyle: 'popover'});
|
|
102
|
-
} else popupWindow = window.open(url, 'popup','width=600,height=600')
|
|
93
|
+
if (this.isNative) {
|
|
94
|
+
popupWindow = await Browser.open({ url, presentationStyle: 'popover' });
|
|
95
|
+
} else popupWindow = window.open(url, 'popup', 'width=600,height=600');
|
|
103
96
|
},
|
|
104
97
|
async handleOktaRedirect() {
|
|
105
98
|
let code = this.$route.query.code;
|
|
@@ -107,7 +100,7 @@ export default {
|
|
|
107
100
|
let clientID;
|
|
108
101
|
let domain;
|
|
109
102
|
let platform;
|
|
110
|
-
let postMessageData = {type: 'okta'}
|
|
103
|
+
let postMessageData = { type: 'okta' };
|
|
111
104
|
if (code) postMessageData.code = code;
|
|
112
105
|
if (this.$route.query.state) {
|
|
113
106
|
state = this.$route.query.state;
|
|
@@ -117,16 +110,16 @@ export default {
|
|
|
117
110
|
domain = searchParams.get('domain');
|
|
118
111
|
platform = searchParams.get('platform');
|
|
119
112
|
}
|
|
120
|
-
if(window.opener) {
|
|
113
|
+
if (window.opener) {
|
|
121
114
|
window.opener.postMessage(postMessageData, location.origin);
|
|
122
|
-
window.close()
|
|
115
|
+
window.close();
|
|
123
116
|
} else {
|
|
124
|
-
if(this.isNative && this.
|
|
125
|
-
EventBus.$emit('ssoEvent', {name: 'setLoading', data: true})
|
|
126
|
-
if (code && clientID && domain) await this.exchangeCode({code, clientID, domain, platform});
|
|
127
|
-
localStorage.removeItem(
|
|
128
|
-
EventBus.$emit('ssoEvent', {name: 'setLoading', data: false})
|
|
117
|
+
if (this.isNative && this.isiOS) await Browser.close();
|
|
118
|
+
EventBus.$emit('ssoEvent', { name: 'setLoading', data: true });
|
|
119
|
+
if (code && clientID && domain) await this.exchangeCode({ code, clientID, domain, platform });
|
|
120
|
+
localStorage.removeItem('pkce_code_verifier');
|
|
121
|
+
EventBus.$emit('ssoEvent', { name: 'setLoading', data: false });
|
|
129
122
|
}
|
|
130
123
|
}
|
|
131
124
|
}
|
|
132
|
-
}
|
|
125
|
+
};
|
|
@@ -1,117 +1,121 @@
|
|
|
1
|
-
import to from 'await-to-js'
|
|
2
|
-
import CompanyService from '../services/CompanyService'
|
|
3
|
-
import {nextTick} from
|
|
4
|
-
import QRCodeStyling from
|
|
1
|
+
import to from 'await-to-js';
|
|
2
|
+
import CompanyService from '../services/CompanyService';
|
|
3
|
+
import { nextTick } from 'vue';
|
|
4
|
+
import QRCodeStyling from 'qr-code-styling';
|
|
5
5
|
|
|
6
6
|
export default {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
let result = "";
|
|
7
|
+
data() {
|
|
8
|
+
return {
|
|
9
|
+
isQrCodeLogin: false,
|
|
10
|
+
qrCode: null,
|
|
11
|
+
qrCodeHash: null,
|
|
12
|
+
qrCodeRefreshInterval: null,
|
|
13
|
+
poolingInterval: null
|
|
14
|
+
};
|
|
15
|
+
},
|
|
16
|
+
props: {
|
|
17
|
+
isModal: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
required: false,
|
|
20
|
+
default: false
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
computed: {
|
|
24
|
+
displayQRLogin() {
|
|
25
|
+
return this.$route.name === 'AuthLogin' && this.display !== 'npm';
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
mounted() {
|
|
29
|
+
if (this.$route.name === 'AuthQR') this.changeLoginToQr();
|
|
30
|
+
},
|
|
31
|
+
methods: {
|
|
32
|
+
async changeLoginToQr() {
|
|
33
|
+
this.isQrCodeLogin = true;
|
|
34
|
+
await nextTick();
|
|
35
|
+
await this.initQrCodeLogin();
|
|
36
|
+
},
|
|
37
|
+
generateRandomHash() {
|
|
38
|
+
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
39
|
+
const charactersLength = characters.length;
|
|
40
|
+
let result = '';
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
// Create an array of 32-bit unsigned integers
|
|
43
|
+
const randomValues = new Uint32Array(32);
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
// Generate random values
|
|
46
|
+
window.crypto.getRandomValues(randomValues);
|
|
47
|
+
randomValues.forEach((value) => {
|
|
48
|
+
result += characters.charAt(value % charactersLength);
|
|
49
|
+
});
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
return result;
|
|
52
|
+
},
|
|
53
|
+
refreshQrCode() {
|
|
54
|
+
if (this.qrCode) {
|
|
55
|
+
document.getElementById('qrCodeContainer')?.childNodes[0]?.remove();
|
|
56
|
+
}
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
this.qrCodeHash = this.generateRandomHash();
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
60
|
+
this.qrCode = new QRCodeStyling({
|
|
61
|
+
width: 300,
|
|
62
|
+
height: 300,
|
|
63
|
+
type: 'png',
|
|
64
|
+
image: '',
|
|
65
|
+
imageOptions: {
|
|
66
|
+
margin: 15
|
|
67
|
+
},
|
|
68
|
+
data: this.qrCodeHash,
|
|
69
|
+
dotsOptions: {
|
|
70
|
+
type: 'extra-rounded',
|
|
71
|
+
color: '#000000'
|
|
72
|
+
},
|
|
73
|
+
cornersSquareOptions: {
|
|
74
|
+
type: 'extra-rounded',
|
|
75
|
+
color: '#000000'
|
|
76
|
+
},
|
|
77
|
+
cornersDotOptions: {
|
|
78
|
+
type: '',
|
|
79
|
+
color: '#000000'
|
|
80
|
+
},
|
|
81
|
+
backgroundOptions: {
|
|
82
|
+
color: '#ffffff00'
|
|
83
|
+
}
|
|
84
|
+
});
|
|
86
85
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
86
|
+
this.qrCode.append(document.getElementById('qrCodeContainer'));
|
|
87
|
+
},
|
|
88
|
+
async startQrCodePooling() {
|
|
89
|
+
this.poolingInterval = setInterval(async () => {
|
|
90
|
+
const [err, response] = await to(
|
|
91
|
+
CompanyService.qrCodePooling(
|
|
92
|
+
{
|
|
93
|
+
qrToken: this.qrCodeHash
|
|
94
|
+
},
|
|
95
|
+
this.$storex
|
|
96
|
+
)
|
|
97
|
+
);
|
|
98
|
+
if (err) return this.errorHandler(err);
|
|
99
|
+
if (response.data.auth_code) {
|
|
100
|
+
if (this.display !== 'popup') {
|
|
101
|
+
this.loginSetup({ ...response, isModal: this.isModal });
|
|
102
|
+
await this.getLoggedInAccounts();
|
|
103
|
+
}
|
|
100
104
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
this.loginSuccess({ ...response, isModal: this.isModal });
|
|
106
|
+
clearInterval(this.poolingInterval);
|
|
107
|
+
clearInterval(this.qrCodeRefreshInterval);
|
|
108
|
+
}
|
|
109
|
+
}, 2000);
|
|
110
|
+
},
|
|
107
111
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
112
|
+
async initQrCodeLogin() {
|
|
113
|
+
this.refreshQrCode();
|
|
114
|
+
await nextTick();
|
|
115
|
+
await this.startQrCodePooling();
|
|
116
|
+
this.qrCodeRefreshInterval = setInterval(() => {
|
|
117
|
+
this.refreshQrCode();
|
|
118
|
+
}, 60000);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
};
|
package/src/mixins/saml.mixin.js
CHANGED
|
@@ -1,29 +1,37 @@
|
|
|
1
1
|
import { Browser } from '@capacitor/browser';
|
|
2
2
|
import UtilService from '@/services/UtilService';
|
|
3
|
-
import { Capacitor } from
|
|
3
|
+
import { Capacitor } from '@capacitor/core';
|
|
4
4
|
import { EventBus } from '@/store/event-bus.js';
|
|
5
5
|
export default {
|
|
6
|
-
data
|
|
6
|
+
data() {
|
|
7
7
|
return {
|
|
8
8
|
code_verifier: '',
|
|
9
|
-
code_challenge: ''
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
code_challenge: '',
|
|
10
|
+
shouldCloseWindow: false,
|
|
11
|
+
popupWindow: null,
|
|
12
|
+
checkInterval: null
|
|
13
|
+
};
|
|
13
14
|
},
|
|
15
|
+
computed: {},
|
|
14
16
|
watch: {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
'$route.path' (nv) {
|
|
18
|
+
if (nv === '/callback/saml') {
|
|
19
|
+
this.handleSamlRedirect(nv)
|
|
20
|
+
}
|
|
18
21
|
}
|
|
19
|
-
*/
|
|
20
22
|
},
|
|
21
23
|
methods: {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
closeWindow() {
|
|
25
|
+
try {
|
|
26
|
+
window.close()
|
|
27
|
+
} catch (e) {
|
|
28
|
+
console.log('Window close error', e);
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
async samlLogin(loginUrl) {
|
|
24
32
|
// Create and store a new PKCE code_verifier (the plaintext random secret)
|
|
25
33
|
this.code_verifier = UtilService.generateRandomString(28);
|
|
26
|
-
localStorage.setItem(
|
|
34
|
+
localStorage.setItem('pkce_code_verifier', this.code_verifier);
|
|
27
35
|
|
|
28
36
|
// Hash and base64-urlencode the secret to use as the challenge
|
|
29
37
|
this.code_challenge = await UtilService.pkceChallengeFromVerifier(this.code_verifier);
|
|
@@ -31,58 +39,99 @@ export default {
|
|
|
31
39
|
const platform = Capacitor.getPlatform();
|
|
32
40
|
|
|
33
41
|
// append public key as relayState
|
|
34
|
-
let dataString = `code_challenge=${this.code_challenge}&platform=${platform}&redirect_uri=${
|
|
42
|
+
let dataString = `code_challenge=${this.code_challenge}&platform=${platform}&redirect_uri=${location.origin + '/callback/saml'}&realm=${this.realm}&display=${this.display}`;
|
|
35
43
|
let relayState = btoa(dataString);
|
|
36
44
|
|
|
37
|
-
loginUrl = `${loginUrl}&RelayState=${relayState}
|
|
45
|
+
loginUrl = `${loginUrl}&RelayState=${relayState}`;
|
|
38
46
|
|
|
39
47
|
let self = this;
|
|
40
48
|
|
|
41
|
-
window.addEventListener(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (this.
|
|
45
|
-
|
|
49
|
+
window.addEventListener(
|
|
50
|
+
'message',
|
|
51
|
+
async (message) => {
|
|
52
|
+
if (!this.allowedOriginsAuth.includes(message.origin)) return console.log('Origin is not allowed!');
|
|
53
|
+
if (message.data.code) {
|
|
54
|
+
console.log('post message from opener', message.data, self.display);
|
|
55
|
+
|
|
56
|
+
if (self.display === 'popup') {
|
|
57
|
+
return window.parent?.postMessage({ code: message.data.code, state: message.data.state, code_verifier: localStorage.getItem('pkce_code_verifier') }, '*');
|
|
58
|
+
}
|
|
59
|
+
await self.exchangeAuthCode({ code: message.data.code, code_verifier: localStorage.getItem('pkce_code_verifier') });
|
|
60
|
+
localStorage.removeItem('pkce_code_verifier');
|
|
46
61
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
62
|
+
},
|
|
63
|
+
{ once: true }
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
if (this.isNative) {
|
|
67
|
+
this.popupWindow = await Browser.open({ url: loginUrl, presentationStyle: 'popover' });
|
|
68
|
+
} else {
|
|
69
|
+
this.checkInterval = setInterval(() => {
|
|
70
|
+
// check localStorage
|
|
71
|
+
const code = localStorage.getItem('auth_code');
|
|
72
|
+
const pkce = localStorage.getItem('pkce_code_verifier');
|
|
51
73
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
74
|
+
console.log('interval', code, pkce);
|
|
75
|
+
|
|
76
|
+
if (code) {
|
|
77
|
+
clearInterval(this.checkInterval);
|
|
78
|
+
localStorage.removeItem('auth_code');
|
|
79
|
+
localStorage.removeItem('pkce_code_verifier');
|
|
80
|
+
|
|
81
|
+
// handle code exchange
|
|
82
|
+
window.parent?.postMessage({ code: code, state: this.$route.query.state, code_verifier: pkce }, '*');
|
|
83
|
+
|
|
84
|
+
// attempt to close child if possible
|
|
85
|
+
// if (this.popupWindow?.closed === false) this.popupWindow.close();
|
|
86
|
+
}
|
|
87
|
+
}, 500);
|
|
88
|
+
|
|
89
|
+
this.popupWindow = window.open('https://auth.tapni.com/callback/redirect?uri=' + btoa(loginUrl), 'popup', 'width=600,height=600');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (this.popupWindow) {
|
|
93
|
+
this.popupWindow.addEventListener('beforeunload', () => {
|
|
94
|
+
console.log('popup window closed');
|
|
95
|
+
})
|
|
55
96
|
}
|
|
56
|
-
|
|
57
|
-
/*
|
|
58
|
-
popupWindow.addEventListener('beforeunload', () => {
|
|
59
|
-
console.log('window closed')
|
|
60
|
-
})
|
|
61
|
-
*/
|
|
97
|
+
|
|
62
98
|
},
|
|
63
99
|
async handleSamlRedirect() {
|
|
64
100
|
let code;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
101
|
+
if (this.$route.query.code) {
|
|
102
|
+
code = this.$route.query.code
|
|
103
|
+
}
|
|
104
|
+
console.log('window1', window.opener);
|
|
105
|
+
console.log('window2', window.parent);
|
|
106
|
+
if (window.opener) {
|
|
107
|
+
window.opener.postMessage({ type: 'saml', code }, '*');
|
|
108
|
+
this.closeWindow();
|
|
70
109
|
} else {
|
|
71
|
-
if(this.isNative && this.
|
|
72
|
-
EventBus.$emit('ssoEvent', {name: 'setLoading', data: true})
|
|
73
|
-
if (this.$route.query.code) code = this.$route.query.code
|
|
110
|
+
if (this.isNative && this.isiOS) await Browser.close();
|
|
111
|
+
EventBus.$emit('ssoEvent', { name: 'setLoading', data: true });
|
|
74
112
|
|
|
75
|
-
console.log(this.display, {code});
|
|
113
|
+
console.log(this.display, { code }, window.parent, window.opener);
|
|
76
114
|
|
|
77
115
|
if (code) {
|
|
78
116
|
if (this.display === 'popup') {
|
|
79
|
-
|
|
117
|
+
localStorage.setItem('auth_code', code);
|
|
118
|
+
this.shouldCloseWindow = true;
|
|
119
|
+
window.parent?.postMessage({ code: code, state: this.$route.query.state }, '*');
|
|
120
|
+
this.closeWindow()
|
|
121
|
+
}
|
|
122
|
+
// TODO: Replace URLs with .env variables to support staging
|
|
123
|
+
if (this.display === 'redirect' || location.host === 'auth.tapni.com') {
|
|
124
|
+
let redirect_url = 'https://auth.tapni.com/callback/auth';
|
|
125
|
+
if (this.realm === 'dashboard') {
|
|
126
|
+
redirect_url = 'https://business.tapni.com/login'
|
|
127
|
+
}
|
|
128
|
+
return location.href = redirect_url + '?code=' + code + '&code_verifier=' + localStorage.getItem('pkce_code_verifier');
|
|
80
129
|
}
|
|
81
|
-
await this.exchangeAuthCode({code, code_verifier: localStorage.getItem(
|
|
130
|
+
await this.exchangeAuthCode({ code, code_verifier: localStorage.getItem('pkce_code_verifier') });
|
|
82
131
|
}
|
|
83
|
-
localStorage.removeItem(
|
|
84
|
-
EventBus.$emit('ssoEvent', {name: 'setLoading', data: false})
|
|
132
|
+
// localStorage.removeItem('pkce_code_verifier');
|
|
133
|
+
EventBus.$emit('ssoEvent', { name: 'setLoading', data: false });
|
|
85
134
|
}
|
|
86
135
|
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
136
|
+
}
|
|
137
|
+
};
|
package/src/router/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createRouter, createWebHistory } from 'vue-router'
|
|
2
|
-
import routes from '../routes.js'
|
|
1
|
+
import { createRouter, createWebHistory } from 'vue-router';
|
|
2
|
+
import routes from '../routes.js';
|
|
3
3
|
|
|
4
4
|
const router = createRouter({
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
})
|
|
5
|
+
history: createWebHistory(import.meta.env.BASE_URL),
|
|
6
|
+
routes
|
|
7
|
+
});
|
|
8
8
|
|
|
9
|
-
export default router
|
|
9
|
+
export default router;
|