Code Monkey home page Code Monkey logo

Comments (39)

jayair avatar jayair commented on June 9, 2024 4

@auz1111 Yeah it has been on our list.

For the tutorial, I'd have to look for one. You need to use Cognito Federated Identities instead of the User Pool to manage your user accounts.

from sst.dev.

jayair avatar jayair commented on June 9, 2024 4

@triunm I was planning on writing on this but a simple way to handle this is as follows.

In your config.js use something like this:

const dev = {
  apiGateway: {
    REGION: 'us-east-1',
    URL: 'https://12345678.execute-api.us-east-1.amazonaws.com/staging',
  },
  cognito: {
    REGION: 'us-east-1',
    USER_POOL_ID : 'us-east-1_123456678',
    APP_CLIENT_ID : '4xxxxxxxxxxxxxxxxxxxx',
    IDENTITY_POOL_ID: 'us-east-1:12345678-1234-1233-9387-1234567890123',
  }
};

const prod = {
  apiGateway: {
    REGION: 'us-east-1',
    URL: 'https://567890.execute-api.us-east-1.amazonaws.com/prod',
  },
  cognito: {
    REGION: 'us-east-1',
    USER_POOL_ID : 'us-east-1_4444444',
    APP_CLIENT_ID : '5xxxxxxxxxxxxxxxxxx',
    IDENTITY_POOL_ID: 'us-east-1:456789-1234-1234-4567-123456789',
  }
};

const config = process.env.REACT_APP_STAGE === 'production'
  ? prod
  : dev;

export default {
  ...config
};

And in your package.json set your scripts as:

  "scripts": {
    "start": "REACT_APP_STAGE=dev react-scripts start",
    "build": "REACT_APP_STAGE=production react-scripts build"
  }

You can extend this idea to have other environments. This is based on the idea of custom environment variables in Create React App.

from sst.dev.

jayair avatar jayair commented on June 9, 2024 1

Hmm I'm not completely sure if I follow the flow you are talking about. It is a bit complicated and not super well documented.

from sst.dev.

 avatar commented on June 9, 2024 1

Figured it out. NoScript stepped in to block amazonaws.com. That'd do it.

from sst.dev.

leejh3224 avatar leejh3224 commented on June 9, 2024 1

I'm leaving this comment just because I had a hard time finding out what was a problem when I faced 502 error(cors problem).

In that case, there are three possible options.
Firstly, you can look at '/libs/response-lib.js' and check whether the function contains 'Access-Control-Allow-Origin' header or not.
Secondly, you may have miss indented serverless.yml.
Or lastly, you may have forgotten deploying your functions as I did ...

I could see my notes after deploying the functions.
If you have same issue like me, you can re-deploy your functions and it might help you get out of trouble.

from sst.dev.

ohenneken avatar ohenneken commented on June 9, 2024 1

from sst.dev.

ohenneken avatar ohenneken commented on June 9, 2024 1

from sst.dev.

auz1111 avatar auz1111 commented on June 9, 2024

I would love it if you added a chapter on logging in with facebook account. Do you guys know of any good tuts that would help walk us through this?

from sst.dev.

rogueturnip avatar rogueturnip commented on June 9, 2024

I'm starting to look into this also. It seems that there is a mapping ability to map the different federated identities together but I'm not exactly sure yet how to do this in a way that makes sense.

from sst.dev.

jayair avatar jayair commented on June 9, 2024

@rogueturnip Yeah it is quite confusing to wrap your head around the set up. But that is how it is supposed to work. Federated identities pulls all your different identity sources together to give you a consolidated view of all your users, regardless of where they are coming from.

from sst.dev.

rogueturnip avatar rogueturnip commented on June 9, 2024

If I'm understanding it correctly it seems you login the first time and that caches the credentials. Then when a login is done using something like facebook you would do a credentials.get to see if there are existing credentials and then when you do the Login Map you would send in both. Am I following the flow right or completely off base? I can't find an example so I'm piecing together things from the AWS docs.

from sst.dev.

rogueturnip avatar rogueturnip commented on June 9, 2024

