I am trying to build Signup through a lambda function with AWS user pool where I added a custom attribute called type.
When I am sending a type value with signup, an error "A client attempted to write unauthorized attribute" is populating.
I am using 'amazon-cognito-identity-js' package to save data.
Here is my code snippet
const attributeList = [];
attributeList.push(new AmazonCognitoIdentity.CognitoUserAttribute({Name:"name",Value:user.username}));
attributeList.push(new AmazonCognitoIdentity.CognitoUserAttribute({Name:"custom:type",Value:'asd'}));
attributeList.push(new AmazonCognitoIdentity.CognitoUserAttribute({Name:"gender",Value:user.gender}));
attributeList.push(new AmazonCognitoIdentity.CognitoUserAttribute({Name:"email",Value:user.email}));
userPool.signUp(user.email, user.password, attributeList, null, function(err, result){
if (err) {
return reject(err);
}
return resolve(result);
});**strong text**
After that you added a new attribute, you should select the user attributes this app client can read and write.
Steps:
Go to your Cognito User Pool page
Click on the "App Client" from the left side menu
Click on the "Set attribute read and write permissions"
Make sure you added the necessary(read/write) permissions for the needed attribute
In addition to the above answer, sometimes custom attributes may take time to reflect under clients. Because I noticed it around 15 mins but after 1 hour it was there.
Related
i was trying to create once logged in the website a function onClick() in the member area. When text clicked would let add the user email in another role and enable user to other functions. I've tried with the code below, but it's not adding user email to the other role(ideas to fix it?). However, what's your opinion? maybe it could be better to let two different types of log in/register when in registration phase? (If answer is yes, how could i do that?)
`import wixUsers from 'wix-users';
import {roles} from 'wix-users-backend';
export function text67_click(event) {
/* This function was added from the Properties & Events panel. To learn
more, visit http://wix.to/UcBnC-4 */
// Add your code for this event here:
function getUser(loginEmail){this}
function assignRole(consulente, loginEmail) {
return roles.assignRole(consulente, loginEmail, { suppressAuth: false })
.then( () => {
console.log("Role assigned to member");
})
.catch((error) => {
console.log(error);
});
}
}`
Thanks in advance, for your opinions
you are trying to run backend function on frontedn. wix isnt allow it: "Member roles help you manage which site members can access certain pages. The Roles APIs allow you to manage the members assigned as holders of each role from your site's backend code." see here
to learn how to call backend function from frontend see here
I am trying to migrate users to Cognito when they sign in the first time. For this I wrote a lambda function that does call an API to check if the users exist in db or not ? if the user exists, it will be created in cognito but I am not sure how do I tell the application that user is created and it should allow the user to login .
Here is the code in c#:
public async Task<Stream> FunctionHandlerAsync(Stream stream, ILambdaContext context)
{
RootObject rootObj = DeserializeStream(stream);
User user = new User(rootObj.userName, rootObj.request.password);
ApiResponse apiResponse = await MobileAuthenticateAsync(user.UserName, user.Password);
// Considering apiResponse returns "user authenticated", we create the user in //cognito. This is working.
// How do I send response back to Application so it knows that user is // //created and authenticated and should be allowed to login.
//Before returning stream, I am setting following 2 status.
rootObj.response.finalUserStatus = "CONFIRMED"; // is this correct ?
rootObj.response.messageAction = "SUPPRESS";
return SerializeToStream(rootObj);;
}
You're pretty close.
You can see the full documentation on the Migrate User Lambda Trigger page, however in short you need your response to look like:
{
response: {
userAttributes: {
email: 'user#example.com',
email_verified: true,
custom:myAttribute: 123,
},
finalUserStatus: 'CONFIRMED',
messageAction: 'SUPPRESS',
forceAliasCreation: false,
}
}
Where:
userAttribute: this is a dictionary/map of the user's attributes keys in cognito (note that any custom attributes need to be prefixed with custom:), to the values from the system you're migrating from. You do not need to provide all of these, although if you're using an email alias you may want to set email_verified: true to prevent the user having to re-verify their e-mail address.
finalUserStatus: if you set this to CONFIRMED then the user will not have to re-confirm their email address/phone number, which is probably a sensible default. If you are concerned that the password is given as plain-text to cognito this first-time, you can instead use RESET_REQUIRED to force them to change their password on first sign-in.
messageAction: should probably be SUPPRESS unless you want to send them a welcome email on migration.
forceAliasCreation: is important only if you're using email aliases, as it stops users who manage to sign-up into cognito being replaced on migration.
If you respond with this (keeping the rest of the original rootObj is convenient but not required then the user will migrated with attributes as specified.
If you throw (or fail to respond with the correct event shape) then the migration lambda fails and the user is told that they couldn't migrated. For example, because they do not exist in your old user database, or they haven't provided the right credentials.
I'm creating a model that I will use to authenticate users for API access, and I have a secret field where I want to store a Base64 encoded uuid/v4 generated value.
I went through the different field types and options, but still not seeing how I could achieve this.
Is there a way to hook in model instance creation, and set the value of my secret field ?
Yes, you can use the pre hooks.
In your situation, the basics would be:
AuthenticationModel.schema.pre("save", function(next) {
const secretValue = generateSecretValue();
this.secret = secretValue;
next();
});
That would go before your final AuthenticationModel.register(); in your model.js file.
This is how I set it up, also with the pre-save hook. My problem before was that I was getting the same random number again until I restarted the server.
Store.schema.pre('save', function (next) {
if (!this.updateId && this.isNew) {
// generates a random ID when the item is created
this.updateId = Math.random().toString(36).slice(-8);
}
next();
});
Using this.isNew was also useful in my case.
I'm trying to update the values and connections on my current viewer within the Relay store.
So without calling the mutation signIn if I print:
console.log(viewer.name) // "Visitor"
console.log(viewer.is_anonymous) // true
on Mutations we got the method updater which gives us the store, so in my mutation I'm doing something like this:
mutation SignInMutation($input: SignInInput!){
signIn(input: $input){
user {
id
name
email
is_anonymous
notifications{
edges{
node {
id
...NotificationItem_notification
}
}
}
}
token
}
}
So my updater method has:
const viewer = store.get(viewer_id);
const signIn = store.getRootField('signIn');
viewer.copyFieldsFrom(signIn.getLinkedRecord('user'))
After this I updated the store I got the name email is_anonymous fields updated with the data that just came from the graphql endpoint (I mean now name is "Erick", is_anonymous is now false, which is great), but If I try to do viewer.notifications and render it, the length of the viewer.connections seem to be 0 even when it has notifications.
How can I update my current viewer and add the notifications from the MutationPayload into the store without the need to force fetch?
Im using the latest relay-modern and graphql.
PS: Sorry for the bad formation, but is just impossible to format the code the way OF wants me to, i formated it to 4 spaces and still gave me errors.
With some reorganisation of your GraphQL schema it might be possible to remove the need to interact directly with the Relay store after your sign-in mutation. Consider:
viewer {
id
currentUser {
name
email
}
}
When a user that is not logged in, currentUser would return null.
You could then modify your login mutation to be:
mutation SignInMutation($input: SignInInput!){
signIn(input: $input){
viewer {
id
currentUser {
name
email
token
}
}
}
}
Knowing the 'nullability' of the currentUser field provides an elegant way of determining if the user is logged in or not.
Based on the presence of the token field implies that you are using JWT or similar to track login status. You would need to store this token in local storage and attach it to the headers of the outgoing Relay requests to your GraphQL endpoint if it is present.
Storing the token itself would have to be done in the onCompleted callback of where you make the mutation request (you will have access to the payload returned by the server in the arguments of the callback function).
As an alternative to the token, you could also explore using cookies which would provide the same user experience but likely require less work to implement then JWT tokens.
I've set up my app to enable email verification and the emails come through fine. Trouble is, when I make a call to retrieve a User object, either with Parse.User.current() or by querying by id, the response does not contain the emailVerified field. I can't therefore check if the user is email verified or not.
I've tried this both in client side code and in cloud code with the same result.
You can try this out in your own code with a very simple snippet in the console:
var user = Parse.User.logIn("your_username", "your_password", {
success: function(user) {
console.log(user)
}
});
That field seems to be protected, the only solution I can think of would be to query for where the value is true using some variant of where and check if you get a user back or not. If user is null, they haven't verified their email.