react-oauth2-code-pkce
Advanced tools
Comparing version 1.17.1 to 1.17.2
@@ -180,5 +180,7 @@ "use strict"; | ||
} | ||
// Register the 'check for soon expiring access token' interval (Every 10 seconds) | ||
// Register the 'check for soon expiring access token' interval (every ~10 seconds). | ||
(0, react_1.useEffect)(() => { | ||
const interval = setInterval(() => refreshAccessToken(), 10000); // eslint-disable-line | ||
// The randomStagger is used to avoid multiple tabs logging in at the exact same time. | ||
const randomStagger = 10000 * Math.random(); | ||
const interval = setInterval(() => refreshAccessToken(), 5000 + randomStagger); | ||
return () => clearInterval(interval); | ||
@@ -196,3 +198,3 @@ }, [token, refreshToken, refreshTokenExpire, tokenExpire]); // Replace the interval with a new when values used inside refreshAccessToken changes | ||
if (!urlParams.get('code')) { | ||
// This should not happen. There should be a 'code' parameter in the url by now..." | ||
// This should not happen. There should be a 'code' parameter in the url by now... | ||
const error_description = urlParams.get('error_description') || | ||
@@ -209,3 +211,3 @@ 'Bad authorization state. Refreshing the page and log in again might solve the issue.'; | ||
try { | ||
(0, authentication_1.validateState)(urlParams); | ||
(0, authentication_1.validateState)(urlParams, config.storage); | ||
} | ||
@@ -257,3 +259,3 @@ catch (e) { | ||
refreshAccessToken(true); // Check if token should be updated | ||
}, []); // eslint-disable-line | ||
}, []); | ||
return (react_1.default.createElement(exports.AuthContext.Provider, { value: { | ||
@@ -260,0 +262,0 @@ token, |
@@ -9,2 +9,2 @@ import { TInternalConfig, TTokenResponse } from './Types'; | ||
export declare function redirectToLogout(config: TInternalConfig, token: string, refresh_token?: string, idToken?: string, state?: string, logoutHint?: string): void; | ||
export declare function validateState(urlParams: URLSearchParams): void; | ||
export declare function validateState(urlParams: URLSearchParams, storageType: TInternalConfig['storage']): void; |
@@ -19,5 +19,6 @@ "use strict"; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
// Create and store a random string in sessionStorage, used as the 'code_verifier' | ||
const storage = config.storage === 'session' ? sessionStorage : localStorage; | ||
// Create and store a random string in storage, used as the 'code_verifier' | ||
const codeVerifier = (0, pkceUtils_1.generateRandomString)(96); | ||
sessionStorage.setItem(codeVerifierStorageKey, codeVerifier); | ||
storage.setItem(codeVerifierStorageKey, codeVerifier); | ||
// Hash and Base64URL encode the code_verifier, used as the 'code_challenge' | ||
@@ -30,6 +31,6 @@ return (0, pkceUtils_1.generateCodeChallenge)(codeVerifier).then((codeChallenge) => { | ||
} | ||
sessionStorage.removeItem(stateStorageKey); | ||
storage.removeItem(stateStorageKey); | ||
const state = customState !== null && customState !== void 0 ? customState : config.state; | ||
if (state) { | ||
sessionStorage.setItem(stateStorageKey, state); | ||
storage.setItem(stateStorageKey, state); | ||
params.append('state', state); | ||
@@ -60,2 +61,3 @@ } | ||
const fetchTokens = (config) => { | ||
const storage = config.storage === 'session' ? sessionStorage : localStorage; | ||
/* | ||
@@ -68,3 +70,3 @@ The browser has been redirected from the authentication endpoint with | ||
const authCode = urlParams.get('code'); | ||
const codeVerifier = window.sessionStorage.getItem(codeVerifierStorageKey); | ||
const codeVerifier = storage.getItem(codeVerifierStorageKey); | ||
if (!authCode) { | ||
@@ -100,5 +102,6 @@ throw Error("Parameter 'code' not found in URL. \nHas authentication taken place?"); | ||
exports.redirectToLogout = redirectToLogout; | ||
function validateState(urlParams) { | ||
function validateState(urlParams, storageType) { | ||
const storage = storageType === 'session' ? sessionStorage : localStorage; | ||
const receivedState = urlParams.get('state'); | ||
const loadedState = sessionStorage.getItem(stateStorageKey); | ||
const loadedState = storage.getItem(stateStorageKey); | ||
if (receivedState !== loadedState) { | ||
@@ -105,0 +108,0 @@ throw new Error('"state" value received from authentication server does no match client request. Possible cross-site request forgery'); |
@@ -29,3 +29,3 @@ "use strict"; | ||
catch (error) { | ||
console.log(`Failed to store value '${value}' for key '${key}'`); | ||
console.error(`Failed to store value '${value}' for key '${key}'`); | ||
} | ||
@@ -37,3 +37,13 @@ }; | ||
if (event.storageArea === storage && event.key === key) { | ||
setStoredValue(JSON.parse((_a = event.newValue) !== null && _a !== void 0 ? _a : '')); | ||
if (event.newValue === null) { | ||
setStoredValue(undefined); | ||
} | ||
else { | ||
try { | ||
setStoredValue(JSON.parse((_a = event.newValue) !== null && _a !== void 0 ? _a : '')); | ||
} | ||
catch (error) { | ||
console.warn(`Failed to handle storageEvent's newValue='${event.newValue}' for key '${key}'`); | ||
} | ||
} | ||
} | ||
@@ -40,0 +50,0 @@ }; |
{ | ||
"name": "react-oauth2-code-pkce", | ||
"version": "1.17.1", | ||
"version": "1.17.2", | ||
"description": "Provider agnostic react package for OAuth2 Authorization Code flow with PKCE", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -184,5 +184,15 @@ # react-oauth2-code-pkce · [](https://github.com/soofstad/react-oauth2-pkce/blob/main/LICENSE) [](https://www.npmjs.com/package/react-oauth2-code-pkce)  | ||
This library expects to have a `localStorage` available. That is not the case when compiling Next.js projects serverside. | ||
This library expects to have a `localStorage` (or `sessionStorage`) available. That is not the case when compiling Next.js projects serverside. | ||
See: https://github.com/soofstad/react-oauth2-pkce/discussions/90 for a solution. | ||
### Error `Bad authorization state...` | ||
This is most likely to happen if the authentication at the identity provider got aborted in some way. | ||
You might also see the error `Expected to find a '?code=' parameter in the URL by now. Did the authentication get aborted or interrupted?` in the console. | ||
First of all, you should handle any errors the library throws. Usually, hinting at the user reload the page is enough. | ||
Some known causes for this is that instead of logging in at the auth provider, the user "Registers" or "Reset password" or | ||
something similar instead. Any such functions should be handled outside of this library, with separate buttons/links than the Login-button. | ||
### After redirect back from auth provider with `?code`, no token request is made | ||
@@ -193,3 +203,3 @@ | ||
This could also happend if some routes in your app are not wrapped by the `<AuthProvider>`. | ||
This could also happen if some routes in your app are not wrapped by the `<AuthProvider>`. | ||
@@ -196,0 +206,0 @@ ### The page randomly refreshes in the middle of a session |
49379
789
219