Skip to content

Commit

Permalink
Add onSignIn handler
Browse files Browse the repository at this point in the history
  • Loading branch information
danielholmes committed Apr 9, 2024
1 parent 4090201 commit 73f1dbb
Show file tree
Hide file tree
Showing 16 changed files with 482 additions and 329 deletions.
735 changes: 428 additions & 307 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dhau/react-aws-cognito",
"version": "0.0.17",
"version": "0.0.18",
"type": "module",
"sideEffects": false,
"description": "Context and hooks to manage an AWS Cognito authenticated user in React.",
Expand Down Expand Up @@ -35,7 +35,7 @@
"author": "Daniel Holmes",
"license": "MIT",
"dependencies": {
"@dhau/lang-extras": "^0.0.5"
"@dhau/lang-extras": "^0.0.6"
},
"devDependencies": {
"@rollup/plugin-typescript": "^11.1.6",
Expand Down
11 changes: 9 additions & 2 deletions src/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import { isUserNotConfirmedException } from "./model/sign-in";
import { AuthState } from "./state";
import { InternalAuthState } from "./model/internal-state";
import getCurrentUser, { getUserDataNoCache } from "./model/get-current-user";
import sessionToAuthAccess from "./model/session-to-auth-access";
import sessionToAuthAccess, {
AuthAccess,
} from "./model/session-to-auth-access";
import {
SignedInAuthState,
createSignedInAuthState,
Expand All @@ -43,6 +45,7 @@ type AuthProviderProps<TUser> = {
readonly parseUser: (data: UserData) => TUser;
readonly cognitoConfig: AuthCognitoConfig;
readonly children: ReactNode;
readonly onSignIn?: (user: TUser & AuthAccess) => void;
};

const storage = window.localStorage;
Expand All @@ -53,6 +56,7 @@ function AuthProvider<TUser>({
cognitoConfig,
children,
parseUser: parseDomainUser,
onSignIn,
}: AuthProviderProps<TUser>) {
const [internalAuthState, setInternalAuthState] = useState<
InternalAuthState<TUser>
Expand Down Expand Up @@ -106,7 +110,9 @@ function AuthProvider<TUser>({
useEffect(() => {
let waiting = true;
(async () => {
let current;
let current:
| Awaited<ReturnType<typeof getCurrentUser<TUser>>>
| undefined;
try {
current = await getCurrentUser(userPool, parseUser);
} catch (e) {
Expand Down Expand Up @@ -178,6 +184,7 @@ function AuthProvider<TUser>({
internalAuthState,
storage,
parseUser,
onSignIn,
});
}, [internalAuthState, refreshUser, userPool]);
return (
Expand Down
2 changes: 1 addition & 1 deletion src/model/change-password.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ async function changePassword(
user: CognitoUser,
currentPassword: string,
newPassword: string,
): Promise<void> {
) {
return new Promise<void>((resolve, reject) => {
user.changePassword(currentPassword, newPassword, (error) => {
if (error) {
Expand Down
2 changes: 1 addition & 1 deletion src/model/confirm-forgot-password.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ async function confirmForgotPassword(
email: string,
code: string,
newPassword: string,
): Promise<void> {
) {
const user = new CognitoUser({
Username: email,
Pool: userPool,
Expand Down
2 changes: 1 addition & 1 deletion src/model/confirm-sign-up.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ async function confirmSignUp(
storage: ICognitoStorage,
emailAddress: string,
code: string,
): Promise<void> {
) {
const user = new CognitoUser({
Username: emailAddress,
Pool: userPool,
Expand Down
2 changes: 1 addition & 1 deletion src/model/forgot-password.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ async function forgotPassword(
storage,
}: { userPool: CognitoUserPool; storage: ICognitoStorage },
email: string,
): Promise<void> {
) {
const user = new CognitoUser({
Username: email,
Pool: userPool,
Expand Down
4 changes: 1 addition & 3 deletions src/model/get-current-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import sessionToAuthAccess from "./session-to-auth-access";

type UserBundle<TUser> = {
readonly cognitoUser: CognitoUser;
readonly authUser: TUser & {
readonly isMfaEnabled: boolean;
};
readonly authUser: TUser & AuthAccess;
};

type UserParser<TUser> = (data: UserData, session: CognitoUserSession) => TUser;
Expand Down
7 changes: 7 additions & 0 deletions src/model/require-mfa-complete.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { CognitoUser } from "amazon-cognito-identity-js";
import { InternalAuthStateSetter } from "./internal-state";
import { UserParser, getUserData } from "./get-current-user";
import { AuthAccess } from "./session-to-auth-access";

type Options<TUser> = {
readonly onSignIn: ((user: TUser & AuthAccess) => void) | undefined;
};

async function requireMfaComplete<TUser>(
setInternalAuthState: InternalAuthStateSetter<TUser>,
parseUser: UserParser<TUser>,
user: CognitoUser,
{ onSignIn }: Options<TUser>,
code: string,
) {
// TODO: Look at source - use UserPool instead
Expand All @@ -31,6 +37,7 @@ async function requireMfaComplete<TUser>(
user,
authUser,
});
onSignIn?.(authUser);
}

export default requireMfaComplete;
9 changes: 8 additions & 1 deletion src/model/require-new-password-complete.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import { CognitoUser } from "amazon-cognito-identity-js";
import { InternalAuthStateSetter } from "./internal-state";
import { getUserData, UserParser } from "./get-current-user";
import { AuthAccess } from "./session-to-auth-access";

type Options<TUser> = {
readonly onSignIn: ((user: TUser & AuthAccess) => void) | undefined;
};

async function requireNewPasswordComplete<TUser>(
setInternalAuthState: InternalAuthStateSetter<TUser>,
parser: UserParser<TUser>,
user: CognitoUser,
{ onSignIn }: Options<TUser>,
password: string,
): Promise<void> {
) {
// TODO: Look at source - use UserPool instead
// https://github.com/aws-amplify/amplify-js/blob/master/packages/
// amazon-cognito-identity-js/src/CognitoUser.js
Expand All @@ -27,6 +33,7 @@ async function requireNewPasswordComplete<TUser>(
user,
authUser,
});
onSignIn?.(authUser);
}

export default requireNewPasswordComplete;
2 changes: 1 addition & 1 deletion src/model/resend-confirmation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ async function resendConfirmation(
userPool: CognitoUserPool,
storage: ICognitoStorage,
emailAddress: string,
): Promise<void> {
) {
const user = new CognitoUser({
Username: emailAddress,
Pool: userPool,
Expand Down
4 changes: 1 addition & 3 deletions src/model/resend-email-address-verification.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { CognitoUser } from "amazon-cognito-identity-js";

async function resendEmailAddressVerification(
user: CognitoUser,
): Promise<void> {
async function resendEmailAddressVerification(user: CognitoUser) {
return new Promise<void>((resolve, reject) => {
user.getAttributeVerificationCode("email", {
onSuccess() {
Expand Down
17 changes: 13 additions & 4 deletions src/model/sign-in.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from "amazon-cognito-identity-js";
import { InternalAuthStateSetter } from "./internal-state";
import { getUserData, UserParser } from "./get-current-user";
import { AuthAccess } from "./session-to-auth-access";

type SignInResult =
| {
Expand All @@ -23,13 +24,20 @@ type SignInResult =
readonly signOut: () => Promise<void>;
};

type Services = {
readonly userPool: CognitoUserPool;
readonly storage: ICognitoStorage;
};

type Options<TUser> = {
readonly onSignIn: ((user: TUser & AuthAccess) => void) | undefined;
};

async function signIn<TUser>(
setInternalAuthState: InternalAuthStateSetter<TUser>,
{
userPool,
storage,
}: { userPool: CognitoUserPool; storage: ICognitoStorage },
{ userPool, storage }: Services,
parseUser: UserParser<TUser>,
{ onSignIn }: Options<TUser>,
email: string,
password: string,
) {
Expand Down Expand Up @@ -85,6 +93,7 @@ async function signIn<TUser>(
user,
authUser,
});
onSignIn?.(authUser);
}

return result;
Expand Down
2 changes: 1 addition & 1 deletion src/model/sign-up.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { SignUpVariables } from "../state";
async function signUp(
userPool: CognitoUserPool,
{ emailAddress, password, extraAttributes }: SignUpVariables,
): Promise<void> {
) {
await new Promise<void>((resolve, reject) => {
userPool.signUp(
emailAddress,
Expand Down
2 changes: 1 addition & 1 deletion src/model/verify-email-address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ async function verifyEmailAddress<TUser>(
parseUser: UserParser<TUser>,
user: CognitoUser,
code: string,
): Promise<void> {
) {
await new Promise<void>((resolve, reject) => {
user.verifyAttribute("email", code, {
onSuccess: () => resolve(),
Expand Down
6 changes: 6 additions & 0 deletions src/signed-out-auth-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
import { UserParser } from "./model/get-current-user";
import signIn from "./model/sign-in";
import requireMfaComplete from "./model/require-mfa-complete";
import { AuthAccess } from "./model/session-to-auth-access";

type Options<TUser> = {
readonly userPool: CognitoUserPool;
Expand All @@ -25,6 +26,7 @@ type Options<TUser> = {
| NewPasswordInternalAuthState;
readonly setInternalAuthState: InternalAuthStateSetter<TUser>;
readonly parseUser: UserParser<TUser>;
readonly onSignIn: ((user: TUser & AuthAccess) => void) | undefined;
};

function createSignedOutAuthState<TUser>({
Expand All @@ -33,6 +35,7 @@ function createSignedOutAuthState<TUser>({
setInternalAuthState,
parseUser,
storage,
onSignIn,
}: Options<TUser>) {
return {
type: "signedOut" as const,
Expand All @@ -41,6 +44,7 @@ function createSignedOutAuthState<TUser>({
setInternalAuthState,
{ userPool, storage },
parseUser,
{ onSignIn },
),
signUp: partial(signUp, userPool),
confirmSignUp: partial(confirmSignUp, userPool, storage),
Expand All @@ -57,6 +61,7 @@ function createSignedOutAuthState<TUser>({
setInternalAuthState,
parseUser,
internalAuthState.user,
{ onSignIn },
)
: undefined,
requireNewPasswordComplete:
Expand All @@ -66,6 +71,7 @@ function createSignedOutAuthState<TUser>({
setInternalAuthState,
parseUser,
internalAuthState.user,
{ onSignIn },
)
: undefined,
};
Expand Down

0 comments on commit 73f1dbb

Please sign in to comment.