Created
December 7, 2020 18:45
-
-
Save DirkWolthuis/055f7e5f4dee27782a11fb4d1b49f139 to your computer and use it in GitHub Desktop.
Svelte context + store example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script lang="ts"> | |
import createAuth0Client, { Auth0Client } from "@auth0/auth0-spa-js"; | |
import { onMount, setContext } from "svelte"; | |
import { writable } from "svelte/store"; | |
const isLoading = writable(true); | |
const isAuthenticated = writable(false); | |
const authToken = writable(""); | |
const userInfo = writable({}); | |
const authError = writable(null); | |
const AUTH_KEY = "AUTHENTICATION"; | |
const authService = writable<Auth0Client>(null); | |
const refreshRate = 10 * 60 * 60 * 1000; | |
let auth0: Auth0Client = null; | |
let intervalId = undefined; | |
onMount(async () => { | |
const auth0 = await createAuth0Client({ | |
domain: __dndtables.env.AUTH0_DOMAIN, | |
client_id: __dndtables.env.AUTH0_CLIENT_ID, | |
}); | |
authService.set(auth0); | |
// Not all browsers support this, please program defensively! | |
const params = new URLSearchParams(window.location.search); | |
// Check if something went wrong during login redirect | |
// and extract the error message | |
if (params.has("error")) { | |
authError.set(new Error(params.get("error_description"))); | |
} | |
// if code then login success | |
if (params.has("code")) { | |
// Let the Auth0 SDK do it's stuff - save some state, etc. | |
await auth0.handleRedirectCallback(); | |
// Can be smart here and redirect to original path instead of root | |
window.history.replaceState({}, document.title, "/"); | |
authError.set(null); | |
} | |
const _isAuthenticated = await auth0.isAuthenticated(); | |
isAuthenticated.set(_isAuthenticated); | |
if (_isAuthenticated) { | |
// while on it, fetch the user info | |
userInfo.set(await auth0.getUser()); | |
// Get the access token. Make sure to supply audience property | |
// in Auth0 config, otherwise you will soon start throwing stuff! | |
const token = await auth0.getTokenSilently(); | |
authToken.set(token); | |
// refresh token after specific period or things will stop | |
// working. Useful for long-lived apps like dashboards. | |
intervalId = setInterval(async () => { | |
authToken.set(await auth0.getTokenSilently()); | |
}, refreshRate); | |
} | |
isLoading.set(false); | |
// clear token refresh interval on component unmount | |
return () => { | |
intervalId && clearInterval(intervalId); | |
}; | |
}); | |
// Provide a redirect page if you need. | |
// It must be whitelisted in Auth0. I think. | |
const login = async () => { | |
let authInstance: Auth0Client; | |
const unsubscribe = authService.subscribe(auth => authInstance = auth); | |
await authInstance.loginWithRedirect({ | |
redirect_uri: window.location.origin, | |
prompt: "login", // Force login prompt. No silence auth for you! | |
}); | |
unsubscribe(); | |
}; | |
const logout = () => { | |
let authInstance: Auth0Client; | |
const unsubscribe = authService.subscribe(auth => authInstance = auth); | |
authInstance.logout({ | |
returnTo: window.location.origin, | |
}); | |
unsubscribe(); | |
}; | |
const auth = { | |
isLoading, | |
isAuthenticated, | |
authToken, | |
authError, | |
login, | |
logout, | |
userInfo, | |
}; | |
// Put everything in context so that child | |
// components can access the state | |
setContext(AUTH_KEY, auth); | |
</script> | |
<slot /> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment