I am trying to update attributes from users from a AWS Cognito userpool with AWS Amplify.
try {
const user = await Auth.currentAuthenticatedUser();
await Auth.updateUserAttributes(user, {
'nickname': 'newtestname'
});
} catch (error) {
console.log(error);
}
But I get the following error:
InvalidParameterException: user.nickname: Attribute cannot be updated.
I would expect it to be updateable because I made the attributes writable in the userpool-client section in my SAM template:
WriteAttributes:
- email
- nickname
UserPoolId: !Ref MyCognitoUserPool
This is also reflected correctly in the console:
I have no app client secret and all auth flows enabled. The security configuration is set to enabled.
Users can register, so I assume that the Amplify config in the client is alright.
What is wrong here?
I found the issue. On creation of the userpool I had to set the mutable flag within the schema definition, like so:
Schema:
- Name: email
Mutable: true
...
- Name: nickname
Mutable: true
...
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html
Related
I am new in AWS Cognito topic. I am using IaC - Pulumi Typescript for deployment to AWS.
the purpose is to create two users(user1 and user2) and and give access only one user to invoke API GW.
// Create a Cognito user pool
const userPool = new pulumiAws.cognito.UserPool('my-user-pool', {});
// Create a Cognito user pool client
const userPoolClient = new pulumiAws.cognito.UserPoolClient('user-pool-client', {
userPoolId: userPool.id,
explicitAuthFlows: ["USER_PASSWORD_AUTH"],
});
//Create the first user group
const group1 = new pulumiAws.cognito.UserGroup('group1',{
description: 'Group1',
userPoolId: userPool.id
})
//Create the second user group
const group2 = new pulumiAws.cognito.UserGroup('group2',{
description: 'Group2',
userPoolId: userPool.id,
})
//Create the first user
const user1 = new pulumiAws.cognito.User('user1',{
username: 'user1',
password: 'TestUser1!',
userPoolId: userPool.id,
})
//Create the second user
const user2 = new pulumiAws.cognito.User('user2',{
username: 'user2',
password: 'TestUser2!',
userPoolId: userPool.id
})
//Assign the user1 to the group
const user1GroupMembership = new pulumiAws.cognito.UserInGroup('user1-group-membership',{
groupName: group1.name,
userPoolId: userPool.id,
username: user1.username
})
//Assign the user2 to the group
const user2GroupMembership = new pulumiAws.cognito.UserInGroup('user2-group-membership',{
groupName: group2.name,
userPoolId: userPool.id,
username: user2.username
})
const authorizer = new pulumiAws.apigateway.Authorizer("my-authorizer", {
restApi: api.id,
type: "COGNITO_USER_POOLS",
identitySource: "method.request.header.Authorization",
providerArns: [userPool.arn],
});
const method = new pulumiAws.apigateway.Method('method', {
authorization: 'COGNITO_USER_POOLS',
authorizerId: authorizer.id,
httpMethod: 'GET',
resourceId: resource.id,
restApi: api.id,
authorizationScopes: [user1GroupMembership.groupName],
});
Now I expect that the token which I created by using user1 credentials can be able to invoke API GW , but I get Unauthorized error.
On the other hand , if I remove authorizationScopes: [user1GroupMembership.groupName], from apigateway.Method(the code piece is in the above) then I can invoke the API GW via of course both user1 and user2 users.
Could you please give an idea how can give access only group1 or user1 to invoke API GW? what is wrong I am doing there.
Best Regards
I think that either user 1 or user 2 will be able to contact the Gateway API. However, you can set up an authorization mechanism with the implementation of a lambda authorizer which will be in charge of authorizing only the requests of the users of the group 1
I am building an app using Ionic, Capacitor and AWS Amplify. I am having some issues
I have set up federated sign-in for my app using the capacitor plugin https://github.com/capacitor-community/facebook-login and call Auth.federatedSignIn() as per the below. This logs my user in with a federated identity. This is great, but it means I cannot use #auth(rules: [{ allow: owner }]) in my graphql schema. Is there any way to create a user in the userpool when calling Auth.federatedSignIn()? I know that calling Auth.federatedSignIn({ provider: "Facebook" }) and using the hosted UI works like this, but I do not want to redirect my user to a browser/chrome tab to sign in. I would like the authentication to be provided by the native functionality provided by the above capacitor plugin.
Using the federated identity allows me to restrict access to my graphql schema using IAM: #auth(rules: [{ allow: private, provider: iam }]) but this is limited to private and public rules. I want to limit the graphql api so that users can see only their own entries with functionality like #auth(rules: [{ allow: owner }]).
Maybe I am going about this the wrong way? I'm stumped. Any help is appreciated. Thanks.
const FBLogIn = async () => {
const result = await FacebookLogin.login({ permissions: FACEBOOK_PERMISSIONS });
const { email } = await FacebookLogin.getProfile({ fields: ['email'] });
try {
const userDetails = await Auth.federatedSignIn("facebook", { token: result.accessToken.token, expires_at: result.accessToken.expires }, { name: result.accessToken.userId, email: email })
} catch (error) {
console.log(error)
}
}
How can I pass the Cognito user's idToken to Amplify.configure() , cause the users have to be authenticated, not as a guest user. So Instead of getting an unauthenticated identityId, How do I get an authenticated Id by setting in the aws amplify configure.
For sign-in and sign-up we are not using Amplify instead we are using Rest API
Currently I'm sending Object to configure as follows,
{
Auth: {
identityPoolId: const.identityPoolId,
IdentityId: 'us-east-1:xxxxxxxxxxxxxxxxxxxyyyyyyzzzzzz',
region: 'us-east-1'
},
Analytics: {
disabled: false,
autoSessionRecord: true,
AWSPinpoint: {
appId: PinpointId,
region: 'us-east-1',
bufferSize: 1000,
flushInterval: 5000,
flushSize: 100,
resendLimit: 3
}
}
}
};
Any help is highly appreciated. Thanks
In serverless framework, I want to set the deployment bucket as
<project_name>-<stage>-<account_id>
I can get the stage using a custom variable, like:
custom:
stage: ${opt:stage, self:provider.stage}
but how can I get the aws account id? I already tried to used serverless-pseudo-parameters, like this below, without success.
custom:
account_id: #{AWS::AccountId}
plugins:
- serverless-pseudo-parameters
Someone could help me to set the account id as a custom variable?
According to the documentation, to get the Account Id, you can use external js files:
// myCustomFile.js
module.exports.getAccountId = async (context) => {
return context.providers.aws.getAccountId();
};
.
# serverless.yml
service: new-service
provider: aws
custom:
accountId: ${file(../myCustomFile.js):getAccountId}
For anyone using Serverless with an "assumed role" where your IAM users are defined in a master AWS account and you're trying to deploy in a child account using a role from that child account: the documented solution - the one in the accepted answer above - does not work.
This setup in described in detail here: https://theithollow.com/2018/04/30/manage-multiple-aws-accounts-with-role-switching/. When using serverless with an --aws-profile that's configured to assume a role defined in another account, sts.getCallerIdentity() returns the account info of your master account from the default profile, and not the account of the assumed role.
To get the account ID of the assumed role (which is where we're deploying to), I did the following:
const { STS } = require('aws-sdk');
module.exports.getAccountId = async (context) => {
// This loads the AWS credentials Serverless is currently using
// They contain the role ARN of the assumed role
const credentials = context.providers.aws.getCredentials();
// init STS using the same credentials
const sts = new STS(credentials);
const identity = await sts.getCallerIdentity().promise();
return identity.Account;
};
Edit:
Found an even better way, that is simpler than the one presented in Serverless docs and also works fine with assumed roles:
module.exports.getAccountId = async (context) => {
return context.providers.aws.getAccountId();
};
You should be able to access them below as per below example https://serverless.com/framework/docs/providers/aws/guide/variables/
Resources:
- 'Fn::Join':
- ':'
- - 'arn:aws:logs'
- Ref: 'AWS::Region'
- Ref: 'AWS::AccountId'
- 'log-group:/aws/lambda/*:*:*'
It seems like your syntax is wrong. Try
custom:
account_id: ${AWS::AccountId}
Because at least in the example that you provided you are using #{AWS::AccountId}
Notice the hashtag in your one?
I've been pulling out my hair trying to set Appsync and Cognito in my React Native app.
I've tried the two following ways:
Amplify.configure(config);
OR
Amplify.configure({
Auth: {
region: config.aws_cognito_region, // REQUIRED - Amazon Cognito Region
userPoolId: config.aws_user_pools_id, // OPTIONAL - Amazon Cognito User Pool ID
userPoolWebClientId: config.aws_user_pools_web_client_id, // User Pool App Client ID
},
});
AND
const client = new AWSAppSyncClient({
url: appSyncConfig.graphqlEndpoint,
region: appSyncConfig.region,
auth: {
type: appSyncConfig.authType,
jwtToken: async () => (await Auth.currentSession()).getIdToken().getJwtToken(),
},
});
OR
const client = new AWSAppSyncClient({
url: appSyncConfig.graphqlEndpoint,
region: appSyncConfig.region,
auth: {
type: appSyncConfig.authType,
apiKey: appSyncConfig.apiKey,
},
});
I've also followed these two tutorials Tackling user auth, Building a notes app.
In both cases, I get the following error in GraphQL with no description:
Error: Network error: Response not successful: Received status code
This is while in Authorization Type is Amazon Cognito User Pool. I've also tried AWS Identity and Access Management (IAM), but that gives me a 403 error. Can someone point me in a direction where I can debug this further?
It might be caused a typo in the docs / article you've read. Trying replacing :
auth: {
type: appSyncConfig.authType,
apiKey: appSyncConfig.apiKey
}
with :
auth: {
type: appSyncConfig.authenticationType,
apiKey: appSyncConfig.apiKey
}
I have the following code and its working for me:
import Amplify, { Auth } from 'aws-amplify';
import API, { graphqlOperation } from '#aws-amplify/api'
window.LOG_LEVEL = 'DEBUG';
Amplify.configure({
Auth: {
"identityPoolId":'ap-southeast-1:xxxxxx',
"mandatorySignIn": false,
"region": "ap-southeast-1",
"userPoolId": "ap-southeast-1_xxxx",
"userPoolWebClientId": "xxxxxxx"
},
API:{
"aws_appsync_graphqlEndpoint": 'https://xxxx.ap-southeast-1.amazonaws.com/graphql',
"aws_appsync_region": 'ap-southwest-1',
"aws_appsync_authenticationType": 'AMAZON_COGNITO_USER_POOLS',
"aws_appsync_apiKey": 'null',
}
});