Skip to content

Conversation

@jsflax
Copy link
Contributor

@jsflax jsflax commented Jun 21, 2018

No description provided.

@jsflax jsflax requested review from adamchel and edaniels and removed request for edaniels June 21, 2018 03:05
@coveralls
Copy link

coveralls commented Jun 21, 2018

Coverage Status

Coverage increased (+0.5%) to 80.992% when pulling 9193cb2 on jsflax:STITCH-1530b into 6fa9627 on mongodb:master.

Copy link
Contributor

@edaniels edaniels left a comment

Choose a reason for hiding this comment

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

Nice work so far. Have some changes to make for this pass. This still needs unit tests as well.

* @returns {string} The encoded object
*/
private uriEncodeObject(obj: object): string {
return encodeURIComponent(base64.btoa(JSON.stringify(obj)));
Copy link
Contributor

Choose a reason for hiding this comment

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

[remove] can you please use b64DecodeUnicode from JWT.ts. Feel free to move it somewhere else. Also remove the base64 package from our deps. That one you included isn't good for us AFAIK

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

],
"license": "Apache-2.0",
"dependencies": {
"Base64": "^1.0.1",
Copy link
Contributor

Choose a reason for hiding this comment

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

remove

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

/**
* The contents of this credential as they will be passed to the Stitch server.
*/
public constructor(public readonly authInfo: AuthInfo) {
Copy link
Contributor

Choose a reason for hiding this comment

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

[q] does this just create a property and set it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, similar to how kotlin's data classes function

newAuthInfo = credential.authInfo;
} else {
if (!response || !response.body) {
throw new StitchError("response was undefined");
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a more specific error you can use? This needs a better error message as it's pretty vague as to where this is coming from

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, this should be a StitchServiceError with an unknown error code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

* requesting the user profile in a separate request.
*/
private processLoginResponse(
private processLogin(
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this name should still stay

Copy link
Contributor

Choose a reason for hiding this comment

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

In addition to that, we should actually pass a response here and we should instead of creating an auth info in the credential, have the response body marshaled.

Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps a better solution is to have this method stay as processLogin but have it accept an ApiAuthInfo or AuthInfo instead of a Response, and move the response decoding logic to a method called processLoginResponse which accepts a non-optional Response. That way, the codepaths for the non-redirect logins can stay the same, whereas the link code path can call processLogin directly with the auth info it reconstructs from the URL. The credential would then only need to hold the provider type and name. Thoughts @edaniels ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 handled offline

);
}

if (!redirectState.found) {
Copy link
Contributor

Choose a reason for hiding this comment

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

all errors below here need better error messages and removal of StitchClient

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍


// If we get here, the state is valid - set auth appropriately.
return this.loginWithCredentialInternal(
new StitchAuthResponseCredential(redirectState.ua)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure this will completely work as written. You're missing the provider type and provider name, both of which need to be stored and retrieved (only one is stored). Please add a unit test that proves this.

Copy link
Contributor

@edaniels edaniels Jun 21, 2018

Choose a reason for hiding this comment

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

We should convert the ua here into the servers JSON form. An encode on ApiAuthInfo (ApiAuthInfo.toJSON) would work. Add a unit test for it's encoding.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The conversion should probably be done within CoreStitchAuth. Browser should be agnostic to ApiAuthInfo

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure that makes sense

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

*/
public readonly material: { [key: string]: string };

/**
Copy link
Contributor

Choose a reason for hiding this comment

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

The contents aren't really passed to the stitch server. AuthInfo is a result to clients, not to the server. we only send access and refresh tokens back.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

Copy link
Contributor

Choose a reason for hiding this comment

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

This wasn't updated

credential: StitchRedirectCredential
): Promise<void> {
this.auth.setRedirectFragment(
RedirectFragmentFields.LinkUser,
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't get why this is being set. This should eliminate the need for the StitchUserCodec and all changes made in in StitchUser.ts

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 unset


const state = generateState();
auth.setRedirectFragment(RedirectFragmentFields.State, state);
auth.setRedirectFragment(RedirectKeys.Type, redirectType);
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like this isn't ever used again

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

Copy link
Contributor

@adamchel adamchel left a comment

Choose a reason for hiding this comment

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

Seems really close, I agree with most of Eric's comments, but I disagreed in a few places. Let's maybe discuss in person when we're all in the office?

);
}

public hasRedirect(): boolean {
Copy link
Contributor

@adamchel adamchel Jun 21, 2018

Choose a reason for hiding this comment

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

I would disagree with you @edaniels . by default, the login/link with redirect redirects to the page from which it was called, so if we don't have this method, I feel like we should get rid of that default behavior and force people to pick a redirect destination as part of the login/link method. (EDIT: Basically what I'm saying is we should make the redirect URL in FacebookRedirectCredential and GoogleRedirectCredential non-optional, if we're getting rid of hasRedirect(). I still think we should have it though, since the 3.0 SDKs handled redirects back to the same page just fine.)

newAuthInfo = credential.authInfo;
} else {
if (!response || !response.body) {
throw new StitchError("response was undefined");
Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, this should be a StitchServiceError with an unknown error code.

* requesting the user profile in a separate request.
*/
private processLoginResponse(
private processLogin(
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps a better solution is to have this method stay as processLogin but have it accept an ApiAuthInfo or AuthInfo instead of a Response, and move the response decoding logic to a method called processLoginResponse which accepts a non-optional Response. That way, the codepaths for the non-redirect logins can stay the same, whereas the link code path can call processLogin directly with the auth info it reconstructs from the URL. The credential would then only need to hold the provider type and name. Thoughts @edaniels ?


if (!window.location || !window.location.hash) {
cleanup();
return Promise.reject(new StitchRedirectError("window location hash was undefined"));
Copy link
Contributor

Choose a reason for hiding this comment

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

we should return a null user.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

why?

ourState
);

if (redirectState.lastError || (redirectState.found && !redirectProvider)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

if we found no redirect info related or stitch, this should return null. specifically, it should look for client app id which ill add to the server now

Copy link
Contributor Author

Choose a reason for hiding this comment

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

why null?

const { redirectUrl, state } = prepareRedirect(
this.auth,
credential,
RedirectTypes.Login
Copy link
Contributor

Choose a reason for hiding this comment

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

this is the wrong type but I think you don't even need this enum

@jsflax
Copy link
Contributor Author

jsflax commented Jun 21, 2018

@adamchel @edaniels PTAL

Copy link
Contributor

@edaniels edaniels left a comment

Choose a reason for hiding this comment

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

Looking very nice. Just have a bunch of trivial nits. Will re-review once tests are in 😎

"long": "^3.2.0"
}
},
"Base64": {
Copy link
Contributor

Choose a reason for hiding this comment

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

[shrug] You need to remove this manually or rm -rf node_modules and npm install again.


loginWithRedirect(credential: StitchRedirectCredential): void;

handleRedirectResult(): Promise<StitchUser>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Where did hasRedirectResult go?

ClientAppId = "_stitch_client_app_id",
}

export default RedirectFragmentFields; No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] newline

authRoutes: StitchAuthRoutes,
storage: Storage,
appInfo: StitchAppClientInfo
public readonly browserAuthRoutes: StitchBrowserAppAuthRoutes,
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] private

);
}

public linkWithRedirect(
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] linkUserWithRedirectInternal Users aren't supposed to call this directly


import { Storage } from "../../../internal/common/Storage";

import AuthInfo from "../AuthInfo";
Copy link
Contributor

Choose a reason for hiding this comment

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

Add some simple encode decode tests for this por favor.

return this.doGetUserProfile()
.then(profile => {
// readonlyly set the info and user
// readonly set the info and user
Copy link
Contributor

Choose a reason for hiding this comment

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

what's readonly?

let userPassClient = client.auth.getProviderClient(UserPasswordAuthProviderClient.factory)
componentDidMount() {
const client = Stitch.initializeDefaultAppClient(
"test-js-sdk-eocey",
Copy link
Contributor

Choose a reason for hiding this comment

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

remove

private processLoginResponse(credential: StitchCredential, response: Response): Promise<TStitchUser> {
try {
if (!response) {
throw new StitchServiceError("response was undefined");
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] add some context to this error

);

describe("StitchAuthImpl", () => {
it("should handleRedirect", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

This test should be updated or go away after your tests.

@jsflax
Copy link
Contributor Author

jsflax commented Jun 22, 2018

@edaniels PTAL

if (!response) {
throw new StitchServiceError("response was undefined");
throw new StitchServiceError(
`the login response could not be processed for credential: ${credential};` +
Copy link
Contributor

Choose a reason for hiding this comment

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

[minor] don't log the credential. may contain sensitive info.

expect((credential as StitchAuthCredential).authInfo).toEqual(redirectResult.ua);
expect(credential.providerName).toEqual("test_provider_name");
expect(credential.providerType).toEqual("test_provider_type");
expect((credential as StitchAuthCredential).authInfo).toEqual(redirectFragmentResult);
Copy link
Contributor

Choose a reason for hiding this comment

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

[request] go a little plus ultra here and mock the profile parts and verify you are logged in with the info above

Copy link
Contributor

@edaniels edaniels left a comment

Choose a reason for hiding this comment

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

LGTM. Just have two requests for you.

Copy link
Contributor

@adamchel adamchel left a comment

Choose a reason for hiding this comment

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

A few nits but LGTM. We're so close to being done!


export default class StitchRedirectError extends StitchError {
constructor(msg: string) { super(msg); }
} No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] newline

});

let hasBeenCalled = false;
const hasBeenCalled = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] do you actually use this anywhere? I think you can get rid of it

}

/**
* Processes the response of the login/link request, setting the authentication state if appropriate, and
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] move this comment to processLoginResponse, and if you have time add a comment here describing what this function does now

@jsflax jsflax merged commit 5728943 into mongodb:master Jun 22, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants