@nsshunt/stsoauth2plugin 0.1.96 → 0.1.99
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/Utils/CryptoUtils.js +32 -30
- package/dist/Utils/CryptoUtils.js.map +1 -1
- package/dist/Utils/QueryParams.js +43 -43
- package/dist/Utils/QueryParams.js.map +1 -1
- package/dist/index.js +27 -11
- package/dist/index.js.map +1 -1
- package/dist/stores/stsoauth2store.js +10 -4
- package/dist/stores/stsoauth2store.js.map +1 -1
- package/dist/stores/testStore.js +5 -2
- package/dist/stores/testStore.js.map +1 -1
- package/dist/stsStorage.js +125 -117
- package/dist/stsStorage.js.map +1 -1
- package/dist/stsoauth2launcher.js +4 -2
- package/dist/stsoauth2launcher.js.map +1 -1
- package/dist/stsoauth2manager.js +289 -302
- package/dist/stsoauth2manager.js.map +1 -1
- package/dist/stsoauth2types.js +11 -8
- package/dist/stsoauth2types.js.map +1 -1
- package/dist/stsoauth2worker.js +471 -532
- package/dist/stsoauth2worker.js.map +1 -1
- package/package.json +1 -1
- package/types/index.d.ts +4 -0
- package/types/index.d.ts.map +1 -1
package/dist/stsoauth2worker.js
CHANGED
|
@@ -1,27 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
4
|
};
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
};
|
|
12
|
-
var _STSOAuth2Worker_clientSessionStore, _STSOAuth2Worker_cUtils, _STSOAuth2Worker_qParams, _STSOAuth2Worker_STORAGE_SESSION_KEY, _STSOAuth2Worker_aic, _STSOAuth2Worker_oauthWorkerPort, _STSOAuth2Worker_options, _STSOAuth2Worker_HandleAuthenticateEvent, _STSOAuth2Worker_HandleErrorEvent, _STSOAuth2Worker_LogMessage, _STSOAuth2Worker_GetAccessToken, _STSOAuth2Worker_UpdateInstrument, _STSOAuth2Worker_ProcessCommand, _STSOAuth2Worker_RestoreSession, _STSOAuth2Worker_Authorize, _STSOAuth2Worker_HandleRedirect, _STSOAuth2Worker_GetTokenFromBroker, _STSOAuth2Worker_GetToken, _STSOAuth2Worker_RefreshToken, _STSOAuth2Worker_Logout;
|
|
13
|
-
import Debug from "debug";
|
|
14
|
-
const debug = Debug(`proc:${process.pid}:stsoauth2worker.ts`);
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.STSOAuth2Worker = void 0;
|
|
7
|
+
const debug_1 = __importDefault(require("debug"));
|
|
8
|
+
const debug = (0, debug_1.default)(`proc:${process.pid}:stsoauth2worker.ts`);
|
|
15
9
|
//import 'colors'
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
10
|
+
const axios_1 = __importDefault(require("axios"));
|
|
11
|
+
const stsutils_1 = require("@nsshunt/stsutils");
|
|
12
|
+
const CryptoUtils_1 = __importDefault(require("./Utils/CryptoUtils"));
|
|
13
|
+
const QueryParams_1 = __importDefault(require("./Utils/QueryParams"));
|
|
14
|
+
const jwt_decode_1 = __importDefault(require("jwt-decode"));
|
|
15
|
+
const stsStorage_1 = require("./stsStorage");
|
|
16
|
+
const http_status_codes_1 = require("http-status-codes");
|
|
17
|
+
const stsoauth2types_1 = require("./stsoauth2types");
|
|
18
|
+
const stsinstrumentation_1 = require("@nsshunt/stsinstrumentation");
|
|
25
19
|
const CreateRandomString = (size = 43) => {
|
|
26
20
|
const randomValues = Array.from(self.crypto.getRandomValues(new Uint8Array(size)));
|
|
27
21
|
const b64 = window.btoa(String.fromCharCode(...randomValues));
|
|
@@ -29,555 +23,500 @@ const CreateRandomString = (size = 43) => {
|
|
|
29
23
|
//return randomValues.toString('base64');
|
|
30
24
|
};
|
|
31
25
|
// STS Client SDK for SPAs
|
|
32
|
-
|
|
26
|
+
class STSOAuth2Worker {
|
|
27
|
+
//#storageManager = null;
|
|
28
|
+
#clientSessionStore = null; // In memory tokens while the client is logged in
|
|
29
|
+
#cUtils = new CryptoUtils_1.default();
|
|
30
|
+
#qParams = new QueryParams_1.default();
|
|
31
|
+
#STORAGE_SESSION_KEY = 'session.stsmda.com.au';
|
|
32
|
+
#aic = null;
|
|
33
|
+
#oauthWorkerPort = null;
|
|
34
|
+
#options = null;
|
|
33
35
|
constructor(workerPort, options) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
{ parameterType: OAuth2ParameterType.REDIRECT_URI, errorType: authErrorType.REDIRECT_URI_MISMATCH },
|
|
47
|
-
{ parameterType: OAuth2ParameterType.AUDIENCE, errorType: authErrorType.SCOPE_MISMATCH }
|
|
48
|
-
|
|
49
|
-
Successful Response
|
|
50
|
-
{
|
|
51
|
-
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
|
|
52
|
-
"token_type": "Bearer",
|
|
53
|
-
"expires_in": 3599,
|
|
54
|
-
"scope": "https%3A%2F%2Fgraph.microsoft.com%2Fmail.read",
|
|
55
|
-
"refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4...",
|
|
56
|
-
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctOD...",
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
Error Response
|
|
60
|
-
{
|
|
61
|
-
"error": "invalid_scope",
|
|
62
|
-
"error_description": "AADSTS70011: The provided value for the input parameter 'scope' is not valid. The scope https://foo.microsoft.com/mail.read is not valid.\r\nTrace ID: 255d1aef-8c98-452f-ac51-23d051240864\r\nCorrelation ID: fb3d2015-bc17-4bb9-bb85-30c5cf1aaaa7\r\nTimestamp: 2016-01-09 02:02:12Z",
|
|
63
|
-
"error_codes": [
|
|
64
|
-
70011
|
|
65
|
-
],
|
|
66
|
-
"timestamp": "2016-01-09 02:02:12Z",
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
*/
|
|
71
|
-
_STSOAuth2Worker_HandleAuthenticateEvent.set(this, (id_token) => {
|
|
72
|
-
const message = {
|
|
73
|
-
messageId: -1,
|
|
74
|
-
command: IOauth2ListenerCommand.AUTHENTICATE_EVENT
|
|
75
|
-
};
|
|
76
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_ProcessCommand, "f").call(this, message, id_token);
|
|
77
|
-
});
|
|
78
|
-
_STSOAuth2Worker_HandleErrorEvent.set(this, (error) => {
|
|
79
|
-
const message = {
|
|
80
|
-
messageId: -1,
|
|
81
|
-
command: IOauth2ListenerCommand.ERROR
|
|
82
|
-
};
|
|
83
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_ProcessCommand, "f").call(this, message, error);
|
|
84
|
-
});
|
|
85
|
-
_STSOAuth2Worker_LogMessage.set(this, (messageToSend) => {
|
|
86
|
-
const message = {
|
|
87
|
-
messageId: -1,
|
|
88
|
-
command: IOauth2ListenerCommand.LOG
|
|
89
|
-
};
|
|
90
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_ProcessCommand, "f").call(this, message, messageToSend);
|
|
91
|
-
});
|
|
92
|
-
_STSOAuth2Worker_GetAccessToken.set(this, () => {
|
|
93
|
-
const tokens = __classPrivateFieldGet(this, _STSOAuth2Worker_clientSessionStore, "f").get(__classPrivateFieldGet(this, _STSOAuth2Worker_STORAGE_SESSION_KEY, "f"));
|
|
94
|
-
return tokens.access_token;
|
|
95
|
-
});
|
|
96
|
-
_STSOAuth2Worker_UpdateInstrument.set(this, (instrumentName, telemetry) => {
|
|
97
|
-
const message = {
|
|
98
|
-
messageId: -1,
|
|
99
|
-
command: IOauth2ListenerCommand.UPDATE_INSTRUMENT
|
|
100
|
-
};
|
|
101
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_ProcessCommand, "f").call(this, message, {
|
|
102
|
-
instrumentName,
|
|
103
|
-
telemetry
|
|
104
|
-
});
|
|
36
|
+
this.#options = options;
|
|
37
|
+
debug(`STSOAuth2Worker:constructor:#options: [${JSON.stringify(this.#options)}]`);
|
|
38
|
+
// In memory storage for OAuth2 tokens for our valid session
|
|
39
|
+
this.#clientSessionStore = new stsStorage_1.ClientStorageFactory({ clientStorageType: stsStorage_1.ClientStorageType.MEMORY_STORAGE }).GetStorage();
|
|
40
|
+
//@@ needs to be sent the instrument manager controller port
|
|
41
|
+
//@@this.#aic = app.config.globalProperties.$sts.aic.PrimaryPublishInstrumentController;
|
|
42
|
+
//this.#handleAuthenticateEvent = handleAuthenticateEvent;
|
|
43
|
+
this.#oauthWorkerPort = workerPort;
|
|
44
|
+
debug(`STSOAuth2Worker:constructor:#oauthWorkerPort: [${JSON.stringify(this.#oauthWorkerPort)}]`);
|
|
45
|
+
this.SetupListener();
|
|
46
|
+
this.#UpdateInstrument(stsinstrumentation_1.Gauge.LOGGER, {
|
|
47
|
+
LogMessage: `STSOauth2 Plugin - Successfully Loaded`
|
|
105
48
|
});
|
|
106
|
-
this.SetupListener = () => {
|
|
107
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_oauthWorkerPort, "f").onmessage = async (data) => {
|
|
108
|
-
const auth2ListenerMessage = data.data;
|
|
109
|
-
debug(`STSOAuth2Worker:SetupListener:onmessage: [${auth2ListenerMessage.command}]`);
|
|
110
|
-
switch (auth2ListenerMessage.command) {
|
|
111
|
-
case IOauth2ListenerCommand.RESTORE_SESSION:
|
|
112
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_ProcessCommand, "f").call(this, auth2ListenerMessage, await __classPrivateFieldGet(this, _STSOAuth2Worker_RestoreSession, "f").call(this));
|
|
113
|
-
break;
|
|
114
|
-
case IOauth2ListenerCommand.AUTHORIZE:
|
|
115
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_ProcessCommand, "f").call(this, auth2ListenerMessage, await __classPrivateFieldGet(this, _STSOAuth2Worker_Authorize, "f").call(this));
|
|
116
|
-
break;
|
|
117
|
-
case IOauth2ListenerCommand.HANDLE_REDIRECT:
|
|
118
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_ProcessCommand, "f").call(this, auth2ListenerMessage, await __classPrivateFieldGet(this, _STSOAuth2Worker_HandleRedirect, "f").call(this, auth2ListenerMessage.payload));
|
|
119
|
-
break;
|
|
120
|
-
case IOauth2ListenerCommand.LOGOUT:
|
|
121
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_ProcessCommand, "f").call(this, auth2ListenerMessage, await __classPrivateFieldGet(this, _STSOAuth2Worker_Logout, "f").call(this));
|
|
122
|
-
break;
|
|
123
|
-
//@@ Need a way of keeping this out of the main thread - should always stay within the worker
|
|
124
|
-
case IOauth2ListenerCommand.ACCESS_TOKEN:
|
|
125
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_ProcessCommand, "f").call(this, auth2ListenerMessage, await __classPrivateFieldGet(this, _STSOAuth2Worker_GetAccessToken, "f").call(this));
|
|
126
|
-
break;
|
|
127
|
-
default:
|
|
128
|
-
throw new Error(`Command: [${auth2ListenerMessage.command}'] not found.`);
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
};
|
|
132
49
|
/*
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
50
|
+
setInterval(() => { // Used for testing purposes only.
|
|
51
|
+
this.#UpdateInstrument(Gauge.LOGGER, {
|
|
52
|
+
LogMessage: `--> [${Date.now().toString()}] <--`
|
|
53
|
+
} as InstrumentLogTelemetry);
|
|
54
|
+
}, 1000);
|
|
136
55
|
*/
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_LogMessage, "f").call(this, url);
|
|
166
|
-
try {
|
|
167
|
-
const retVal = await axios({
|
|
168
|
-
method: "post",
|
|
169
|
-
url: url,
|
|
170
|
-
data: {
|
|
171
|
-
[OAuth2ParameterType.CLIENT_ID]: __classPrivateFieldGet(this, _STSOAuth2Worker_options, "f").client_id,
|
|
172
|
-
[OAuth2ParameterType.SCOPE]: __classPrivateFieldGet(this, _STSOAuth2Worker_options, "f").scope,
|
|
173
|
-
[OAuth2ParameterType.REDIRECT_URI]: __classPrivateFieldGet(this, _STSOAuth2Worker_options, "f").redirect_uri,
|
|
174
|
-
[OAuth2ParameterType.AUDIENCE]: __classPrivateFieldGet(this, _STSOAuth2Worker_options, "f").audience
|
|
175
|
-
},
|
|
176
|
-
withCredentials: true,
|
|
177
|
-
timeout: __classPrivateFieldGet(this, _STSOAuth2Worker_options, "f").timeout,
|
|
178
|
-
});
|
|
179
|
-
if (retVal.data.status === StatusCodes.OK) {
|
|
180
|
-
restoredSessionData = retVal.data.detail;
|
|
181
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_clientSessionStore, "f").set(__classPrivateFieldGet(this, _STSOAuth2Worker_STORAGE_SESSION_KEY, "f"), restoredSessionData);
|
|
182
|
-
console.log('Session restored from server side cookie.');
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
//@@ handle error better
|
|
186
|
-
console.log('Could not restore previous session:-');
|
|
187
|
-
console.log(JSON.stringify(retVal.data));
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
catch (error) {
|
|
191
|
-
//@@ handle error better
|
|
192
|
-
console.log('Could not restore previous session (error state):-');
|
|
193
|
-
console.log(error);
|
|
194
|
-
console.log(JSON.stringify(error));
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
//@@ must only use in-memory for this ...
|
|
198
|
-
if (restoredSessionData !== null) {
|
|
199
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_HandleAuthenticateEvent, "f").call(this, restoredSessionData.id_token);
|
|
200
|
-
console.log('Refreshing tokens ...');
|
|
201
|
-
return __classPrivateFieldGet(this, _STSOAuth2Worker_RefreshToken, "f").call(this);
|
|
202
|
-
}
|
|
203
|
-
else {
|
|
204
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_HandleAuthenticateEvent, "f").call(this, null);
|
|
205
|
-
return false;
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
_STSOAuth2Worker_Authorize.set(this, async () => {
|
|
209
|
-
console.log('Authorize ...');
|
|
210
|
-
/* MS Example
|
|
211
|
-
--------------
|
|
212
|
-
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
|
|
213
|
-
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
|
|
214
|
-
&response_type=code
|
|
215
|
-
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
|
|
216
|
-
&response_mode=query
|
|
217
|
-
&scope=offline_access%20https%3A%2F%2Fgraph.microsoft.com%2Fuser.read%20api%3A%2F%2F
|
|
218
|
-
&state=12345
|
|
219
|
-
&code_challenge=YTFjNjI1OWYzMzA3MTI4ZDY2Njg5M2RkNmVjNDE5YmEyZGRhOGYyM2IzNjdmZWFhMTQ1ODg3NDcxY2Nl
|
|
220
|
-
&code_challenge_method=S256
|
|
221
|
-
|
|
222
|
-
Successful Response
|
|
223
|
-
|
|
224
|
-
GET http://localhost?
|
|
225
|
-
code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...
|
|
226
|
-
&state=12345
|
|
227
|
-
|
|
228
|
-
Error Response
|
|
229
|
-
GET http://localhost?
|
|
230
|
-
error=access_denied
|
|
231
|
-
&error_description=the+user+canceled+the+authentication
|
|
232
|
-
|
|
233
|
-
<< Hybrid Flow >>
|
|
234
|
-
|
|
235
|
-
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
|
|
236
|
-
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
|
|
237
|
-
&response_type=code%20id_token
|
|
238
|
-
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
|
|
239
|
-
&response_mode=fragment
|
|
240
|
-
&scope=openid%20offline_access%20https%3A%2F%2Fgraph.microsoft.com%2Fuser.read
|
|
241
|
-
&state=12345
|
|
242
|
-
&nonce=abcde
|
|
243
|
-
&code_challenge=YTFjNjI1OWYzMzA3MTI4ZDY2Njg5M2RkNmVjNDE5YmEyZGRhOGYyM2IzNjdmZWFhMTQ1ODg3NDcxY2Nl
|
|
244
|
-
&code_challenge_method=S256
|
|
245
|
-
|
|
246
|
-
Successful Response
|
|
247
|
-
|
|
248
|
-
GET https://login.microsoftonline.com/common/oauth2/nativeclient#
|
|
249
|
-
code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...
|
|
250
|
-
&id_token=eYj...
|
|
251
|
-
&state=12345
|
|
56
|
+
}
|
|
57
|
+
// Attempt to restore a previous session using the STSBroker
|
|
58
|
+
/*
|
|
59
|
+
{ parameterType: OAuth2ParameterType.CLIENT_ID, errorType: authErrorType.CLIENT_ID_MISMATCH },
|
|
60
|
+
{ parameterType: OAuth2ParameterType.SCOPE, errorType: authErrorType.SCOPE_MISMATCH }
|
|
61
|
+
{ parameterType: OAuth2ParameterType.REDIRECT_URI, errorType: authErrorType.REDIRECT_URI_MISMATCH },
|
|
62
|
+
{ parameterType: OAuth2ParameterType.AUDIENCE, errorType: authErrorType.SCOPE_MISMATCH }
|
|
63
|
+
|
|
64
|
+
Successful Response
|
|
65
|
+
{
|
|
66
|
+
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
|
|
67
|
+
"token_type": "Bearer",
|
|
68
|
+
"expires_in": 3599,
|
|
69
|
+
"scope": "https%3A%2F%2Fgraph.microsoft.com%2Fmail.read",
|
|
70
|
+
"refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4...",
|
|
71
|
+
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctOD...",
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
Error Response
|
|
75
|
+
{
|
|
76
|
+
"error": "invalid_scope",
|
|
77
|
+
"error_description": "AADSTS70011: The provided value for the input parameter 'scope' is not valid. The scope https://foo.microsoft.com/mail.read is not valid.\r\nTrace ID: 255d1aef-8c98-452f-ac51-23d051240864\r\nCorrelation ID: fb3d2015-bc17-4bb9-bb85-30c5cf1aaaa7\r\nTimestamp: 2016-01-09 02:02:12Z",
|
|
78
|
+
"error_codes": [
|
|
79
|
+
70011
|
|
80
|
+
],
|
|
81
|
+
"timestamp": "2016-01-09 02:02:12Z",
|
|
82
|
+
}
|
|
83
|
+
|
|
252
84
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
};
|
|
288
|
-
//window.location.assign(url);
|
|
289
|
-
//@@ this may need to be a message back to the plugin to re-direct
|
|
290
|
-
//window.location.replace(url);
|
|
85
|
+
*/
|
|
86
|
+
#HandleAuthenticateEvent = (id_token) => {
|
|
87
|
+
const message = {
|
|
88
|
+
messageId: -1,
|
|
89
|
+
command: stsoauth2types_1.IOauth2ListenerCommand.AUTHENTICATE_EVENT
|
|
90
|
+
};
|
|
91
|
+
this.#ProcessCommand(message, id_token);
|
|
92
|
+
};
|
|
93
|
+
#HandleErrorEvent = (error) => {
|
|
94
|
+
const message = {
|
|
95
|
+
messageId: -1,
|
|
96
|
+
command: stsoauth2types_1.IOauth2ListenerCommand.ERROR
|
|
97
|
+
};
|
|
98
|
+
this.#ProcessCommand(message, error);
|
|
99
|
+
};
|
|
100
|
+
#LogMessage = (messageToSend) => {
|
|
101
|
+
const message = {
|
|
102
|
+
messageId: -1,
|
|
103
|
+
command: stsoauth2types_1.IOauth2ListenerCommand.LOG
|
|
104
|
+
};
|
|
105
|
+
this.#ProcessCommand(message, messageToSend);
|
|
106
|
+
};
|
|
107
|
+
#GetAccessToken = () => {
|
|
108
|
+
const tokens = this.#clientSessionStore.get(this.#STORAGE_SESSION_KEY);
|
|
109
|
+
return tokens.access_token;
|
|
110
|
+
};
|
|
111
|
+
#UpdateInstrument = (instrumentName, telemetry) => {
|
|
112
|
+
const message = {
|
|
113
|
+
messageId: -1,
|
|
114
|
+
command: stsoauth2types_1.IOauth2ListenerCommand.UPDATE_INSTRUMENT
|
|
115
|
+
};
|
|
116
|
+
this.#ProcessCommand(message, {
|
|
117
|
+
instrumentName,
|
|
118
|
+
telemetry
|
|
291
119
|
});
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
120
|
+
};
|
|
121
|
+
SetupListener = () => {
|
|
122
|
+
this.#oauthWorkerPort.onmessage = async (data) => {
|
|
123
|
+
const auth2ListenerMessage = data.data;
|
|
124
|
+
debug(`STSOAuth2Worker:SetupListener:onmessage: [${auth2ListenerMessage.command}]`);
|
|
125
|
+
switch (auth2ListenerMessage.command) {
|
|
126
|
+
case stsoauth2types_1.IOauth2ListenerCommand.RESTORE_SESSION:
|
|
127
|
+
this.#ProcessCommand(auth2ListenerMessage, await this.#RestoreSession());
|
|
128
|
+
break;
|
|
129
|
+
case stsoauth2types_1.IOauth2ListenerCommand.AUTHORIZE:
|
|
130
|
+
this.#ProcessCommand(auth2ListenerMessage, await this.#Authorize());
|
|
131
|
+
break;
|
|
132
|
+
case stsoauth2types_1.IOauth2ListenerCommand.HANDLE_REDIRECT:
|
|
133
|
+
this.#ProcessCommand(auth2ListenerMessage, await this.#HandleRedirect(auth2ListenerMessage.payload));
|
|
134
|
+
break;
|
|
135
|
+
case stsoauth2types_1.IOauth2ListenerCommand.LOGOUT:
|
|
136
|
+
this.#ProcessCommand(auth2ListenerMessage, await this.#Logout());
|
|
137
|
+
break;
|
|
138
|
+
//@@ Need a way of keeping this out of the main thread - should always stay within the worker
|
|
139
|
+
case stsoauth2types_1.IOauth2ListenerCommand.ACCESS_TOKEN:
|
|
140
|
+
this.#ProcessCommand(auth2ListenerMessage, await this.#GetAccessToken());
|
|
141
|
+
break;
|
|
142
|
+
default:
|
|
143
|
+
throw new Error(`Command: [${auth2ListenerMessage.command}'] not found.`);
|
|
312
144
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
/*
|
|
148
|
+
#GetIDToken = async(): Promise<string> => {
|
|
149
|
+
return '-- ID Token --';
|
|
150
|
+
}
|
|
151
|
+
*/
|
|
152
|
+
#ProcessCommand = async (auth2ListenerMessage, response) => {
|
|
153
|
+
const messageResponse = {
|
|
154
|
+
messageId: auth2ListenerMessage.messageId,
|
|
155
|
+
command: auth2ListenerMessage.command,
|
|
156
|
+
payload: response
|
|
157
|
+
};
|
|
158
|
+
this.#oauthWorkerPort.postMessage(messageResponse);
|
|
159
|
+
};
|
|
160
|
+
#RestoreSession = async () => {
|
|
161
|
+
//@@ attempt to get from client storage first
|
|
162
|
+
let restoredSessionData = null;
|
|
163
|
+
restoredSessionData = this.#clientSessionStore.get(this.#STORAGE_SESSION_KEY);
|
|
164
|
+
if (restoredSessionData !== null) {
|
|
165
|
+
console.log('Session restored from client storage.');
|
|
166
|
+
if (this.#aic) {
|
|
167
|
+
this.#aic.UpdateInstrument('m', { LogMessage: 'Session restored from client storage.' });
|
|
327
168
|
}
|
|
169
|
+
this.#LogMessage('Session restored from client storage.');
|
|
328
170
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
{
|
|
340
|
-
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
|
|
341
|
-
"token_type": "Bearer",
|
|
342
|
-
"expires_in": 3599,
|
|
343
|
-
"scope": "https%3A%2F%2Fgraph.microsoft.com%2Fmail.read",
|
|
344
|
-
"refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4...",
|
|
345
|
-
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctOD...",
|
|
346
|
-
}
|
|
347
|
-
*/
|
|
348
|
-
// Get access_token, refresh_token and id_token using OAuth2 Authorization Code Flow
|
|
349
|
-
);
|
|
350
|
-
/*
|
|
351
|
-
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
|
|
352
|
-
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fmail.read
|
|
353
|
-
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
|
|
354
|
-
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
|
|
355
|
-
&grant_type=authorization_code
|
|
356
|
-
&code_verifier=ThisIsntRandomButItNeedsToBe43CharactersLong
|
|
357
|
-
&client_secret=JqQX2PNo9bpM0uEihUPzyrh // NOTE: Only required for web apps. This secret needs to be URL-Encoded.
|
|
358
|
-
|
|
359
|
-
Successful Response
|
|
360
|
-
{
|
|
361
|
-
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
|
|
362
|
-
"token_type": "Bearer",
|
|
363
|
-
"expires_in": 3599,
|
|
364
|
-
"scope": "https%3A%2F%2Fgraph.microsoft.com%2Fmail.read",
|
|
365
|
-
"refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4...",
|
|
366
|
-
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctOD...",
|
|
367
|
-
}
|
|
368
|
-
*/
|
|
369
|
-
// Get access_token, refresh_token and id_token using OAuth2 Authorization Code Flow
|
|
370
|
-
_STSOAuth2Worker_GetTokenFromBroker.set(this, async (authorizationCodeFlowParameters) => {
|
|
371
|
-
console.log("#GetTokenFromBroker");
|
|
372
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_clientSessionStore, "f").remove(__classPrivateFieldGet(this, _STSOAuth2Worker_STORAGE_SESSION_KEY, "f"));
|
|
373
|
-
const url = `${__classPrivateFieldGet(this, _STSOAuth2Worker_options, "f").brokerendpoint}:${__classPrivateFieldGet(this, _STSOAuth2Worker_options, "f").brokerport}${__classPrivateFieldGet(this, _STSOAuth2Worker_options, "f").brokerapiroot}/token`;
|
|
374
|
-
console.log(`#GetTokenFromBroker:url = [${url}]`);
|
|
375
|
-
console.log(authorizationCodeFlowParameters);
|
|
171
|
+
else {
|
|
172
|
+
const url = `${this.#options.brokerendpoint}:${this.#options.brokerport}${this.#options.brokerapiroot}/session`;
|
|
173
|
+
console.log('RestoreSession');
|
|
174
|
+
console.log(url);
|
|
175
|
+
if (this.#aic) {
|
|
176
|
+
this.#aic.UpdateInstrument('m', { LogMessage: 'RestoreSession' });
|
|
177
|
+
this.#aic.UpdateInstrument('m', { LogMessage: url });
|
|
178
|
+
}
|
|
179
|
+
this.#LogMessage('RestoreSession.');
|
|
180
|
+
this.#LogMessage(url);
|
|
376
181
|
try {
|
|
377
|
-
const retVal = await
|
|
182
|
+
const retVal = await (0, axios_1.default)({
|
|
378
183
|
method: "post",
|
|
379
184
|
url: url,
|
|
380
|
-
data:
|
|
185
|
+
data: {
|
|
186
|
+
[stsutils_1.OAuth2ParameterType.CLIENT_ID]: this.#options.client_id,
|
|
187
|
+
[stsutils_1.OAuth2ParameterType.SCOPE]: this.#options.scope,
|
|
188
|
+
[stsutils_1.OAuth2ParameterType.REDIRECT_URI]: this.#options.redirect_uri,
|
|
189
|
+
[stsutils_1.OAuth2ParameterType.AUDIENCE]: this.#options.audience
|
|
190
|
+
},
|
|
381
191
|
withCredentials: true,
|
|
382
|
-
timeout:
|
|
192
|
+
timeout: this.#options.timeout,
|
|
383
193
|
});
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_HandleAuthenticateEvent, "f").call(this, tokenResponse.id_token);
|
|
389
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_clientSessionStore, "f").set(__classPrivateFieldGet(this, _STSOAuth2Worker_STORAGE_SESSION_KEY, "f"), tokenResponse);
|
|
390
|
-
return true;
|
|
391
|
-
}
|
|
392
|
-
else if (retVal.status === StatusCodes.UNAUTHORIZED) {
|
|
393
|
-
console.log('NOT Storing tokens...');
|
|
394
|
-
console.log(retVal.status);
|
|
395
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_HandleAuthenticateEvent, "f").call(this, null);
|
|
396
|
-
const response = retVal.data;
|
|
397
|
-
//@@ store response in state
|
|
398
|
-
//@@ go to error page ??
|
|
399
|
-
return false;
|
|
194
|
+
if (retVal.data.status === http_status_codes_1.StatusCodes.OK) {
|
|
195
|
+
restoredSessionData = retVal.data.detail;
|
|
196
|
+
this.#clientSessionStore.set(this.#STORAGE_SESSION_KEY, restoredSessionData);
|
|
197
|
+
console.log('Session restored from server side cookie.');
|
|
400
198
|
}
|
|
401
199
|
else {
|
|
402
|
-
|
|
403
|
-
console.log('
|
|
404
|
-
console.log(retVal.status);
|
|
405
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_HandleAuthenticateEvent, "f").call(this, null);
|
|
406
|
-
console.log('Could not obtain access_token from token end-point:-');
|
|
200
|
+
//@@ handle error better
|
|
201
|
+
console.log('Could not restore previous session:-');
|
|
407
202
|
console.log(JSON.stringify(retVal.data));
|
|
408
|
-
//@@ store error in state to show in error page
|
|
409
|
-
return false;
|
|
410
203
|
}
|
|
411
204
|
}
|
|
412
205
|
catch (error) {
|
|
413
|
-
|
|
414
|
-
|
|
206
|
+
//@@ handle error better
|
|
207
|
+
console.log('Could not restore previous session (error state):-');
|
|
415
208
|
console.log(error);
|
|
416
209
|
console.log(JSON.stringify(error));
|
|
417
|
-
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
//@@ must only use in-memory for this ...
|
|
213
|
+
if (restoredSessionData !== null) {
|
|
214
|
+
this.#HandleAuthenticateEvent(restoredSessionData.id_token);
|
|
215
|
+
console.log('Refreshing tokens ...');
|
|
216
|
+
return this.#RefreshToken();
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
this.#HandleAuthenticateEvent(null);
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
#Authorize = async () => {
|
|
224
|
+
console.log('Authorize ...');
|
|
225
|
+
/* MS Example
|
|
226
|
+
--------------
|
|
227
|
+
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
|
|
228
|
+
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
|
|
229
|
+
&response_type=code
|
|
230
|
+
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
|
|
231
|
+
&response_mode=query
|
|
232
|
+
&scope=offline_access%20https%3A%2F%2Fgraph.microsoft.com%2Fuser.read%20api%3A%2F%2F
|
|
233
|
+
&state=12345
|
|
234
|
+
&code_challenge=YTFjNjI1OWYzMzA3MTI4ZDY2Njg5M2RkNmVjNDE5YmEyZGRhOGYyM2IzNjdmZWFhMTQ1ODg3NDcxY2Nl
|
|
235
|
+
&code_challenge_method=S256
|
|
236
|
+
|
|
237
|
+
Successful Response
|
|
238
|
+
|
|
239
|
+
GET http://localhost?
|
|
240
|
+
code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...
|
|
241
|
+
&state=12345
|
|
242
|
+
|
|
243
|
+
Error Response
|
|
244
|
+
GET http://localhost?
|
|
245
|
+
error=access_denied
|
|
246
|
+
&error_description=the+user+canceled+the+authentication
|
|
247
|
+
|
|
248
|
+
<< Hybrid Flow >>
|
|
249
|
+
|
|
250
|
+
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
|
|
251
|
+
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
|
|
252
|
+
&response_type=code%20id_token
|
|
253
|
+
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
|
|
254
|
+
&response_mode=fragment
|
|
255
|
+
&scope=openid%20offline_access%20https%3A%2F%2Fgraph.microsoft.com%2Fuser.read
|
|
256
|
+
&state=12345
|
|
257
|
+
&nonce=abcde
|
|
258
|
+
&code_challenge=YTFjNjI1OWYzMzA3MTI4ZDY2Njg5M2RkNmVjNDE5YmEyZGRhOGYyM2IzNjdmZWFhMTQ1ODg3NDcxY2Nl
|
|
259
|
+
&code_challenge_method=S256
|
|
260
|
+
|
|
261
|
+
Successful Response
|
|
262
|
+
|
|
263
|
+
GET https://login.microsoftonline.com/common/oauth2/nativeclient#
|
|
264
|
+
code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...
|
|
265
|
+
&id_token=eYj...
|
|
266
|
+
&state=12345
|
|
267
|
+
|
|
268
|
+
Notes:
|
|
269
|
+
The nonce is included as a claim inside the returned id_token
|
|
270
|
+
Ref: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow
|
|
271
|
+
*/
|
|
272
|
+
const client_id = this.#options.client_id;
|
|
273
|
+
const nonce = this.#cUtils.CreateRandomString();
|
|
274
|
+
const response_type = [stsoauth2types_1.AuthorizeOptionsResponseType.CODE];
|
|
275
|
+
const redirect_uri = this.#options.redirect_uri;
|
|
276
|
+
const response_mode = stsoauth2types_1.AuthorizeOptionsResponseMode.QUERY;
|
|
277
|
+
const scope = this.#options.scope;
|
|
278
|
+
const state = this.#cUtils.CreateRandomString();
|
|
279
|
+
const code_verifier = this.#cUtils.CreateRandomString();
|
|
280
|
+
const code_challenge = await this.#cUtils.DigestMessage(code_verifier);
|
|
281
|
+
const code_challenge_method = 'S256';
|
|
282
|
+
//let audience = this.#options.AUDIENCE;
|
|
283
|
+
const authorizeOptions = {
|
|
284
|
+
client_id,
|
|
285
|
+
nonce,
|
|
286
|
+
response_type,
|
|
287
|
+
redirect_uri,
|
|
288
|
+
response_mode,
|
|
289
|
+
scope,
|
|
290
|
+
state,
|
|
291
|
+
code_challenge,
|
|
292
|
+
code_challenge_method
|
|
293
|
+
};
|
|
294
|
+
const url = `${this.#options.authorizeendpoint}:${this.#options.authorizeport}${this.#options.authorizeapiroot}?${this.#qParams.CreateQueryParams(authorizeOptions)}`;
|
|
295
|
+
console.log(url);
|
|
296
|
+
// Now add the code_verifier to the transaction data
|
|
297
|
+
authorizeOptions.code_verifier = code_verifier; //@@ Is this is the only thing required across the transaction ?
|
|
298
|
+
console.log(`Authorize:authorizeOptions: [${JSON.stringify(authorizeOptions)}]`);
|
|
299
|
+
return {
|
|
300
|
+
url,
|
|
301
|
+
authorizeOptions
|
|
302
|
+
};
|
|
303
|
+
//window.location.assign(url);
|
|
304
|
+
//@@ this may need to be a message back to the plugin to re-direct
|
|
305
|
+
//window.location.replace(url);
|
|
306
|
+
};
|
|
307
|
+
#HandleRedirect = async (payload) => {
|
|
308
|
+
const queryVars = payload.queryVars;
|
|
309
|
+
const authorizeOptions = payload.authorizeOptions;
|
|
310
|
+
console.log('HandleRedirect');
|
|
311
|
+
// We have been re-direct back here from the /authorize end-point
|
|
312
|
+
console.log(`HandleRedirect:Query Vars: [${JSON.stringify(queryVars)}]`);
|
|
313
|
+
if (queryVars[stsutils_1.OAuth2ParameterType.CODE]) {
|
|
314
|
+
const response = queryVars;
|
|
315
|
+
console.log(`authorizeOptions from transaction state: [${JSON.stringify(authorizeOptions)}]`);
|
|
316
|
+
const redirectState = response.state;
|
|
317
|
+
const authorizeOptionsState = authorizeOptions.state;
|
|
318
|
+
if (authorizeOptionsState.localeCompare(redirectState) === 0) {
|
|
319
|
+
console.log('redirected state (from queryVars) matched previously saved transaction authorizeOptions state'); // green
|
|
320
|
+
return await this.#GetToken(authorizeOptions, response);
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
console.log('redirected state (from queryVars) did NOT match previously saved transaction authorizeOptions state'); // red
|
|
324
|
+
this.#HandleErrorEvent({ message: 'State un-matched' });
|
|
418
325
|
return false;
|
|
419
326
|
}
|
|
420
327
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
const authorizationCodeFlowParameters = {
|
|
429
|
-
client_id: __classPrivateFieldGet(this, _STSOAuth2Worker_options, "f").client_id,
|
|
430
|
-
scope: __classPrivateFieldGet(this, _STSOAuth2Worker_options, "f").scope,
|
|
431
|
-
code: authorizeResponse.code,
|
|
432
|
-
redirect_uri: __classPrivateFieldGet(this, _STSOAuth2Worker_options, "f").redirect_uri,
|
|
433
|
-
grant_type: OAuthGrantTypes.AUTHORIZATION_CODE,
|
|
434
|
-
code_verifier: authorizeOptions.code_verifier
|
|
435
|
-
};
|
|
436
|
-
return __classPrivateFieldGet(this, _STSOAuth2Worker_GetTokenFromBroker, "f").call(this, authorizationCodeFlowParameters);
|
|
328
|
+
else if (queryVars[stsutils_1.OAuth2ParameterType.ERROR]) {
|
|
329
|
+
const response = queryVars;
|
|
330
|
+
//@@ pass error back to parent thread (to the plugin) as a message
|
|
331
|
+
const error = response.error;
|
|
332
|
+
const errorDescription = response.error_description;
|
|
333
|
+
this.#HandleErrorEvent({ message: 'State un-matched' });
|
|
334
|
+
return false;
|
|
437
335
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
&grant_type=refresh_token
|
|
449
|
-
&client_secret=sampleCredentia1s // NOTE: Only required for web apps. This secret needs to be URL-Encoded
|
|
450
|
-
|
|
451
|
-
Error Response
|
|
452
|
-
{
|
|
453
|
-
"error": "invalid_scope",
|
|
454
|
-
"error_description": "AADSTS70011: The provided value for the input parameter 'scope' is not valid. The scope https://foo.microsoft.com/mail.read is not valid.\r\nTrace ID: 255d1aef-8c98-452f-ac51-23d051240864\r\nCorrelation ID: fb3d2015-bc17-4bb9-bb85-30c5cf1aaaa7\r\nTimestamp: 2016-01-09 02:02:12Z",
|
|
455
|
-
"error_codes": [
|
|
456
|
-
70011
|
|
457
|
-
],
|
|
458
|
-
"timestamp": "2016-01-09 02:02:12Z",
|
|
459
|
-
"trace_id": "255d1aef-8c98-452f-ac51-23d051240864",
|
|
460
|
-
"correlation_id": "fb3d2015-bc17-4bb9-bb85-30c5cf1aaaa7"
|
|
461
|
-
}
|
|
462
|
-
*/
|
|
463
|
-
);
|
|
464
|
-
/*
|
|
465
|
-
// Line breaks for legibility only
|
|
466
|
-
|
|
467
|
-
POST /{tenant}/oauth2/v2.0/token HTTP/1.1
|
|
468
|
-
Host: https://login.microsoftonline.com
|
|
469
|
-
Content-Type: application/x-www-form-urlencoded
|
|
470
|
-
|
|
471
|
-
client_id=535fb089-9ff3-47b6-9bfb-4f1264799865
|
|
336
|
+
else {
|
|
337
|
+
// Invalid redirect query params
|
|
338
|
+
const error = 'Invalid redirect query params'; //@@ fix
|
|
339
|
+
const errorDescription = 'Invalid redirect query params description'; //@@ fix
|
|
340
|
+
this.#HandleErrorEvent({ message: 'State un-matched' });
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
/*
|
|
345
|
+
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
|
|
472
346
|
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fmail.read
|
|
473
|
-
&
|
|
474
|
-
&
|
|
475
|
-
&
|
|
476
|
-
|
|
477
|
-
|
|
347
|
+
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
|
|
348
|
+
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
|
|
349
|
+
&grant_type=authorization_code
|
|
350
|
+
&code_verifier=ThisIsntRandomButItNeedsToBe43CharactersLong
|
|
351
|
+
&client_secret=JqQX2PNo9bpM0uEihUPzyrh // NOTE: Only required for web apps. This secret needs to be URL-Encoded.
|
|
352
|
+
|
|
353
|
+
Successful Response
|
|
478
354
|
{
|
|
479
|
-
"
|
|
480
|
-
"
|
|
481
|
-
"
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
"
|
|
485
|
-
|
|
486
|
-
"correlation_id": "fb3d2015-bc17-4bb9-bb85-30c5cf1aaaa7"
|
|
487
|
-
}
|
|
355
|
+
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
|
|
356
|
+
"token_type": "Bearer",
|
|
357
|
+
"expires_in": 3599,
|
|
358
|
+
"scope": "https%3A%2F%2Fgraph.microsoft.com%2Fmail.read",
|
|
359
|
+
"refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4...",
|
|
360
|
+
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctOD...",
|
|
361
|
+
}
|
|
488
362
|
*/
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
363
|
+
// Get access_token, refresh_token and id_token using OAuth2 Authorization Code Flow
|
|
364
|
+
#GetTokenFromBroker = async (authorizationCodeFlowParameters) => {
|
|
365
|
+
console.log("#GetTokenFromBroker");
|
|
366
|
+
this.#clientSessionStore.remove(this.#STORAGE_SESSION_KEY);
|
|
367
|
+
const url = `${this.#options.brokerendpoint}:${this.#options.brokerport}${this.#options.brokerapiroot}/token`;
|
|
368
|
+
console.log(`#GetTokenFromBroker:url = [${url}]`);
|
|
369
|
+
console.log(authorizationCodeFlowParameters);
|
|
370
|
+
try {
|
|
371
|
+
const retVal = await (0, axios_1.default)({
|
|
372
|
+
method: "post",
|
|
373
|
+
url: url,
|
|
374
|
+
data: authorizationCodeFlowParameters,
|
|
375
|
+
withCredentials: true,
|
|
376
|
+
timeout: this.#options.timeout
|
|
377
|
+
});
|
|
378
|
+
console.log(`retVal: ${JSON.stringify(retVal)}`);
|
|
379
|
+
if (retVal.status === http_status_codes_1.StatusCodes.OK) {
|
|
380
|
+
console.log('Storing tokens...');
|
|
381
|
+
const tokenResponse = retVal.data;
|
|
382
|
+
this.#HandleAuthenticateEvent(tokenResponse.id_token);
|
|
383
|
+
this.#clientSessionStore.set(this.#STORAGE_SESSION_KEY, tokenResponse);
|
|
384
|
+
return true;
|
|
385
|
+
}
|
|
386
|
+
else if (retVal.status === http_status_codes_1.StatusCodes.UNAUTHORIZED) {
|
|
387
|
+
console.log('NOT Storing tokens...');
|
|
388
|
+
console.log(retVal.status);
|
|
389
|
+
this.#HandleAuthenticateEvent(null);
|
|
390
|
+
const response = retVal.data;
|
|
391
|
+
//@@ store response in state
|
|
392
|
+
//@@ go to error page ??
|
|
393
|
+
return false;
|
|
501
394
|
}
|
|
502
395
|
else {
|
|
503
|
-
//
|
|
504
|
-
|
|
396
|
+
// General error
|
|
397
|
+
console.log('NOT Storing tokens...');
|
|
398
|
+
console.log(retVal.status);
|
|
399
|
+
this.#HandleAuthenticateEvent(null);
|
|
400
|
+
console.log('Could not obtain access_token from token end-point:-');
|
|
401
|
+
console.log(JSON.stringify(retVal.data));
|
|
402
|
+
//@@ store error in state to show in error page
|
|
505
403
|
return false;
|
|
506
404
|
}
|
|
507
405
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
406
|
+
catch (error) {
|
|
407
|
+
this.#HandleAuthenticateEvent(null);
|
|
408
|
+
//console.log('Could not restore previous session (error state):-');
|
|
409
|
+
console.log(error);
|
|
410
|
+
console.log(JSON.stringify(error));
|
|
411
|
+
//@@ store error in state to show in error page
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
// Get access_token, refresh_token and id_token using OAuth2 Authorization Code Flow
|
|
416
|
+
#GetToken = async (authorizeOptions, authorizeResponse) => {
|
|
417
|
+
console.log("#GetToken");
|
|
418
|
+
console.log(authorizeResponse);
|
|
419
|
+
this.#clientSessionStore.set(this.#STORAGE_SESSION_KEY, null);
|
|
420
|
+
const authorizationCodeFlowParameters = {
|
|
421
|
+
client_id: this.#options.client_id,
|
|
422
|
+
scope: this.#options.scope,
|
|
423
|
+
code: authorizeResponse.code,
|
|
424
|
+
redirect_uri: this.#options.redirect_uri,
|
|
425
|
+
grant_type: stsoauth2types_1.OAuthGrantTypes.AUTHORIZATION_CODE,
|
|
426
|
+
code_verifier: authorizeOptions.code_verifier
|
|
427
|
+
};
|
|
428
|
+
return this.#GetTokenFromBroker(authorizationCodeFlowParameters);
|
|
429
|
+
};
|
|
430
|
+
/*
|
|
431
|
+
// Line breaks for legibility only
|
|
432
|
+
|
|
433
|
+
POST /{tenant}/oauth2/v2.0/token HTTP/1.1
|
|
434
|
+
Host: https://login.microsoftonline.com
|
|
435
|
+
Content-Type: application/x-www-form-urlencoded
|
|
436
|
+
|
|
437
|
+
client_id=535fb089-9ff3-47b6-9bfb-4f1264799865
|
|
438
|
+
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fmail.read
|
|
439
|
+
&refresh_token=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq...
|
|
440
|
+
&grant_type=refresh_token
|
|
441
|
+
&client_secret=sampleCredentia1s // NOTE: Only required for web apps. This secret needs to be URL-Encoded
|
|
442
|
+
|
|
443
|
+
Error Response
|
|
444
|
+
{
|
|
445
|
+
"error": "invalid_scope",
|
|
446
|
+
"error_description": "AADSTS70011: The provided value for the input parameter 'scope' is not valid. The scope https://foo.microsoft.com/mail.read is not valid.\r\nTrace ID: 255d1aef-8c98-452f-ac51-23d051240864\r\nCorrelation ID: fb3d2015-bc17-4bb9-bb85-30c5cf1aaaa7\r\nTimestamp: 2016-01-09 02:02:12Z",
|
|
447
|
+
"error_codes": [
|
|
448
|
+
70011
|
|
449
|
+
],
|
|
450
|
+
"timestamp": "2016-01-09 02:02:12Z",
|
|
451
|
+
"trace_id": "255d1aef-8c98-452f-ac51-23d051240864",
|
|
452
|
+
"correlation_id": "fb3d2015-bc17-4bb9-bb85-30c5cf1aaaa7"
|
|
453
|
+
}
|
|
454
|
+
*/
|
|
455
|
+
#RefreshToken = async () => {
|
|
456
|
+
// Get access_token, refresh_token and id_token using OAuth2 Authorization Code Flow
|
|
457
|
+
console.log("RefreshToken");
|
|
458
|
+
const currentSessionData = this.#clientSessionStore.get(this.#STORAGE_SESSION_KEY);
|
|
459
|
+
if (currentSessionData) {
|
|
460
|
+
const refreshFlowParameters = {
|
|
461
|
+
client_id: this.#options.client_id,
|
|
462
|
+
scope: this.#options.scope,
|
|
463
|
+
refresh_token: currentSessionData.refresh_token,
|
|
464
|
+
grant_type: stsoauth2types_1.OAuthGrantTypes.REFRESH_TOKEN
|
|
465
|
+
};
|
|
466
|
+
return this.#GetTokenFromBroker(refreshFlowParameters);
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
// show error
|
|
470
|
+
//@@ no valid session exists for refresh
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
// call broker to logout
|
|
475
|
+
// broker to logout of server
|
|
476
|
+
// delete cookie
|
|
477
|
+
// clear session storage
|
|
478
|
+
// clear all state from $store
|
|
479
|
+
#Logout = async () => {
|
|
480
|
+
console.log('Logout');
|
|
481
|
+
const url = `${this.#options.brokerendpoint}:${this.#options.brokerport}${this.#options.brokerapiroot}/logout`;
|
|
482
|
+
console.log(url);
|
|
483
|
+
const currentSessionData = this.#clientSessionStore.get(this.#STORAGE_SESSION_KEY);
|
|
484
|
+
const refresh_token = currentSessionData.refresh_token;
|
|
485
|
+
console.log(refresh_token);
|
|
486
|
+
const decodedRefreshToken = (0, jwt_decode_1.default)(refresh_token);
|
|
487
|
+
console.log(decodedRefreshToken);
|
|
488
|
+
const sessionId = decodedRefreshToken.sts_session;
|
|
489
|
+
console.log(sessionId);
|
|
490
|
+
this.#clientSessionStore.remove(this.#STORAGE_SESSION_KEY);
|
|
491
|
+
this.#HandleAuthenticateEvent(null);
|
|
492
|
+
try {
|
|
493
|
+
const retVal = await (0, axios_1.default)({
|
|
494
|
+
method: "post",
|
|
495
|
+
url: url,
|
|
496
|
+
data: {
|
|
497
|
+
sessionId
|
|
498
|
+
},
|
|
499
|
+
withCredentials: true,
|
|
500
|
+
timeout: this.#options.timeout,
|
|
501
|
+
});
|
|
502
|
+
if (retVal.data.status === http_status_codes_1.StatusCodes.OK) {
|
|
503
|
+
return true;
|
|
550
504
|
}
|
|
551
|
-
|
|
505
|
+
else {
|
|
552
506
|
console.log('Error during logout (server side)');
|
|
553
|
-
console.log(
|
|
554
|
-
console.log(JSON.stringify(error));
|
|
507
|
+
console.log(JSON.stringify(retVal.data));
|
|
555
508
|
return false;
|
|
556
509
|
}
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
__classPrivateFieldSet(this, _STSOAuth2Worker_oauthWorkerPort, workerPort, "f");
|
|
566
|
-
debug(`STSOAuth2Worker:constructor:#oauthWorkerPort: [${JSON.stringify(__classPrivateFieldGet(this, _STSOAuth2Worker_oauthWorkerPort, "f"))}]`);
|
|
567
|
-
this.SetupListener();
|
|
568
|
-
__classPrivateFieldGet(this, _STSOAuth2Worker_UpdateInstrument, "f").call(this, Gauge.LOGGER, {
|
|
569
|
-
LogMessage: `STSOauth2 Plugin - Successfully Loaded`
|
|
570
|
-
});
|
|
571
|
-
/*
|
|
572
|
-
setInterval(() => { // Used for testing purposes only.
|
|
573
|
-
this.#UpdateInstrument(Gauge.LOGGER, {
|
|
574
|
-
LogMessage: `--> [${Date.now().toString()}] <--`
|
|
575
|
-
} as InstrumentLogTelemetry);
|
|
576
|
-
}, 1000);
|
|
577
|
-
*/
|
|
578
|
-
}
|
|
510
|
+
}
|
|
511
|
+
catch (error) {
|
|
512
|
+
console.log('Error during logout (server side)');
|
|
513
|
+
console.log(error);
|
|
514
|
+
console.log(JSON.stringify(error));
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
};
|
|
579
518
|
}
|
|
580
|
-
|
|
519
|
+
exports.STSOAuth2Worker = STSOAuth2Worker;
|
|
581
520
|
/*
|
|
582
521
|
let oAuth2Worker: STSOAuth2Worker = null;
|
|
583
522
|
|