aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.42k stars 2.12k forks source link

Cognito Hosted UI documentation (and components) improvements #705

Closed OlivierPT closed 6 years ago

OlivierPT commented 6 years ago

Do you want to request a feature or report a bug?

Feature request for documentation improvements and more complete Amplify components

What is the current behavior?

The existing documentation for the Cognito Hosted UI/Oauth is not complete enough in order to be easily used. It only explains how to launch the Cognito Hosted UI but not how to manage user credentials within the application via Amplify.

What is the expected behavior?

It would be highly valuable to have a more complete documentation which provides the full process to authenticate and manage credentials. Then, it would also be great to have Amplify components to fully work with Cognito Hosted UI/Oauth for React, React native, Angular...

Thanks

mlabieniec commented 6 years ago

@OlivierPT thanks for the feedback. Do you have any suggestions on what might make it more clear for us to add? Once the hosted UI returns back, the JWT tokens (if using token grant) get injected into the Cognito session and things continue as usual (just as if you logged in using or simlar. There is also a react component: https://aws.github.io/aws-amplify/media/authentication_guide#launching-the-hosted-ui-in-react

The button really only constructs a link with the configuration parameters. React native requires a native module and we haven't gotten to supporting this yet in aws-amplify-react-native.

As far as the interface, we are trying to keep this generic (not so cognito specific) because we plan on supporting other authentication providers in the future, so we tried to follow OAuth nomenclature and specifications when defining the parameters. Please let us know your suggestions in the meantime or feel free to submit a PR.

OlivierPT commented 6 years ago

Hi @mlabieniec Thanks for your answer. First, I fully agree with the generic approach and also the support of other authentication provider in the futur. This is a great news :) Then, I have to mention that I am beginner regarding Oauth authentication so maybe this is a basic problem. Actually, my issue is that I don't manage to get it working fully only from the documentation and the example it provides so I feel something is missing there. The authentication UI is launching well and the authentication is ok (google authentication, back on my app with the tokens in the URL) but the tokens are not injected into the Cognito session as you mention.

With the Authenticator component, there is a state that manage the display of the different authentication components when needed and the app when authentication ok. How is it supposed to work with Oauth component? Is it supposed to work the same way? Or should I manage it myself with specific routing for example? Then, how the authentication context is supposed to be injected? Is there any prerequisite in the application structure ? Should we use the Authenticator component as well?

I am pretty sure this kind of precision will be helpful for many developper to save time and use the Amplify lib in the best way possible :)

Thank you

powerful23 commented 6 years ago

@OlivierPT do you have a federated identity pool to provide credentials?

OlivierPT commented 6 years ago

Hi @powerful23,

On the AWS side, I have:

Signin and signup to the User Pool with Amplify Authenticator is working well and since I would like to also allow authentication with Google, I am trying to use the Oauth component. Using Oauth component, I can launch the Hosted UI, sign-in with Google for example. Then, the user is added to the user pool and redirected to the app, with the idToken and accessToken in the URL as expected. But the authentication is not taken into account in the application.

Thanks,

powerful23 commented 6 years ago

@OlivierPT can you open the debug mode and search for 'Cognito Hosted authentication result' which would happen if your callback url is parsed correctly? Or there will be a message saying 'Error in cognito hosted auth response'

OlivierPT commented 6 years ago

Hi @powerful23,

I had a deeper check with debug mode (actually console logs with "window.LOG_LEVEL = 'DEBUG' activated, right?)

At the end of the authentication process, I can't find any log with 'Cognito Hosted authentication result' or 'Error in cognito hosted auth response'.

Maybe I should give more details about my configuration to help to understand the issue.

package.json:

I encapsulated my App component in the following AppWithAuth component: `

      <ConfirmSignIn/>
      <RequireNewPassword/>
      <SignUp/>
      <ConfirmSignUp/>
      <VerifyContact/>
      <ForgotPassword/>
      <App />

`

Oauth configuration: oauth: { domain: 'xxxxxx.auth.eu-west-1.amazoncognito.com', scope: ['phone', 'email', 'profile', 'openid','aws.cognito.signin.user.admin'], redirectSignIn: 'http://localhost:3000', redirectSignOut: 'http://localhost:3000', responseType: 'code', }

From the authentication screen, there is a "Sign with AWS" button that I can use to open the Cognito Hosted UI. From there, I can do the sign-in with Google. So, this is looking pretty well with the example in the documentation except that I use the Authenticator component to hide the application when the user is not logged in (and also to continue to login while the hosted UI is not working).

After the login process with Google, the user is added in the Cognito UserPool with all the mapped attributes but I am redirected to the Application sign-in screen without be logged in. The result is the same if I login with the Cognito UserPool user.

So I hope it will you to understand the issue.

powerful23 commented 6 years ago

@OlivierPT I doubt the format of callback url you got might not be valid. The reason why I want to see the debug info mentioned above is because when parsing the callback url, it should trigger either a success callback or a failure callback. Since you are not seeing any of those, maybe it is caused by this line which will end silently if the callback url is neither in code type or in token type.

So could you paste the callback url here?

OlivierPT commented 6 years ago

Hi,

Here is the callback url I get :

http://localhost:3000/?code=501c4adb-df4d-434e-b024-9f1f93575c7b#

powerful23 commented 6 years ago

@OlivierPT the url looks fine to me.

Can you check the followings:

  1. Ensure the version of amazon-cognito-auth-js is ^1.1.9
  2. Check there is a call to endpoint https://XXX.auth.${aws-region}.amazoncognito.com/oauth2/token which will return a set of tokens when you jump back from Cognito login page to your app.
  3. Provide a screenshot of all the logging info you got.

Thanks

OlivierPT commented 6 years ago

Hi,

  1. I don't have any dependency with amazon-cognito-auth-js. This dependency is not documented and it seems it is not a transitive dependency... Installing the lib didn't change anything in the behaving of the app (version ^1.2.0)

  2. instead of a call to https://XXX.auth.${aws-region}.amazoncognito.com/oauth2/token, there is a call to https://XXX.auth.${aws-region}..amazoncognito.com/oauth2/idpresponse This is the URL I configured in the Google console. This is also the URL documented by Amplify. Should it be changed?

  3. I added 2 screenshot with the details of the 2 last request of the authentication process. I hope it is what you are looking for

capture d ecran 2018-04-26 a 21 40 19 capture d ecran 2018-04-26 a 21 41 25

Can you tell me which component is in charge of calling the parsing of the URL and the token? It is like something is missing and it is not done on the client side.

Thanks

powerful23 commented 6 years ago

@OlivierPT

  1. amazon-cognito-auth-js is a dependency of aws-amplify so it should be installed when you are using aws-amplify

  2. The call to https://XXX.auth.${aws-region}.amazoncognito.com/oauth2/token is triggered when you get back from that hosted page with the callback url. The amazon-cognito-auth-js library will parse the callback url and send the code to this endpoint so that Cognito service will send tokens back to the client. After that Amplify will use those tokens to construct a valid user session for you and also get a aws credentials with the JWT token from your federated identity pool.

Maybe you can try reinstall aws-amplify and see if amazon-cognito-auth-js is also installed. Also it would be great if you can send the screenshots of your console log that contains amplify debug info which would help a lot to confirm the auth flow.

OlivierPT commented 6 years ago

Hi @powerful23,

I did reinstall full aws-amplify and aws-amplify and now the authentication is working with OAuth! It seems like it was only an installation/dependency issue at the end. Sorry to have bothered you guys and thank you for you support.

The withOAuth component is event working inside an Authenticator component which let to manage the access to the application very easily, which is even nicer. Since it not documented, maybe would a nice addition to the documentation? what do you think?

Thank you again!

powerful23 commented 6 years ago

Cool, will add that.

jamesoflol commented 6 years ago

Thank god I found this thread. Was very confused about how to process the response from oauth. However, I'm still concerned that it's an automagic process that happens on its own time. I think you'll find that most people want to run the parsing and config init themselves, as we then direct our apps to respond to the init event. If we don't have a callback for that, then our app just sits there stupid, not knowing if/when the login was successful. Or have I missed something?

E.g., I'm at http://localhost:8080/login-callback/?code=d4gwregewr...

In about a tenth of a second it processes the hash (this._cognitoAuthClient.parseCognitoWebResponse(curUrl)) but what should I do to tell my app if the user is logged in? Currently I am embarassingly running something along the lines of setInterval(() => Auth.currentSession().then(// Logged in, do stuff), 1000). It fires first time every time, but I can't assuem it will. If I run Auth.currentSession() immediately it errors out with 'not logged in'.

powerful23 commented 6 years ago

@jamesoflol good point. We have a Hub class which can be used to listen events sent from Auth module. https://aws.github.io/aws-amplify/media/hub_guide#listening-authentication-events

So you can listen on signIn event and do whatever you want in the callback

jamesoflol commented 6 years ago

Oh rad, thanks Zhuo! I've just now seen it in the "subscribing to events" section - my bad.

sbrickner commented 5 years ago

@powerful23 When using the /login endpoint and "token" grant the Access and ID tokens are both returned on the URL after logging in. However, only the accessToken is automatically written to localStorage which causes an error with Auth.configure: "Error: Local storage is missing an ID Token, Please authenticate". Is this a bug?

powerful23 commented 5 years ago

@sbrickner can you provide some code snippets about how are u using the feature? Also you can open the debug mode to find more logging info. window.LOG_LEVEL='DEBUG'

sbrickner commented 5 years ago

@powerful23 I am using the GET /login endpoint with the appended fields it needs. I paste the link in the broswer and it brings up the hosted UI. I log in and then it redirects to my app. The code is just the auth.configure() with the correct config values. The idToken and accessToken are on the URL but only the accessToken gets written to localStorage on it's own which causes the error below. Below is the console log.

capture

powerful23 commented 5 years ago

@sbrickner can you check the parsing result object which is appended after this message: 'Cognito Hosted authentication result'

sbrickner commented 5 years ago

@powerful23 The issue I'm experiencing is that there is no object. I only get the error you see there at the bottom of the logs. If I take the id_token from the response url and manually write it to the .idToken localStorage key and refresh then it finds a user and returns the object but the session property is always null. I have tried listening to the various events with the Hub class but unless I dispatch the event myself the onHubCapsule is never triggered. Is there an example somewhere that is using the Hosted UI with the implicit token flow?

Additional Notes:

jonasao commented 5 years ago

@powerful23 Basically the documentation provided regarding ReactJS and hosted UI is partially "crap"! Sorry to say this, but it is full of errors and misleading information. Try creating a new ReacJS app, that uses the hosted UI with the withOAuth() HOC, based on the provided documentation. I guarantee you it will not work without a lot of trial and error.

mlabieniec commented 5 years ago

@jonasao sorry to hear this is been so challenging. I was able to just spin one up with the hosted ui and did notice one issue with the config code snippet that seemed to cause some issues. I fixed that in the docs, and everything seems to be working for me right now. Can you provide some feedback on how you suggest we improve the doc so we can make the changes/updates that caused you issues?

chezhiane commented 5 years ago

Please reopen this and provide better documentation on angular implementation of amplify auth. No documentation and has been painful.

github-actions[bot] commented 3 years ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels or Discussions for those types of questions.