It's possible I"m messing up what I think the process is. No where is this documented very well.

from sst.dev.

 avatar commented on June 9, 2024

Getting "Error: Network Failure" out of the AWS xhr.js at this point. Have verified the correct username & password, they work from the console with aws cognito-idep admin-initiate-auth. Have verified the right user pool & client IDs in config.js. Not sure what to look at next...

from sst.dev.

eng1n88r avatar eng1n88r commented on June 9, 2024

+1 for Federated Identities chapter.

from sst.dev.

triunm avatar triunm commented on June 9, 2024

Great tutorial! I've been through all the content and now building my app by customising the code produced in this tutorial. I just have question on how we can dynamically configure the app to use specific config.js file for different stages. I'm using the created config.js in this tutorial for production environment. Config.js should be different on dev or test environment like the user pool & app client id. It should be somewhere in build time, right?

Thanks in advance!

from sst.dev.

jayair avatar jayair commented on June 9, 2024

@leejh3224 Thanks for leaving your comment here.

from sst.dev.

ohenneken avatar ohenneken commented on June 9, 2024

Hi,

I have reached a point in the splendid tutorial where a first time app-client user should login in for the first time, having his email already verified.

The login function from the Login.js is executed and comes back with a new challenge 'NEW_PASSWORD_REQUIRED'.

The tutorial says nothing about this and assumes the login succeeds?

So I added a function newPasswordRequired: function(userAttributes, requiredAttributes)

-according to http://docs.aws.amazon.com/cognito/latest/developerguide/using-amazon-cognito-identity-user-pools-javascript-example-authenticating-admin-created-user.html-

but i can not get that to work. How should i proceed?

Is the tutorial somewhat outdated regarding this feature? The Login.js in the tutorial does not have the newPasswordRequired method nor are there any problems mentioned at the end of the chapter.

Thnx,

Oscar Henneken

from sst.dev.

jayair avatar jayair commented on June 9, 2024

@ohenneken Hmm you shouldn't need to do this. If you've followed this chapter - https://serverless-stack.com/chapters/create-a-cognito-test-user.html

Then you user should be able to login without having to set a new password.

from sst.dev.

mdhendri avatar mdhendri commented on June 9, 2024

With cognito how would you setup up the ability to reset ones password if the user forgot the password or even within the app?

-Michael

from sst.dev.

ohenneken avatar ohenneken commented on June 9, 2024

from sst.dev.

jayair avatar jayair commented on June 9, 2024

@mdhendri It is a few extra steps but it is fairly straightforward. Cognito will send a code to the user and they can reset their password with the code and their new password. I might write a chapter on this at some point, but here is the sample code from the Cogntio JS SDK docs - https://github.com/aws/amazon-cognito-identity-js

cognitoUser.forgotPassword({
    onSuccess: function (data) {
        // successfully initiated reset password request
        console.log('CodeDeliveryData from forgotPassword: ' + data);
    },
    onFailure: function(err) {
        alert(err);
    },
    //Optional automatic callback
    inputVerificationCode: function(data) {
        console.log('Code sent to: ' + data);
        var verificationCode = prompt('Please input verification code ' ,'');
        var newPassword = prompt('Enter new password ' ,'');
        cognitoUser.confirmPassword(verificationCode, newPassword, {
            onSuccess() {
                console.log('Password confirmed!');
            },
            onFailure(err) {
                console.log('Password not confirmed!');
            }
        });
    }
});

from sst.dev.

jayair avatar jayair commented on June 9, 2024

@ohenneken I'm not entirely sure based on what is happening here but a good place to start would be by checking the logs for API Gateway and Lambda. We have a chapter on this here - https://serverless-stack.com/chapters/api-gateway-and-lambda-logs.html

from sst.dev.

ohenneken avatar ohenneken commented on June 9, 2024

from sst.dev.

jayair avatar jayair commented on June 9, 2024

@ohenneken You should be able to inspect the Lambda logs to see why they are failing. What do the logs for the failed ones say?

from sst.dev.

ohenneken avatar ohenneken commented on June 9, 2024

from sst.dev.

jayair avatar jayair commented on June 9, 2024

@ohenneken The permissions for DynamoDB are set in the serverless.yml here https://github.com/AnomalyInnovations/serverless-stack-demo-api/blob/master/serverless.yml#L21

I'm not sure what your set up is and how it relates to the tutorial though.

from sst.dev.

walshe avatar walshe commented on June 9, 2024

hey guys, looking for some advice if you got any..

So this cognito stuff is really great, especially for managing users but also for using their authentication to get temporary user credentials in order to access secured api gateways.

I have a slightly different situation but wondering if I could somehow stay close to the same pattern/principles you guys are using.

So here is my situation.. (by the way, BigCommerce does not support OpenID Connect OIDC)

  • A user logs into their BigCommerce store and installs my app (my app is the react app with serverless backend).
  • when user clicks my app from inside BigCommerce, then bigcommerce forwards the user to my app via Auth Callback URL .. which is a serverless function I created. e.g. https://xxx.execute-api.us-east-1.amazonaws.com/prod/bc/oauth
  • In here I use a bigcommerce module to authorize the data sent to it from BigCommerce
    import {
    success,
    failure
    } from "./libs/response-lib";

    const BigCommerce = require('node-bigcommerce');

    const bigCommerce = new BigCommerce({
    logLevel: 'info',
    clientId: 'xxxx',
    secret: 'yyyy',
    callback: 'https://xxxxx.execute-api.us-east-1.amazonaws.com/prod/bc/oauth',
    responseType: 'json',
    apiVersion: 'v3' // Default is v2
    });

    export async function oauth(event, context, callback) {

    bigCommerce.authorize(JSON.stringify(event.queryStringParameters))
        .then(data => {

            console.log('Authorized! ' + JSON.stringify(data));
           
           // TODO what should I do here
         
            callback(null, {
                statusCode: 302,
                headers: {
                    Location: 'https://myreactapp.com',
                },
            })


        }).catch(error => {
            callback(null, failure(error));

        });

}

So above you can see the point at which I know the bigcommerce user is valid. The data I receive from bigcommerce is something like this: {"context":"stores/2345","code":"gpkof3rb4vo1ck0picwqjkeeeeett","scope":"store_v2_default"}.

So here is where I am at a crossroads and wondering what to do. Basically I ideally want to do something that allows me to hook into the same pattern as the tutorial and use cognito if possible.

For instance at the 'TODO' section above should I try to create (first time somehow) or retrieve a cognito user (every subsequent time) and get a token for that user using currentUser.getSession(..).getIdToken().getJwtToken() ? and then forward that token to some route in my react app e.g. myreactapp.com/bc/loginSuccess so that I can continue development just like the vein of the tutorial . When I create the cognito user I would perhaps give it some attribute that associates it with the BigCommerce user account e.g. the store id above

One other nice reason to use the cognito pool pattern is this:
While users will usually log in via the BigCommerce site and get forwarded to my app (at least once anyway for the first time), I will also want to give my users a direct login to my app. This access can only be given after they have first authenticated via BigCommerce at least once (obviously since otherwise we would have no bigcommerce data to connect them to). So if I could use the cognito pattern that I described above then this could all work really nicely.. i.e. at the time I create the cognito user (inside bigCommerce.authorize()..) above, cognito would sent the conformation email to the user with something like this: 'You logged into the app via BigCommerce but we have also created a username/password for direct access to the app, click here to confirm etc'

so anyway, curious if theres a better way or if such an approach is totally crackers..

from sst.dev.

jayair avatar jayair commented on June 9, 2024

@walshe Yeah this isn't straightforward but here is how I would do it. I haven't tried it but theoretically it should work.

  1. Create/Auth the user using the Admin Cognito APIs (https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html). This needs to be done in your serverless backend and not in the client since you don't want to expose the Admin APIs publicly. These calls need to return the JWT token.

  2. Store the JWT token and handle sessions in the React app yourself instead of relying on the Cognito JS SDK.

So effectively, you are going to do the login and signup portions on your own in the serverless backend.

from sst.dev.

walshe avatar walshe commented on June 9, 2024

thanks @jayair , actually I was thinking more since and thing I could further simplify:

so when BigCommerce forwards to my /bc/oauth and when bigCommerce.authorize(JSON.stringify(event.queryStringParameters)) succeeds, I do the following:

  1. I check if cognito user exists, if not , I create the new cognito user there with an attribute connecting user to the bigcommerce store (in the meantime an email gets sent to the new app user with login/password etc).
  2. Next I just forward user to the login form of the app (with a message saying check your email for password etc)

if on the other hand this is a second/subsequent time the user has authenticated with bigcommerce, then in this case (in my oauth method) the cognito user will be found and here I just forward them to the react app (without the message). If there is already a session still valid in the app then the user would go straight to the home page of app etc. If not then they are presented with the login form of the app

So in this approach the react app works exactly like it does in the tutorial, still uses the cognito js sdk and iam authorizer etc, saving me lots of work

thoughts ?

from sst.dev.

jayair avatar jayair commented on June 9, 2024

@walshe Yeah this would be a lot simpler than handling the sessions yourself.

from sst.dev.

walshe avatar walshe commented on June 9, 2024

@jayair one other question.

There will be an admin (maybe more than one) user for the react app.

I have a requirement that this admin once logged in to be able to 'log in as' another user. I guess I could pass the id or something of the 'other' cognito user as an extra 'asUserId' param to each api call and then on the server side check that the caller is ADMIN and the existence of the extra userID param and then run business logic using the userId param - but is there a better way of doing this ?

from sst.dev.

jayair avatar jayair commented on June 9, 2024

@walshe I don't think there is a built-in way to do this with Cognito (I'm not entirely sure though). So you'd probably have to come up with a solution that works for you.

from sst.dev.

walshe avatar walshe commented on June 9, 2024

@jayair thanks

from sst.dev.

walshe avatar walshe commented on June 9, 2024

re my comment above..

It turns out that BigCommerce doesnt want a user to have to login to the app a second time once validated by the oauth callback.. (i.e. when they click my app link from inside bigcommerce)

So, in my oauth serverless callback, if I create the Cognito user, (and save some info in a db table connecting the user to a bigcommerce store etc) is it possible for me to get credentials for that new user and just forward these credentials to the react app.

I could add a special hook in the app to accept the credentials which would allow it to make api gateway calls that are locked down with the iam_authorizer. This would avoid the user having to explicitly log into the app if they come from BigCommerce, while still allowing them to use the apps login form for direct access outside of BigCommerce. @jayair

from sst.dev.

sunkay avatar sunkay commented on June 9, 2024

@jayair have you used the withAuthenticator HOC that comes with aws-amplify-react? Is that a good way to use for Auth?

from sst.dev.

jayair avatar jayair commented on June 9, 2024

@sunkay I had a brief look at it. Just didn't find enough examples on it and so I decided to stick with the simple methods that they have. I like the current setup since it's pretty flexible and you could swap it out for a different auth provider. I would need to play around with a sample app to see it in detail.

from sst.dev.

smokeyblues avatar smokeyblues commented on June 9, 2024

Hey thanks for the tutorial. It has been informative and inspiring. Maybe too inspiring (lol) because I tried to integrate it with a gatsbyjs generated frontend and ran into a problem that doesn't have a lot of documentation online.

I have a login page with cognito and aws amplify set up but when I click the 'sign in' button I get:

_this3 is not defined

or


That is the only thing it is returning. There is no console output server-side or client-side. This may be the wrong place to ask this question but I can't find a workable solution anywhere else. Does anyone here know how to resolve this error?

Thanks in advance.

from sst.dev.

jayair avatar jayair commented on June 9, 2024

@smokeyblues Can you boil it down to the line that is throwing the error?

from sst.dev.

jayair avatar jayair commented on June 9, 2024

This issue was moved to https://discourse.serverless-stack.com/t/comments-login-with-aws-cognito/129

from sst.dev.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.