mirror of
https://github.com/TECHNOFAB11/svelte-oidc.git
synced 2025-12-11 23:50:06 +01:00
fix: context must be loaded on initialization
svelte 3.25 and later won't let you call getContext and setContext outside of component initialization. This means you need to implement components inside the Auth0Context that getContext on initialization then pass them to functions BREAKING CHANGE: function signature for login, logout, and refreshToken
This commit is contained in:
parent
c35df91c73
commit
e4cf984082
8 changed files with 766 additions and 500 deletions
1171
package-lock.json
generated
1171
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@dopry/svelte-oidc",
|
||||
"version": "0.3.1",
|
||||
"version": "1.0.0",
|
||||
"repository": "https://github.com/dopry/svelte-oidc",
|
||||
"description": "Svelte OIDC Component Library",
|
||||
"keywords": [
|
||||
|
|
@ -71,8 +71,8 @@
|
|||
"rollup-plugin-terser": "7.0.2",
|
||||
"sirv-cli": "1.0.6",
|
||||
"start-server-and-test": "1.12.0",
|
||||
"svelte": "3.24.1",
|
||||
"svelte-highlight": "0.6.2",
|
||||
"svelte-preprocess": "4.0.11"
|
||||
"svelte": "3.35.0",
|
||||
"svelte-highlight": "0.7.1",
|
||||
"svelte-preprocess": "4.6.9"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import { json } from 'svelte-highlight/languages';
|
|||
import { arduinoLight as highlightTheme } from "svelte-highlight/styles";
|
||||
import {
|
||||
OidcContext,
|
||||
LoginButton,
|
||||
LogoutButton,
|
||||
RefreshTokenButton,
|
||||
authError,
|
||||
idToken,
|
||||
accessToken,
|
||||
|
|
@ -27,10 +30,9 @@ import {
|
|||
redirect_uri="process.env.OIDC_REDIRECT_URI"
|
||||
post_logout_redirect_uri="process.env.OIDC_POST_LOGOUT_REDIRECT_URI"
|
||||
>
|
||||
|
||||
<button class="btn" on:click|preventDefault='{() => login() }'>Login</button>
|
||||
<button class="btn" on:click|preventDefault='{() => logout() }'>Logout</button>
|
||||
<button class="btn" on:click|preventDefault='{() => refreshToken() }'>refreshToken</button>
|
||||
<LoginButton>Login</LoginButton>
|
||||
<LogoutButton>Logout</LogoutButton>
|
||||
<RefreshTokenButton>refreshToken</RefreshTokenButton>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th style="width: 20%;">store</th><th style="width: 80%;">value</th></tr>
|
||||
|
|
|
|||
14
src/components/LoginButton.svelte
Normal file
14
src/components/LoginButton.svelte
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
import {
|
||||
OIDC_CONTEXT_CLIENT_PROMISE,
|
||||
OIDC_CONTEXT_REDIRECT_URI,
|
||||
login,
|
||||
} from './OidcContext.svelte';
|
||||
|
||||
const oidcPromise = getContext(OIDC_CONTEXT_CLIENT_PROMISE)
|
||||
export let callback_url = getContext(OIDC_CONTEXT_REDIRECT_URI)
|
||||
export let preserveRoute
|
||||
</script>
|
||||
|
||||
<button class="btn" on:click|preventDefault='{() => login(oidcPromise, preserveRoute, callback_url) }'><slot></slot></button>
|
||||
13
src/components/LogoutButton.svelte
Normal file
13
src/components/LogoutButton.svelte
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
import {
|
||||
OIDC_CONTEXT_CLIENT_PROMISE,
|
||||
OIDC_CONTEXT_POST_LOGOUT_REDIRECT_URI,
|
||||
logout,
|
||||
} from './OidcContext.svelte';
|
||||
|
||||
const oidcPromise = getContext(OIDC_CONTEXT_CLIENT_PROMISE)
|
||||
export let logout_url = getContext(OIDC_CONTEXT_POST_LOGOUT_REDIRECT_URI)
|
||||
</script>
|
||||
|
||||
<button class="btn" on:click|preventDefault='{() => logout(oidcPromise, logout_url) }'><slot></slot></button>
|
||||
|
|
@ -28,12 +28,14 @@
|
|||
|
||||
/**
|
||||
* Refresh the accessToken using the silentRenew method (hidden iframe)
|
||||
*
|
||||
* @param {Promise<UserManager>} oidcPromise
|
||||
* @return bool indicated whether the token was refreshed, if false error will be set
|
||||
* in the authError store.
|
||||
*/
|
||||
export async function refreshToken() {
|
||||
export async function refreshToken(oidcPromise) {
|
||||
try {
|
||||
const oidc = await getContext(OIDC_CONTEXT_CLIENT_PROMISE);
|
||||
const oidc = await oidcPromise
|
||||
await oidc.signinSilent();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -47,12 +49,13 @@
|
|||
/**
|
||||
* Initiate Register/Login flow.
|
||||
*
|
||||
* @param {Promise<UserManager>} oidcPromise
|
||||
* @param {boolean} preserveRoute - store current location so callback handler will navigate back to it.
|
||||
* @param {string} callback_url - explicit path to use for the callback.
|
||||
*/
|
||||
export async function login(preserveRoute = true, callback_url = null) {
|
||||
const oidc = await getContext(OIDC_CONTEXT_CLIENT_PROMISE);
|
||||
const redirect_uri = callback_url || getContext(OIDC_CONTEXT_REDIRECT_URI) || window.location.href;
|
||||
export async function login(oidcPromise, preserveRoute = true, callback_url = null) {
|
||||
const oidc = await oidcPromise;
|
||||
const redirect_uri = callback_url || window.location.href;
|
||||
|
||||
// try to keep the user on the same page from which they triggered login. If set to false should typically
|
||||
// cause redirect to /.
|
||||
|
|
@ -68,11 +71,12 @@
|
|||
/**
|
||||
* Log out the current user.
|
||||
*
|
||||
* @param {Promise<UserManager>} oidcPromise
|
||||
* @param {string} logout_url - specify the url to return to after login.
|
||||
*/
|
||||
export async function logout(logout_url = null) {
|
||||
const oidc = await getContext(OIDC_CONTEXT_CLIENT_PROMISE);
|
||||
const returnTo = logout_url || getContext(OIDC_CONTEXT_POST_LOGOUT_REDIRECT_URI) || window.location.href;
|
||||
export async function logout(oidcPromise, logout_url = null) {
|
||||
const oidc = await oidcPromise;
|
||||
const returnTo = logout_url || window.location.href;
|
||||
oidc.signoutRedirect({ returnTo });
|
||||
}
|
||||
</script>
|
||||
|
|
@ -120,9 +124,8 @@
|
|||
});
|
||||
|
||||
|
||||
// userManager needs to be wrapped in a promise and the work
|
||||
// needs to be done onMount to otherwise there is an
|
||||
// Error: Function called outside component initialization
|
||||
// does userManager needs to be wrapped in a promise? or is this a left over to maintain
|
||||
// symmetry with the @dopry/svelte-auth0 auth0 implementation
|
||||
let oidcPromise = Promise.resolve(userManager);
|
||||
setContext(OIDC_CONTEXT_CLIENT_PROMISE, oidcPromise);
|
||||
|
||||
|
|
@ -132,7 +135,7 @@
|
|||
// Use 'error' and 'code' to test if the component is being executed as a part of a login callback. If we're not
|
||||
// running in a login callback, and the user isn't logged in, see if we can capture their existing session.
|
||||
if (!params.has('error') && !params.has('code') && !$isAuthenticated) {
|
||||
refreshToken();
|
||||
refreshToken(oidcPromise);
|
||||
}
|
||||
|
||||
async function handleOnMount() {
|
||||
|
|
@ -165,6 +168,7 @@
|
|||
// what the uris loook like. I fear this may be problematic in other auth flows in the future.
|
||||
else if (params.has('state')) {
|
||||
const response = await oidc.signinCallback();
|
||||
console.log('oidc.signinCallback::response', response)
|
||||
}
|
||||
isLoading.set(false);
|
||||
}
|
||||
|
|
|
|||
11
src/components/RefreshTokenButton.svelte
Normal file
11
src/components/RefreshTokenButton.svelte
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
import {
|
||||
OIDC_CONTEXT_CLIENT_PROMISE,
|
||||
refreshToken,
|
||||
} from './OidcContext.svelte';
|
||||
|
||||
const oidcPromise = getContext(OIDC_CONTEXT_CLIENT_PROMISE)
|
||||
</script>
|
||||
|
||||
<button class="btn" on:click|preventDefault='{() => refreshToken(oidcPromise) }'><slot></slot></button>
|
||||
|
|
@ -10,4 +10,7 @@ export {
|
|||
refreshToken,
|
||||
userInfo,
|
||||
} from './OidcContext.svelte';
|
||||
export { default as LoginButton} from './LoginButton.svelte'
|
||||
export { default as LogoutButton} from './LogoutButton.svelte'
|
||||
export { default as RefreshTokenButton} from './RefreshTokenButton.svelte'
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue