diff --git a/src/lib/createAuthContext.js b/src/lib/createAuthContext.js
index a2bfbb3..b0a8efc 100644
--- a/src/lib/createAuthContext.js
+++ b/src/lib/createAuthContext.js
@@ -5,6 +5,7 @@ import { fetchToken } from './helpers/fetchToken'
import { removeCodeFromLocation } from './helpers/removeCodeFromLocation'
import { getVerifierFromStorage } from './helpers/getVerifierFromStorage'
import { removeVerifierFromStorage } from './helpers/removeVerifierFromStorage'
+import {exchangeRefreshForAccessToken} from './helpers/exchangeRefreshForAccessToken'
export default ({
clientId,
@@ -39,10 +40,24 @@ export default ({
}
const useToken = () => {
- const { token } = useContext(context)
- if (!token) {
- console.warn(`Trying to useToken() while not being authenticated.\nMake sure to useToken() only inside of an component.`)
- }
+ const { token, setToken } = useContext(context)
+ useEffect(() => {
+ if (token) {
+ const now = new Date()
+ const elapsed = new Date(token.expires_at).getTime() - now.getTime()
+ const slack = 10000
+ if(token.refresh_token) {
+ const timer = setTimeout(() =>exchangeRefreshForAccessToken({clientId, clientSecret, tokenEndpoint, fetch , token })
+ .then(response => {
+ setToken(response)
+ }),elapsed - slack )
+ return () => clearTimeout(timer)
+ }
+ } else {
+ console.warn(`Trying to useToken() while not being authenticated.\nMake sure to useToken() only inside of an component.`)
+ }
+ },[token])
+
return token
}
@@ -56,6 +71,7 @@ export default ({
if (!token) {
const code = getCodeFromLocation({ location: window.location })
const verifier = getVerifierFromStorage({ clientId, storage })
+ const slackSeconds = 10
if (code && verifier) {
fetchToken({
clientId, clientSecret, tokenEndpoint, code, verifier, fetch
@@ -63,7 +79,7 @@ export default ({
.then(setToken)
.then(() => {
removeCodeFromLocation()
- removeVerifierFromStorage({ clientId, storage })
+ removeVerifierFromStorage({ clientId, storage })
})
.catch(e => {
console.error(e)
@@ -81,7 +97,7 @@ export default ({
}
return (
-
+
{children}
)
diff --git a/src/lib/helpers/exchangeRefreshForAccessToken.js b/src/lib/helpers/exchangeRefreshForAccessToken.js
new file mode 100644
index 0000000..601f1a7
--- /dev/null
+++ b/src/lib/helpers/exchangeRefreshForAccessToken.js
@@ -0,0 +1,35 @@
+export const exchangeRefreshForAccessToken = ({ clientId, clientSecret, tokenEndpoint, fetch = window.fetch, token }) => {
+ const payload = {
+ client_secret: clientSecret,
+ client_id: clientId,
+ grant_type: "refresh_token",
+ scope: "openid, profile",
+ refresh_token: token.refresh_token
+ };
+ return fetch(tokenEndpoint, {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ },
+ method: 'POST',
+ body: new window.URLSearchParams(payload)
+ })
+ .then(r => {
+ if (!r.ok) {
+ throw new Error(`Token response not ok, status is ${r.status}, check the react-u5auth configuration (wrong provider or token endpoint?)`);
+ }
+ return r.json();
+ })
+ .then(token => {
+ const { expires_in } = token;
+ if (expires_in && Number.isFinite(expires_in)) {
+ const slackSeconds = 10;
+ // add 'expires_at', with the given slack
+ token.expires_at = new Date(new Date().getTime() + expires_in * 1000 - (slackSeconds * 1000));
+ }
+ return token;
+ })
+ .catch(err => {
+ console.error('ERR (fetch)', err);
+ throw err;
+ });
+}