Skip to content

Custom auth/alban/react next sample app signin #7624

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: custom-auth/main
Choose a base branch
from

Conversation

albanx
Copy link

@albanx albanx commented Mar 8, 2025

  1. Completed Sign In sample with NextJs
  2. [Bug] Created Sign Up but not working due to missing exposure of submitCode in the result.state
  3. Removed correlationId from Fetch client because it is present already in the header
  4. Removed HTTPS checks in SDK, it is not needed to be handled by JS and blocks local development

…ple-app-signin

# Conflicts:
#	lib/msal-custom-auth/src/core/network_client/http_client/FetchHttpClient.ts
password,
});

if (result.error) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, it is better to use following check in the if (xxx).
if (result.state?.type === SignInState.Failed)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I check state as above this causes a type check error (for the reasons widely discussed in the chat today). This happens because the result.error is ambiguous due to the polymorphic type of result:

image

image

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see any problem.

image

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check SignUp return result not signIn

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the signup:
image

setError("");
setLoading(true);

try {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need the type catch here since the SDK is guaranteed no error thrown

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a await promise resolve there, meaning that the try catch is a must of the promise rejects

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Afaik, the promise rejection only occurs if an error is thrown and not caught inside the method. But as I said, any API in this SDK is guaranteed no error thrown.

Copy link
Author

@albanx albanx Mar 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A JavaScript promise has 2 statuses: resolve, reject.
The compiler or javascript cannot know that the SDK internally handles all errors of that away reject.
Without the try-catch, any error of the promise would cause the function to immediately throw an exception and potentially crash.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't get it. If we guarantee the API will never reject the promise or throw an error, is the try catch still necessary?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can guarantee it, but JavaScript engine cannot know it. No developer can know it, unless the read the source of the SDK itself.
If I read await something -> that means it can throw an exception.

const [email, setEmail] = useState("");
const [code, setCode] = useState("");
const [error, setError] = useState("");
const [flowState, setFlowState] = useState<any>(null);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using any here, It can set as SignInCompleted | SignInFailed | SignInCodeRequired | SignInPasswordRequired.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This points out the point I was making, in terms of S of SOLID.
flowState has many responsibilities and if we update the SDK with a new state, the engineer have to update his integration code, resulting in breaking the backward compatibility exactly because it is breaking the O of open close.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this does not work

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it doesn't work? Also we can consider using the AuthFlowStateBase since it is better than any.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar suggestion: can we use the base class AuthFlowStateBase or SignUpCompleted | SignUpFailed | SignUpCodeRequired | SignUpPasswordRequired | SignUpAttributesRequired to replace any?

@shenj
Copy link

shenj commented Mar 18, 2025

Do you think we can move this sample app into the repo Kaushik suggested? I am planning the create the PR to MSAL for JS team soon for checking in the changes into the dev branch. If it is possible, it is better to exclude the sample app in that PR.

@albanx
Copy link
Author

albanx commented Mar 18, 2025

Do you think we can move this sample app into the repo Kaushik suggested? I am planning the create the PR to MSAL for JS team soon for checking in the changes into the dev branch. If it is possible, it is better to exclude the sample app in that PR.

Yes I have moved them partially, not the last version. Otherwise I cannot run them in the repo until the package is published.

setError("Incorrect password");
} else {
setError("An error occurred during sign in");
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I misunderstood, but any reason why you didn't use the handleError function you defined in the utils/index.ts?

setLoading(true);

try {
const result = await flowState.submitCode(code);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed earlier, can you double check whether flowState.submitCode(code) is working?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have ran the sign in different times, it works, unless there has been some recent updates.

const [password, setPassword] = useState("");
const [code, setCode] = useState("");
const [error, setError] = useState("");
const [flowState, setFlowState] = useState<any>(null);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it is better to use the state base class AuthFlowStateBase to replace any?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or use SignInCompleted | SignInFailed | SignInCodeRequired | SignInPasswordRequired?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be AuthFlowStateBase , the later one I really do not recommend. This is how developer experience will look with the latest:
const [flowState, SetFlowState] = useState< checking docs

I see SignInCompleted , perfect
const [flowState, SetFlowState] = useState<SignInCompleted>(null)

Ahh wait there is more
const [flowState, SetFlowState] = useState<SignInCompleted | SignInFailed>(null)

no wait more types in or

const [flowState, SetFlowState] = useState<SignInCompleted | SignInFailed | SignInCodeRequired >(null)
(how many possible types in OR I should have, I have to check all of them and find out by reading a long boring documentation)

1 month after the SDK releseas version 2.0 ... Ah crap I have to update all my code again

const [flowState, SetFlowState] = useState<SignInCompleted | SignInFailed | SignInCodeRequired | **ANewSignInState** >(null)

if (flowState instanceOf SignInCompleted)
if (flowState instanceOf SignInFailed )
if (flowState instanceOf SignInCodeRequired )
**if (flowState instanceOf ANewSignInState)**

setLoading(true);

try {
const app = await CustomAuthPublicClientApplication.create(customAuthConfig);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, the app can be shared cross the whole application for sign-in, sign-up and sspr. Is it possible we can use the single instance of app in this sample app?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no point and need to share the same app instance for different flows that are not connected in the lifecycle of an app. Imagine Sign Up , Sign In and SSPR as different flows that are separated in time and usage , as it happens in every app (a user does not go through the all flows in the same app cycle). Making this flows sharing the same instance it kind of tight them together for no reason.

<div style={styles.container}>
<h2>Sign Up</h2>
{flowState?.type === SignUpState.CodeRequired ? (
<CodeForm onSubmit={handleCodeSubmit} code={code} setCode={setCode} loading={loading} />
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May I ask why we don't have the PasswordForm?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is SignUp with OTP does not asks for password which I based on the past samples. That is the configuration of the sample tenant. I can add the password field but it will be optional

Copy link
Contributor

Reminder: This PR appears to be stale. If this PR is still a work in progress please mark as draft.

@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs: Attention 👋 Awaiting response from the MSAL.js team label Apr 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs: Attention 👋 Awaiting response from the MSAL.js team samples Related to the samples apps for the library.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants