Commit bb742fa1 authored by Robert Knight's avatar Robert Knight

Extract `getGrantToken` helper

Put the logic for getting the grant token in one place so it can be
better documented.

Also remove or simplify some other code slightly upon a second reading.
parent 0355bc53
...@@ -180,29 +180,34 @@ export class AuthService extends TinyEmitter { ...@@ -180,29 +180,34 @@ export class AuthService extends TinyEmitter {
/** /**
* Exchange authorization code retrieved from login popup for a new * Exchange authorization code retrieved from login popup for a new
* access token. * access token.
*
* @param {string} code
*/ */
const exchangeAuthCodeForToken = async () => { const exchangeAuthCodeForToken = async code => {
const code = /** @type {string} */ (authCode);
authCode = null; // Auth codes can only be used once.
const client = await oauthClient(); const client = await oauthClient();
const tokenInfo = await client.exchangeAuthCode(code); const tokenInfo = await client.exchangeAuthCode(code);
saveToken(tokenInfo); saveToken(tokenInfo);
return tokenInfo; return tokenInfo;
}; };
/**
* Return the grant token provided by the host page or parent frame used
* for automatic login. This will be:
* - `undefined` if automatic login is not used
* - `null` if automatic login is used but the user is not logged in
* - a non-empty string if automatic login is used and the user is logged in
*/
const getGrantToken = () => serviceConfig(settings)?.grantToken;
/** /**
* Retrieve an access token for the API. * Retrieve an access token for the API.
* *
* @return {Promise<string|null>} The API access token or `null` if not logged in. * @return {Promise<string|null>} The API access token or `null` if not logged in.
*/ */
const getAccessToken = async () => { const getAccessToken = async () => {
// Step 1: Determine how to get an access token, depending on the login // Determine how to get an access token, depending on the login method being used.
// method being used.
if (!tokenInfoPromise) { if (!tokenInfoPromise) {
// Check if automatic login is being used, indicated by the presence of const grantToken = getGrantToken();
// the 'grantToken' property in the service configuration.
const grantToken = serviceConfig(settings)?.grantToken;
if (typeof grantToken !== 'undefined') { if (typeof grantToken !== 'undefined') {
if (grantToken) { if (grantToken) {
// User is logged-in on the publisher's website. // User is logged-in on the publisher's website.
...@@ -220,14 +225,16 @@ export class AuthService extends TinyEmitter { ...@@ -220,14 +225,16 @@ export class AuthService extends TinyEmitter {
tokenInfoPromise = Promise.resolve(null); tokenInfoPromise = Promise.resolve(null);
} }
} else if (authCode) { } else if (authCode) {
tokenInfoPromise = exchangeAuthCodeForToken(); tokenInfoPromise = exchangeAuthCodeForToken(authCode);
authCode = null; // Auth codes can only be used once.
} else { } else {
// Attempt to load the tokens from the previous session. // Attempt to load the tokens from the previous session.
tokenInfoPromise = Promise.resolve(loadToken()); tokenInfoPromise = Promise.resolve(loadToken());
} }
} }
// Step 2: Wait for the token to be fetched // Wait for the token to be fetched, and check that it is valid and that
// it wasn't invalidated while it was being fetched.
const origToken = tokenInfoPromise; const origToken = tokenInfoPromise;
const token = await tokenInfoPromise; const token = await tokenInfoPromise;
...@@ -236,7 +243,6 @@ export class AuthService extends TinyEmitter { ...@@ -236,7 +243,6 @@ export class AuthService extends TinyEmitter {
return null; return null;
} }
// Step 3: Re-fetch the token if it is no longer valid
if (origToken !== tokenInfoPromise) { if (origToken !== tokenInfoPromise) {
// The token source was changed while waiting for the token to be fetched. // The token source was changed while waiting for the token to be fetched.
// This can happen for various reasons. We'll just need to try again. // This can happen for various reasons. We'll just need to try again.
...@@ -245,19 +251,14 @@ export class AuthService extends TinyEmitter { ...@@ -245,19 +251,14 @@ export class AuthService extends TinyEmitter {
if (Date.now() > token.expiresAt) { if (Date.now() > token.expiresAt) {
// Token has expired, so we need to fetch a new one. // Token has expired, so we need to fetch a new one.
const usingGrantToken = const grantToken = getGrantToken();
typeof serviceConfig(settings)?.grantToken === 'string';
tokenInfoPromise = refreshAccessToken(token.refreshToken, { tokenInfoPromise = refreshAccessToken(token.refreshToken, {
// If we are using automatic login via a grant token, do not persist the // Only persist tokens if automatic login is not being used.
// initial access token or refreshed tokens. persist: typeof grantToken === 'undefined',
persist: !usingGrantToken,
}); });
return getAccessToken(); return getAccessToken();
} }
// Step 4: If the token was valid, return it
return token.accessToken; return token.accessToken;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment