Skip to content

WIP: delegate SW registration to the user #1081

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 2 additions & 18 deletions packages/react/src/oidc/vanilla/initWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ const sendMessageAsync = (registration) => (data) => {
});
};

export const initWorkerAsync = async(serviceWorkerRelativeUrl, configurationName) => {
export const initWorkerAsync = async(serviceWorkerRelativeUrl, configurationName, noAutoRegister) => {
if (typeof window === 'undefined' || typeof navigator === 'undefined' || !navigator.serviceWorker || !serviceWorkerRelativeUrl) {
return null;
}
Expand All @@ -175,8 +175,7 @@ export const initWorkerAsync = async(serviceWorkerRelativeUrl, configurationName
if (excludeOs(operatingSystem)) {
return null;
}

const registration = await navigator.serviceWorker.register(serviceWorkerRelativeUrl);
const registration = await (noAutoRegister ? navigator.serviceWorker.getRegistration() : navigator.serviceWorker.register(serviceWorkerRelativeUrl));

try {
await navigator.serviceWorker.ready;
Expand All @@ -188,21 +187,6 @@ export const initWorkerAsync = async(serviceWorkerRelativeUrl, configurationName
return await registration.unregister();
};

registration.addEventListener('updatefound', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this code reloads the page if an update to a service worker is detected, is it really needed? if the user manages the service worker on his own, it probably should be on his side

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I know,

may be another property to disable this default behavior would be a nice idea.
The difficulty, is link to the time to leave request which maintain the old service worker to life and block updates.

I does not found a cleaner default behavior way. Many people does not understand well service worker so I prefer a default page realoard in production than all production page broken.

May be a clean defaut and safer way can be found.

const newWorker = registration.installing;
newWorker.addEventListener('statechange', () => {
switch (newWorker.state) {
case 'installed':
if (navigator.serviceWorker.controller) {
registration.unregister().then(() => {
window.location.reload();
});
}
break;
}
});
});

const clearAsync = async (status) => {
return sendMessageAsync(registration)({ type: 'clear', data: { status }, configurationName });
};
Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/oidc/vanilla/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const defaultLoginAsync = (window, configurationName, configuration:OidcC
extraFinal.nonce = generateRandom(12);
}
const nonce = { nonce: extraFinal.nonce };
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, configurationName);
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, configurationName, configuration.service_worker_no_auto_register);
const oidcServerConfiguration = await initAsync(configuration.authority, configuration.authority_configuration);
let storage;
if (serviceWorker) {
Expand Down Expand Up @@ -82,7 +82,7 @@ export const loginCallbackAsync = (oidc) => async (isSilentSignin = false) => {
const oidcServerConfiguration = await oidc.initAsync(authority, configuration.authority_configuration);
const queryParams = getParseQueryStringFromLocation(window.location.href);
const sessionState = queryParams.session_state;
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, oidc.configurationName);
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, oidc.configurationName, configuration.service_worker_no_auto_register);
let storage;
let nonceData;
let getLoginParams;
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/oidc/vanilla/logout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const destroyAsync = (oidc) => async (status) => {
if (oidc.checkSessionIFrame) {
oidc.checkSessionIFrame.stop();
}
const serviceWorker = await initWorkerAsync(oidc.configuration.service_worker_relative_url, oidc.configurationName);
const serviceWorker = await initWorkerAsync(oidc.configuration.service_worker_relative_url, oidc.configurationName, oidc.configuration.service_worker_no_auto_register);
if (!serviceWorker) {
const session = initSession(oidc.configurationName, oidc.configuration.storage);
await session.clearAsync(status);
Expand Down
10 changes: 5 additions & 5 deletions packages/react/src/oidc/vanilla/oidc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
});
}

const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName);
const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName, this.configuration.service_worker_no_auto_register);
const storage = serviceWorker ? window.localStorage : null;
return await fetchFromIssuer(this.getFetch())(authority, this.configuration.authority_time_cache_wellknowurl_in_second ?? 60 * 60, storage, this.configuration.authority_timeout_wellknowurl_in_millisecond);
};
Expand All @@ -226,7 +226,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
try {
const configuration = this.configuration;
const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName, configuration.service_worker_no_auto_register);
if (serviceWorker) {
const { tokens } = await serviceWorker.initAsync(oidcServerConfiguration, 'tryKeepExistingSessionAsync', configuration);
if (tokens) {
Expand Down Expand Up @@ -326,7 +326,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
const parsedTokens = response.tokens;
// @ts-ignore
this.tokens = parsedTokens;
const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName);
const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName, this.configuration.service_worker_no_auto_register);
if (!serviceWorker) {
const session = initSession(this.configurationName, this.configuration.storage);
session.setTokens(parsedTokens);
Expand Down Expand Up @@ -372,7 +372,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
const localsilentLoginAsync = async () => {
try {
let loginParams;
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName, configuration.service_worker_no_auto_register);
if (serviceWorker) {
loginParams = serviceWorker.getLoginParams(this.configurationName);
} else {
Expand Down Expand Up @@ -496,7 +496,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
}
let nonce = nullNonce;
const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, configurationName);
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, configurationName, configuration.service_worker_no_auto_register);
if (serviceWorker) {
const { status, tokens } = await serviceWorker.initAsync(oidcServerConfiguration, 'syncTokensAsync', configuration);
if (status === 'LOGGED_OUT') {
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/oidc/vanilla/renewTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export async function renewTokensAndStartTimerAsync(oidc, refreshToken, forceRef
const updateTokens = (tokens) => { oidc.tokens = tokens; };
const { tokens, status } = await oidc.synchroniseTokensAsync(refreshToken, 0, forceRefresh, extras, updateTokens);

const serviceWorker = await initWorkerAsync(oidc.configuration.service_worker_relative_url, oidc.configurationName);
const serviceWorker = await initWorkerAsync(oidc.configuration.service_worker_relative_url, oidc.configurationName, oidc.configuration.service_worker_no_auto_register);
if (!serviceWorker) {
const session = initSession(oidc.configurationName, oidc.configuration.storage);
await session.setTokens(oidc.tokens);
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/oidc/vanilla/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type OidcConfiguration = {
service_worker_relative_url?:string;
service_worker_only?:boolean;
service_worker_convert_all_requests_to_cors?:boolean;
service_worker_no_auto_register?: boolean;
extras?:StringMap;
token_request_extras?:StringMap;
storage?: Storage;
Expand Down
7 changes: 7 additions & 0 deletions packages/vanilla-demo/public/main-service-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
console.log('my worker registered');

self.addEventListener('fetch', (e) => {
console.log('fetch', e.request.url);
});

importScripts('OidcServiceWorker.js');
128 changes: 66 additions & 62 deletions packages/vanilla-demo/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,66 +86,70 @@ export const configuration = {
// monitor_session: true,
};

const href = window.location.href;

const vanillaOidc = VanillaOidc.getOrCreate(fetch)(configuration);

console.log(href);


vanillaOidc.tryKeepExistingSessionAsync().then(() => {
if(href.includes(configuration.redirect_uri)){
// @ts-ignore
element.innerHTML = `<div>
<h1>@axa-fr/vanilla-oidc demo</h1>
<h2>Loading callback</h2>
</div>`;
vanillaOidc.loginCallbackAsync().then(()=>{
router.getCustomHistory().replaceState("/");
// @ts-ignore
window.logout = () => vanillaOidc.logoutAsync();
let tokens = vanillaOidc.tokens;
// @ts-ignore
element.innerHTML = `<div>
<h1>@axa-fr/vanilla-oidc demo</h1>
<button onclick="window.logout()">Logout</button>
<h2>Authenticated</h2>
<pre>${JSON.stringify(tokens,null,'\t')}</pre>
</div>`
});
return
}

let tokens = vanillaOidc.tokens;

if(tokens){

// @ts-ignore
window.logout = () => vanillaOidc.logoutAsync();
// @ts-ignore
element.innerHTML = `<div>
<h1>@axa-fr/vanilla-oidc demo</h1>
<button onclick="window.logout()">Logout</button>
<h2>Authenticated</h2>
<pre>${JSON.stringify(tokens,null,'\t')}</pre>
</div>`

}
else {
// @ts-ignore
window.login= () => {
// @ts-ignore
element.innerHTML = `<div>
<h1>@axa-fr/vanilla-oidc demo</h1>
<h2>Loading</h2>
</div>`;
vanillaOidc.loginAsync("/")
};
// @ts-ignore
element.innerHTML = `<div>
<h1>@axa-fr/vanilla-oidc demo</h1>
<button onclick="window.login()">Login</button>
</div>`
}
})
navigator.serviceWorker.register('main-service-worker.js')
// wip: let's wait 1s, to test what happens if our service worker loads earlier, before any axa-oidc stuff runs
.then(() => new Promise(r => setTimeout(r, 1000))).then(() => {
const href = window.location.href;

const vanillaOidc = VanillaOidc.getOrCreate(() => fetch)(configuration);

console.log(href);


vanillaOidc.tryKeepExistingSessionAsync().then(() => {
if(href.includes(configuration.redirect_uri)){
// @ts-ignore
element.innerHTML = `<div>
<h1>@axa-fr/vanilla-oidc demo</h1>
<h2>Loading callback</h2>
</div>`;
vanillaOidc.loginCallbackAsync().then(()=>{
router.getCustomHistory().replaceState("/");
// @ts-ignore
window.logout = () => vanillaOidc.logoutAsync();
let tokens = vanillaOidc.tokens;
// @ts-ignore
element.innerHTML = `<div>
<h1>@axa-fr/vanilla-oidc demo</h1>
<button onclick="window.logout()">Logout</button>
<h2>Authenticated</h2>
<pre>${JSON.stringify(tokens,null,'\t')}</pre>
</div>`
});
return
}

let tokens = vanillaOidc.tokens;

if(tokens){

// @ts-ignore
window.logout = () => vanillaOidc.logoutAsync();
// @ts-ignore
element.innerHTML = `<div>
<h1>@axa-fr/vanilla-oidc demo</h1>
<button onclick="window.logout()">Logout</button>
<h2>Authenticated</h2>
<pre>${JSON.stringify(tokens,null,'\t')}</pre>
</div>`

}
else {
// @ts-ignore
window.login= () => {
// @ts-ignore
element.innerHTML = `<div>
<h1>@axa-fr/vanilla-oidc demo</h1>
<h2>Loading</h2>
</div>`;
vanillaOidc.loginAsync("/")
};
// @ts-ignore
element.innerHTML = `<div>
<h1>@axa-fr/vanilla-oidc demo</h1>
<button onclick="window.login()">Login</button>
</div>`
}
})
});