-
Notifications
You must be signed in to change notification settings - Fork 1
/
background.js
194 lines (160 loc) · 5.81 KB
/
background.js
1
2
3
4
5
6
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
import {getAccessToken, getToken, getTokenUrl} from "./solid.js";
import {createDpopHeader} from '@inrupt/solid-client-authn-core';
var id;
var secret;
var tokenUrl;
var isChrome;
/**
* Main function that is called upon extension (re)start
*/
function main() {
isChrome = (navigator.userAgent.toLowerCase().includes("chrome"));
getCredentialsFromBrowserStorage();
/**
* Runtime message listener, capable of handling and properly awaiting asynchronous functions
*/
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
handleMessage(request).then(sendResponse);
return true;
});
/**
* Blocking web request listener that blocks a web request until the alteration of its request headers is completed
*/
chrome.webRequest.onBeforeSendHeaders.addListener(
rewriteRequestHeaders,
{
urls: ["<all_urls>"]
},
["blocking", "requestHeaders"]
)
}
/**
* Rewrite request headers with correct credentials so that successful authentication may be achieved
* @param {Object} details - Request details passed on from blocking web request listener
* @returns {Object} - Object containing altered request headers, to be handled by the web request listener callback
*/
async function rewriteRequestHeaders(details) {
// TODO: find a more elegant way to catch the access token creation request called from getAccessToken()
if (details.method === "POST") {
return
}
if (id === undefined || secret === undefined || tokenUrl === undefined) {
return
}
const {accessToken, dpopKey} = await getAccessToken(id, secret, tokenUrl);
const dpopHeader = await createDpopHeader(details.url, "GET", dpopKey);
details.requestHeaders.push({
name: "authorization",
value: "DPoP " + accessToken
})
details.requestHeaders.push({
name: "dpop",
value: dpopHeader
})
return {requestHeaders: details.requestHeaders}
}
/**
* Handle various runtime messages sent from the browser action popup
* @param {Object} message - Message object that contains various parameters, specific to the message's purpose
*/
async function handleMessage(message) {
if (message.msg === "generate-id") {
let credentialsUrl = message.idp + "idp/credentials/";
tokenUrl = await getTokenUrl(message.idp);
const response = await getToken(message.email, message.password, credentialsUrl);
id = response.id;
secret = response.secret;
let success = (id !== undefined && secret !== undefined);
changeIcon(success);
if (success) {
storeCredentialsInBrowserStorage(id, secret, tokenUrl);
}
return {
success: success
};
} else if (message.msg === "logout") {
id = undefined;
secret = undefined;
tokenUrl = undefined;
changeIcon(false);
removeClientCredentialsFromBrowserStorage();
} else if (message.msg === "check-authenticated") {
let authenticated = (id !== undefined && secret !== undefined && tokenUrl !== undefined);
return {
authenticated: authenticated
};
}
}
/**
* Alter the browser action's icon in the toolbar depending on the success of an attempted log in
* @param {Boolean} success - Potential success of log in that the icon should indicate
*/
function changeIcon(success) {
const iconPath = success ? "solid-48-checkmark.png" : "solid-48.png";
chrome.browserAction.setIcon({
path: {
"48": iconPath
}
});
}
/**
* Load any potential client credentials still stored in the browser storage
*/
function getCredentialsFromBrowserStorage() {
loadFromBrowserStorage("solidCredentials", function (result) {
if (result.solidCredentials !== undefined) {
id = result.solidCredentials.id
secret = result.solidCredentials.secret
tokenUrl = result.solidCredentials.tokenUrl
changeIcon(true);
} else {
changeIcon(false);
}
})
}
/**
* Store the current client credentials and token url into the browser storage
* @param {String} id - Client ID
* @param {String} secret - Client secret
* @param {String} tokenUrl - Token url from which access tokens can be requested
*/
function storeCredentialsInBrowserStorage(id, secret, tokenUrl) {
storeInBrowserStorage({
solidCredentials: {
id: id,
secret: secret,
tokenUrl: tokenUrl
}
})
}
/**
* Remove any potential client credentials from browser storage
*/
function removeClientCredentialsFromBrowserStorage() {
removeFromBrowserStorage("solidCredentials");
}
/**
* Load item from the browser storage before calling a callback function with the loaded item as a parameter
* @param {Object} item - Object containing the item which should be stored in the browser storage
* @param {Function} callback - Callback function which is called after the item is added
*/
function loadFromBrowserStorage(item, callback) {
chrome.storage.local.get(item, callback);
}
/**
* Store item in the browser storage before calling a callback function
* @param {String} item - Name of the item which should be loaded from the browser storage
* @param {Function} callback - Callback function which is called after the item is loaded
*/
function storeInBrowserStorage(item, callback) {
chrome.storage.local.set(item, callback);
}
/**
* Remove item from the browser storage before calling a callback function
* @param {String} item - Name of the item which should be removed from the browser storage
* @param {Function} callback - Callback function which is called after the item is removed
*/
function removeFromBrowserStorage(item, callback) {
chrome.storage.local.remove(item, callback);
}
main();