bpt-pack-two
Version:
Study Passwordless authentication on aws project
93 lines (92 loc) • 3.87 kB
JavaScript
/**
* Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You
* may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* or in the "license" file accompanying this file. This file is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
* ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
import { revokeToken } from "./cognito-api.js";
import { configure } from "./config.js";
import { retrieveTokens, storeTokens } from "./storage.js";
import { busyState, } from "./model.js";
import { scheduleRefresh } from "./refresh.js";
/** The default tokens callback stores tokens in storage and reschedules token refresh */
export const defaultTokensCb = async ({ tokens, abort, }) => {
const storeAndScheduleRefresh = async (tokens) => {
await storeTokens(tokens);
scheduleRefresh({
abort,
tokensCb: (newTokens) => newTokens && storeAndScheduleRefresh({ ...tokens, ...newTokens }),
}).catch((err) => {
const { debug } = configure();
debug?.("Failed to store and refresh tokens:", err);
});
};
await storeAndScheduleRefresh(tokens);
};
/**
* Sign the user out. This means: clear tokens from storage,
* and revoke the refresh token from Amazon Cognito
*/
export const signOut = (props) => {
const { clientId, debug, storage } = configure();
const { currentStatus, statusCb } = props ?? {};
if (currentStatus && busyState.includes(currentStatus)) {
debug?.(`Initiating sign-out despite being in a busy state: ${currentStatus}`);
}
statusCb?.("SIGNING_OUT");
const abort = new AbortController();
const signedOut = (async () => {
try {
const tokens = await retrieveTokens();
if (abort.signal.aborted) {
debug?.("Aborting sign-out");
currentStatus && statusCb?.(currentStatus);
return;
}
if (!tokens) {
debug?.("No tokens in storage to delete");
props?.tokensRemovedLocallyCb?.();
statusCb?.("SIGNED_OUT");
return;
}
const amplifyKeyPrefix = `CognitoIdentityServiceProvider.${clientId}`;
const customKeyPrefix = `Passwordless.${clientId}`;
await Promise.all([
storage.removeItem(`${amplifyKeyPrefix}.${tokens.username}.idToken`),
storage.removeItem(`${amplifyKeyPrefix}.${tokens.username}.accessToken`),
storage.removeItem(`${amplifyKeyPrefix}.${tokens.username}.refreshToken`),
storage.removeItem(`${amplifyKeyPrefix}.${tokens.username}.tokenScopesString`),
storage.removeItem(`${amplifyKeyPrefix}.${tokens.username}.userData`),
storage.removeItem(`${amplifyKeyPrefix}.LastAuthUser`),
storage.removeItem(`${customKeyPrefix}.${tokens.username}.expireAt`),
storage.removeItem(`Passwordless.${clientId}.${tokens.username}.refreshingTokens`),
]);
props?.tokensRemovedLocallyCb?.();
if (tokens.refreshToken) {
await revokeToken({
abort: undefined,
refreshToken: tokens.refreshToken,
});
}
statusCb?.("SIGNED_OUT");
}
catch (err) {
if (abort.signal.aborted)
return;
currentStatus && statusCb?.(currentStatus);
throw err;
}
})();
return {
signedOut,
abort: () => abort.abort(),
};
};