react-oauth2-code-pkce
Advanced tools
Comparing version 1.1.3 to 1.2.0
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; | ||
result["default"] = mod; | ||
return result; | ||
@@ -25,3 +13,2 @@ }; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.AuthProvider = exports.AuthContext = void 0; | ||
var react_1 = __importStar(require("react")); | ||
@@ -31,12 +18,13 @@ var authentication_1 = require("./authentication"); | ||
var validateAuthConfig_1 = require("./validateAuthConfig"); | ||
exports.AuthContext = (0, react_1.createContext)({}); | ||
var AuthProvider = function (_a) { | ||
exports.AuthContext = react_1.createContext({}); | ||
exports.AuthProvider = function (_a) { | ||
var authConfig = _a.authConfig, children = _a.children; | ||
var _b = (0, Hooks_1.default)('ROCP_refreshToken', null), refreshToken = _b[0], setRefreshToken = _b[1]; | ||
var _c = (0, Hooks_1.default)('ROCP_token', null), token = _c[0], setToken = _c[1]; | ||
var _d = (0, Hooks_1.default)('ROCP_idToken', null), idToken = _d[0], setIdToken = _d[1]; | ||
var _e = (0, Hooks_1.default)('ROCP_loginInProgress', false), loginInProgress = _e[0], setLoginInProgress = _e[1]; | ||
var _f = (0, react_1.useState)(), tokenData = _f[0], setTokenData = _f[1]; | ||
var _g = (0, react_1.useState)(null), error = _g[0], setError = _g[1]; | ||
(0, validateAuthConfig_1.validateAuthConfig)(authConfig); | ||
var _b = Hooks_1.default('ROCP_refreshToken', null), refreshToken = _b[0], setRefreshToken = _b[1]; | ||
var _c = Hooks_1.default('ROCP_token', null), token = _c[0], setToken = _c[1]; | ||
var _d = Hooks_1.default('ROCP_idToken', null), idToken = _d[0], setIdToken = _d[1]; | ||
var _e = Hooks_1.default('ROCP_loginInProgress', false), loginInProgress = _e[0], setLoginInProgress = _e[1]; | ||
var _f = react_1.useState(), tokenData = _f[0], setTokenData = _f[1]; | ||
var _g = react_1.useState(null), error = _g[0], setError = _g[1]; | ||
var interval; | ||
validateAuthConfig_1.validateAuthConfig(authConfig); | ||
function logOut() { | ||
@@ -54,5 +42,30 @@ setRefreshToken(null); | ||
setLoginInProgress(false); | ||
setTokenData((0, authentication_1.decodeToken)(response.access_token)); | ||
setTokenData(authentication_1.decodeToken(response.access_token)); | ||
} | ||
(0, react_1.useEffect)(function () { | ||
function refreshAccessToken() { | ||
if (refreshToken) { | ||
if (authentication_1.tokenExpired(token)) { // The client has an expired token. Will try to get a new one with the refreshToken | ||
authentication_1.fetchWithRefreshToken({ authConfig: authConfig, refreshToken: refreshToken }) | ||
.then(function (result) { return handleTokenResponse(result); }) | ||
.catch(function (error) { | ||
console.log(error); | ||
setError(error.message); | ||
}); | ||
} | ||
else { // The client still has a valid token | ||
setTokenData(authentication_1.decodeToken(token)); | ||
} | ||
} | ||
else { // No refresh_token | ||
console.error("Tried to refresh token without a refresh token. Clearing state..."); | ||
setError('Bad authorization state. Refreshing the page might solve the issue.'); | ||
} | ||
} | ||
// Register the 'check for soon expiring access token' interval (Every minute) | ||
react_1.useEffect(function () { | ||
interval = setInterval(function () { return refreshAccessToken(); }, 60000); | ||
return function () { return clearInterval(interval); }; | ||
}, [token]); // This token dependency removes the old, and registers a new Interval when a new token is fetched. | ||
// Runs once on page load | ||
react_1.useEffect(function () { | ||
if (loginInProgress) { // The client has been redirected back from the Auth endpoint with an auth code | ||
@@ -68,14 +81,13 @@ var urlParams = new URLSearchParams(window.location.search); | ||
else { // Request token from auth server with the auth code | ||
(0, authentication_1.getTokens)(authConfig).then(function (response) { | ||
if (!response.ok) { | ||
console.error(response.body.error_description); | ||
setError(response.body.error_description); | ||
} | ||
else { | ||
handleTokenResponse(response.body); | ||
history.replaceState(null, "", location.pathname); // Clear ugly url params | ||
// Call any postLogin function in authConfig | ||
if (authConfig === null || authConfig === void 0 ? void 0 : authConfig.postLogin) | ||
authConfig.postLogin(); | ||
} | ||
authentication_1.fetchTokens(authConfig) | ||
.then(function (tokens) { | ||
handleTokenResponse(tokens); | ||
history.replaceState(null, "", location.pathname); // Clear ugly url params | ||
// Call any postLogin function in authConfig | ||
if (authConfig === null || authConfig === void 0 ? void 0 : authConfig.postLogin) | ||
authConfig.postLogin(); | ||
}) | ||
.catch(function (error) { | ||
console.error(error); | ||
setError(error); | ||
}); | ||
@@ -86,20 +98,6 @@ } | ||
setLoginInProgress(true); | ||
(0, authentication_1.login)(authConfig); | ||
authentication_1.login(authConfig); | ||
} | ||
else if (refreshToken) { // A refresh token is stored in client | ||
if ((0, authentication_1.tokenExpired)(token)) { // The client has an expired token. Will try to get a new one with the refreshToken | ||
(0, authentication_1.getAccessTokenFromRefreshToken)({ authConfig: authConfig, refreshToken: refreshToken }) | ||
.then(function (_a) { | ||
var response = _a.response; | ||
handleTokenResponse(response); | ||
}) | ||
.catch(function (error) { | ||
console.error(error); | ||
setLoginInProgress(true); | ||
(0, authentication_1.login)(authConfig); | ||
}); | ||
} | ||
else { // The client still has a valid token | ||
setTokenData((0, authentication_1.decodeToken)(token)); | ||
} | ||
else { | ||
refreshAccessToken(); // Check if token should be updated and sets tokenData | ||
} | ||
@@ -109,2 +107,1 @@ }, []); | ||
}; | ||
exports.AuthProvider = AuthProvider; |
import { TAuthConfig, TTokenData } from "./Types"; | ||
export declare function login(authConfig: TAuthConfig): Promise<void>; | ||
export declare const getTokens: (authConfig: TAuthConfig) => Promise<any>; | ||
export declare const getAccessTokenFromRefreshToken: ({ authConfig, refreshToken }: any) => Promise<any>; | ||
export declare const fetchTokens: (authConfig: TAuthConfig) => Promise<any>; | ||
export declare const fetchWithRefreshToken: (props: { | ||
authConfig: TAuthConfig; | ||
refreshToken: string; | ||
}) => Promise<any>; | ||
/** | ||
@@ -11,4 +14,4 @@ * Decodes the the base64 encoded JWT. Returns a TToken. | ||
* Check if the Access Token has expired by looking at the 'exp' JWT header. | ||
* Will return True if the token has expired, OR there is less than 30min until it expires. | ||
* Will return True if the token has expired, OR there is less than 10min until it expires. | ||
*/ | ||
export declare const tokenExpired: (token: string) => Boolean; |
@@ -39,3 +39,2 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.tokenExpired = exports.decodeToken = exports.getAccessTokenFromRefreshToken = exports.getTokens = exports.login = void 0; | ||
var pkceUtils_1 = require("./pkceUtils"); | ||
@@ -47,6 +46,6 @@ var codeVerifierStorageKey = "PKCE_code_verifier"; | ||
return __generator(this, function (_a) { | ||
codeVerifier = (0, pkceUtils_1.generateRandomString)(40); | ||
codeVerifier = pkceUtils_1.generateRandomString(40); | ||
localStorage.setItem(codeVerifierStorageKey, codeVerifier); | ||
// Hash and Base64URL encode the code_verifier, used as the 'code_challenge' | ||
(0, pkceUtils_1.generateCodeChallenge)(codeVerifier).then(function (codeChallenge) { | ||
pkceUtils_1.generateCodeChallenge(codeVerifier).then(function (codeChallenge) { | ||
// Set query parameters and redirect user to OAuth2 authentication endpoint | ||
@@ -71,3 +70,3 @@ var params = new URLSearchParams({ | ||
exports.login = login; | ||
var getTokens = function (authConfig) { | ||
exports.fetchTokens = function (authConfig) { | ||
/* | ||
@@ -98,28 +97,34 @@ The browser has been redirected from the authentication endpoint with | ||
}) | ||
.then(function (response) { return response.json().then(function (body) { return ({ ok: response.ok, body: body }); }); }) | ||
.catch(function (error) { | ||
console.log(error); | ||
}); | ||
.then(function (response) { return response.json().then(function (body) { | ||
if (!response.ok) { | ||
console.error(body.error_description); | ||
throw body.error_description; | ||
} | ||
return body; | ||
}); }); | ||
}; | ||
exports.getTokens = getTokens; | ||
var getAccessTokenFromRefreshToken = function (_a) { | ||
var authConfig = _a.authConfig, refreshToken = _a.refreshToken; | ||
var params = new URLSearchParams({ | ||
client_id: authConfig.clientId, | ||
grant_type: 'refresh_token', | ||
refresh_token: refreshToken, | ||
}); | ||
var url = new URL(authConfig.tokenEndpoint); | ||
url.search = params.toString(); | ||
return fetch(url.toString(), { method: 'POST' }) | ||
.then(function (response) { return response.json(); }) | ||
.catch(function (error) { | ||
console.error("Failed to fetch AccessToken with RefreshToken: " + error); | ||
}); | ||
exports.fetchWithRefreshToken = function (props) { | ||
var authConfig = props.authConfig, refreshToken = props.refreshToken; | ||
var formData = new FormData(); | ||
formData.append('grant_type', 'refresh_token'); | ||
formData.append('refresh_token', refreshToken); | ||
formData.append('scope', authConfig.scope || ""); | ||
formData.append('client_id', authConfig.clientId); | ||
formData.append('redirect_uri', authConfig.redirectUri); | ||
return fetch(authConfig.tokenEndpoint, { | ||
method: 'POST', | ||
body: formData, | ||
}) | ||
.then(function (response) { return response.json().then(function (body) { | ||
if (!response.ok) { | ||
console.error(body.error_description); | ||
throw body.error_description; | ||
} | ||
return body; | ||
}); }); | ||
}; | ||
exports.getAccessTokenFromRefreshToken = getAccessTokenFromRefreshToken; | ||
/** | ||
* Decodes the the base64 encoded JWT. Returns a TToken. | ||
*/ | ||
var decodeToken = function (token) { | ||
exports.decodeToken = function (token) { | ||
var base64Url = token.split('.')[1]; | ||
@@ -135,13 +140,11 @@ var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); | ||
}; | ||
exports.decodeToken = decodeToken; | ||
/** | ||
* Check if the Access Token has expired by looking at the 'exp' JWT header. | ||
* Will return True if the token has expired, OR there is less than 30min until it expires. | ||
* Will return True if the token has expired, OR there is less than 10min until it expires. | ||
*/ | ||
var tokenExpired = function (token) { | ||
var bufferTimeInMilliseconds = 30 * 60 * 1000; // minutes * seconds * toMilliseconds | ||
var exp = (0, exports.decodeToken)(token).exp; | ||
exports.tokenExpired = function (token) { | ||
var bufferTimeInMilliseconds = 10 * 60 * 1000; // minutes * seconds * toMilliseconds | ||
var exp = exports.decodeToken(token).exp; | ||
var expirationTimeWithBuffer = new Date(exp * 1000 - bufferTimeInMilliseconds); | ||
return new Date() > expirationTimeWithBuffer; | ||
}; | ||
exports.tokenExpired = tokenExpired; |
@@ -5,3 +5,3 @@ "use strict"; | ||
function useLocalStorage(key, initialValue) { | ||
var _a = (0, react_1.useState)(function () { | ||
var _a = react_1.useState(function () { | ||
try { | ||
@@ -8,0 +8,0 @@ var item = localStorage.getItem(key); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.AuthContext = exports.AuthProvider = void 0; | ||
var AuthContext_1 = require("./AuthContext"); | ||
Object.defineProperty(exports, "AuthProvider", { enumerable: true, get: function () { return AuthContext_1.AuthProvider; } }); | ||
Object.defineProperty(exports, "AuthContext", { enumerable: true, get: function () { return AuthContext_1.AuthContext; } }); | ||
exports.AuthProvider = AuthContext_1.AuthProvider; | ||
exports.AuthContext = AuthContext_1.AuthContext; |
@@ -39,3 +39,2 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.generateCodeChallenge = exports.generateRandomString = exports.getRandomInteger = void 0; | ||
function getRandomInteger(range) { | ||
@@ -42,0 +41,0 @@ var max_range = 256; // Highest possible number in Uint8 |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.validateAuthConfig = void 0; | ||
function stringIsUnset(value) { | ||
@@ -5,0 +4,0 @@ var unset = ["", undefined, null]; |
{ | ||
"name": "react-oauth2-code-pkce", | ||
"version": "1.1.3", | ||
"version": "1.2.0", | ||
"description": "Plug-and-play react package for OAuth2 Authorization Code flow with PKCE", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
24073