UNPKG

react-ketting

Version:
162 lines 7.18 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RequireLogin = void 0; const React = require("react"); const use_client_1 = require("../hooks/use-client"); const ketting_1 = require("ketting"); const { useEffect, useState } = React; const LOCALSTORAGEKEY = 'ketting-auth:3'; /** * The RequireLogin component ensures that a user is authenticated. * * Children will not be rendered until this is the case. */ const RequireLogin = (props) => { const [isAuthenticated, setAuthenticated] = useState(false); const client = (0, use_client_1.useClient)(); const validateToken = async () => { const location = new URL(document.location.href); if (location.search) { // If we have a 'code' query parameter, the client will attempt to authenticate with // the code via oauth2 and attempt to redirect back to your url const searchParams = new URLSearchParams(location.search.substr(1)); if (searchParams.has('code')) { const code = searchParams.get('code'); // This 'state' is the OAuth2 state, and we're using it to put a // relative url where the user needs to go (in app) after // authentication. const state = searchParams.get('state') || null; await processCodeFromUrl(code, state); return; } } // If we got this far in the function, there was no 'code' in the url. // Lets check if we have credentials in LocalStorage. const localStorageAuth = window.localStorage.getItem(LOCALSTORAGEKEY); if (localStorageAuth) { // this doesnt feel like a good variable name const parsedToken = JSON.parse(localStorageAuth); client.use((0, ketting_1.oauth2)({ grantType: undefined, clientId: props.clientId, tokenEndpoint: props.tokenEndpoint, onTokenUpdate: (token) => storeKettingCredentialsInLocalStorage(token), onAuthError: err => { console.error('[ketting] Got a deep 401 error, lets re-authenticate'); // IF we got here it means we didn't have tokens in LocalStorage, or they // were expired. document.location.href = getAuthorizeUri(props); } }, parsedToken)); // Lets test auth. try { if (props.testEndpoint === null) { console.info('[ketting] Using stored credentials. testEndpoint is disabled.'); setAuthenticated(true); } else { const testResource = client.go(props.testEndpoint); console.info('[ketting] Testing stored credentials on %s', testResource.uri); await testResource.get(); console.info('[ketting] Stored credentials were accepted'); // Authentication succeeded setAuthenticated(true); // End function return; } } catch (err) { switch (err.httpCode) { case 400: if (err.oauth2Code === 'invalid_grant') { console.info('Refresh token might already have been used, or invalid or expired. Lets re-authenticate'); } else { console.error('[ketting] ', err); throw new Error('Got error while accessing api: ' + err.httpCode); } break; case 401: console.info('[ketting] Stored credentials were not valid. Lets re-authenticate'); break; default: console.error('[ketting] ', err); throw new Error('Got error while accessing api: ' + err.httpCode); } } } else { console.info('[ketting] No stored credentials. Redirecting to auth API api'); } // IF we got here it means we didn't have tokens in LocalStorage, or they // were expired. document.location.href = getAuthorizeUri(props); }; useEffect(() => { validateToken().catch(err => { console.error('[ketting] Error while validating token', err); }); }, [client]); if (isAuthenticated) { return React.createElement(React.Fragment, null, props.children); } /** * This function gets called when we get redirected back from a OAuth2 * authorization endpoint. */ const processCodeFromUrl = async (code, state) => { client.use((0, ketting_1.oauth2)({ grantType: 'authorization_code', clientId: props.clientId, tokenEndpoint: props.tokenEndpoint, redirectUri: document.location.origin + '/', code: code, onTokenUpdate: (token) => storeKettingCredentialsInLocalStorage(token), onAuthError: err => { console.error('[ketting] Got a deep 401 error, lets re-authenticate'); // IF we got here it means we didn't have tokens in LocalStorage, or they // were expired. document.location.href = getAuthorizeUri(props); } })); // Lets test authentication. try { await client.go().get(); } catch (err) { throw new Error('Error from API after authenticating: ' + err); } setAuthenticated(true); props.onSuccess(state); }; const storeKettingCredentialsInLocalStorage = async (token) => { // Store credentials. // ? Should this be custom-set by the user? window.localStorage.setItem(LOCALSTORAGEKEY, JSON.stringify(token)); }; // We return a generic "Authenticating" component while the useEffect is...in effect // A custom "authenticating" component can also be passed in instead return (React.createElement(React.Fragment, null, props.authenticatingComponent ? (props.authenticatingComponent) : (React.createElement("div", { className: 'authenticating' }, React.createElement("header", null, React.createElement("h1", null, "Authenticating")))))); }; exports.RequireLogin = RequireLogin; /** * Generates the full URL to redirect the user to for the OAuth2 authorization * endpoint. */ function getAuthorizeUri(props) { const currentRoot = document.location.origin + '/'; const currentPath = document.location.pathname; const params = new URLSearchParams([ ['response_type', 'code'], ['client_id', props.clientId], ['redirect_uri', currentRoot], ['state', currentPath], ]); return props.authorizeEndpoint + '?' + params.toString(); } //# sourceMappingURL=RequireLogin.js.map