How to prevent "Delivery Status Notification (Failure)" when using service account - permissions

I am using a web application to create and share write permission in a google drive folder through service account. The creation and permission sharing successfully performed.
I am using below code to create this permission.
function createPermissionOffic(auth){
const drive = google.drive({version: 'v3', auth});
var fileId = rootFolderId;
var permissions = [
{
'type': 'user',
'role': 'writer',
'emailAddress': serviceAccountEmail
}
];
// Using the NPM module 'async'
async.eachSeries(permissions, (permission, permissionCallback)=> {
drive.permissions.create({
resource: permission,
fileId: fileId,
fields: 'id',
sendNotificationEmails: false
}, (err, res)=> {
if (err) {
// Handle error...
console.error(err);
permissionCallback(err);
} else {
console.log('Permission ID: '+ res)
permissionCallback();
}
});
}, (err)=> {
if (err) {
// Handle error
console.error(err);
} else {
// All permissions inserted
}
});
}
I was hoping that " sendNotificationEmails: false" will prevent any such mail notification. How to solve this issue?

I think that the reason of your issue is due to the spell mistake. So please modify as follows and test it again.
From:
sendNotificationEmails: false
To:
sendNotificationEmail: false
Please remove the last character s of sendNotificationEmails.
Reference:
Permissions: create

Related

How to protect routes using JWT in NextJS?

I was working on a project in next js where i need to protect some routes. I was trying to do this using jwt but for some reason it's not working, the POST method below inside index.js is injecting new entry in db bypass the verify token middleware. Any kind of help would be greatly appreciated.
verifyAuthToken.middleware.js
import jwt from "jsonwebtoken";
export default function verifyAuthToken(req, res) {
try {
const token = req.headers;
if (!token) {
return res.status(401).json({
success: false,
msg: "You are not authorized to access this route",
});
}
const { userId } = jwt.verify(
req.headers.authorization,
process.env.TOKEN_SECRET
);
if (!userId) {
return res.status(401).json({
success: false,
msg: "You are not authorized to access this route",
});
}
req.userId = userId;
} catch (error) {
res.status(401).json({
success: false,
msg: "You are not authorized to access this route",
error: error.message,
});
}
}
index.js
import verifyAuthToken from "../../../middleware/verifyAuthToken.middleware";
import Evoluter from "../../../models/Evoluter.model";
import dbConnect from "../../../server-utils/connectDB";
import { sendEmail } from "../../../server-utils/sendEmail";
import baseURL from "../../../utils/baseURL";
export default async (req, res) => {
const { method } = req;
verifyAuthToken(req, res);
await dbConnect();
switch (method) {
// #route GET api/evoluters
// #desc Create new evoluter
// #access Private
case "POST":
try {
const { name, email } = req.body;
const evoluter = await Evoluter.findOne({ email: email.toLowerCase() });
if (evoluter) {
return res.status(400).json({
success: false,
msg: "Evoluter already exists",
});
}
const newEvoluter = await Evoluter.create({
name,
email: email.toLowerCase(),
});
try {
await sendEmail({
email: newEvoluter.email,
subject: "Welcome to Rubrica",
message: `Hi ${newEvoluter.name}, welcome to Rubrica. Please click on the link below to activate your account. ${baseURL}/home/${newEvoluter._id}`,
});
res.status(201).json({
success: true,
data: newEvoluter,
msg: "Evoluter created successfully. Please check your email to activate your account.",
});
} catch (error) {
console.log(error);
res.status(500).json({
success: false,
msg: "Error sending invitation email, please let the admin know.",
});
}
} catch (error) {
res.status(400).json({
success: false,
msg: "Sorry, we couldn't send the invitation. Please try again.",
error: error,
});
}
break;
default:
res.status(400).json({
success: false,
msg: "Invalid request",
});
break;
}
};
Here we can see that the verify token middleware was fired as expected, however the data inside the body got injected into the DB which we don't really need.
Postman output
Please let me know if you need more information I don't have much experience asking questions in stackoverflow.
It is bypassing the verifyAuthToken function because You are doing it anyway you are just generating response on verifyAuthToken
You can return a boolean at the end of your verifyAuthToken something like this:
if (userId) return true;
else return false;
Then in your index.js before injecting data to database instead of verifyAuthToken(req, res); do this:
if (!verifyAuthToken(req, res)) {
return;
}
You can also use NextJs middleware

Is it possible to update the userAttributes(email) in aws cognito using React-Native?

I have tried below lines to update the userEmail in aws cognito.
For update email, the updateAttributes is needed.
import {Auth} from 'aws-amplify';
let user = await Auth.currentAuthenticatedUser();
user.session = user.signInUserSession;
let userAttributes = await Auth.userAttributes(user);
let new = { Name: 'email', Value: emailAddress }
Auth.updateUserAttributes(user, new).then((res) => {
console.log("success", res);
}).catch(e => {
console.log("EEE", e);
});
But when I tried, I got this error:
{"code": "InvalidParameterException", "message": "user.Value: Attribute does not exist in the schema.
user.Name: Attribute does not exist in the schema.
", "name": "InvalidParameterException"}
You are almost there, the input should just be a normal key/value where the key is 'email' and the value is the emailadress.
let new = { email: emailAddress } // <-- change this line
Auth.updateUserAttributes(user, new).then((res) => {
console.log("success", res);
}).catch(e => {
console.log("EEE", e);
});
Normally when working with cognito with the aws-sdk you should use the syntax that you did, but it is diffrent with amplify.
This way you can edit more userAttributes at once. Take a look at det amplify docs for a more detailed look:
https://docs.amplify.aws/lib/auth/manageusers/q/platform/js/#managing-user-attributes

How to store a property in a session with express-session?

I have the following code:
app.post("/login", (req, res) => {
const { username, password } = req.body;
// dummy local database with custome helper functions to look up a user:
db.users.findByUsername(username, (err, user) => {
if (!user) return res.status(403).json({ msg: "No user found!" });
if (user.password === password) {
// Adding properties to session
req.session.authenticated = true;
req.session.user = {
username,
password,
};
console.log(req.session);
// Session is printed in terminal with the above properties. Works fine up to here.
res.redirect("/shop");
} else {
res.status(403).json({ msg: "Bad Credentials" });
}
});
});
I used express-session to create a session and i'm storing it in memory. I created a middleware that would allow a user to access a /shop page only if they're authenticated and have the req.session.authenticated property set to true. For some reason, after they log in, and they're redirected to the /shop page, the properties created in the session are no longer there. Here's the rest of the code:
Authentication middleware:
function ensureAuthentication(req, res, next) {
if (req.session.authenticated) {
// Properties that were added upon logging in are not attached.
return next();
} else {
res.status(403).json({ msg: "You're not authorized to view this page" });
}
}
Shop page
app.get("/shop", ensureAuthentication, (req, res) => {
// Send the user object to the view page:
res.render("shop", { user: req.session.user });
});
Any opinions? Am I missing something here? Does the order of how I have the endpoints written matter?

How to properly store a CognitoUser?

I'm working on a simple React/Typescript application to test Cognito and I'm running into some problems handling the user, I have a function that gets the user like so:
/* CognitoUtils.tsx */
import UserPool from './UserPool';
export const getCognitoUser = (phone: string): CognitoUser => {
const userData: ICognitoUserData = {
Username: phone,
Pool: UserPool,
};
return new CognitoUser(userData);
}
I have the UserPool defined in a separate file like so:
/* UsePool.tsx */
import { ICognitoUserPoolData, CognitoUserPool } from "amazon-cognito-identity-js";
const poolData: ICognitoUserPoolData = {
UserPoolId: 'XXX',
ClientId: 'XXX',
Storage: window.sessionStorage
};
const userPool = new CognitoUserPool(poolData);
export default userPool;
And this is the code I use to sign in:
/* CognitoUtils.tsx */
export const signIn = (phone: string) => {
var authenticationDetails = new AuthenticationDetails({
Username: phone,
Password: 'XXXX',
});
const user = getCognitoUser(phone);
user.authenticateUser(authenticationDetails, {
onSuccess: function(session: CognitoUserSession) {
console.log("Succesfully signed in", session, "current user", user);
},
onFailure: function(error) {
console.log("Error while signing in", error);
},
});
}
This is working fine, the user and session objects are printed without a problem.
I have a button for signing out that calls this function:
/* CognitoUtils.tsx */
export const signOut = (phone: string) => {
var user = getCognitoUser(phone);
user.getSession((err: any, session: CognitoUserSession) => {
console.log("Getting session error", err, "session:", session);
user.globalSignOut({
onSuccess: (msg: string) => {
console.log("Succesfully signed out", msg);
},
onFailure: (err: globalThis.Error) => {
console.log("Error while signing out", err);
}
});
});
}
This causes the following error on user.getSession():
Getting session error Error: Local storage is missing an ID Token, Please authenticate
Despite having an id token in my local storage (which is generated on sign in), I have tried saving the user in a shared variable in the same file, saving it on a redux store and even converting the object into a json and saving using localStorage, the closes I've ever got to have this working is the signOut function working after signIn but the user breaking if I refresh the page in between.
My question is, what is the proper way of storing/retrieving this user?
This is the closest I've found to my error but even after moving the UsePool to a separate file this still happens.
This is the tutorial I've been following.
Any help is greatly appreciated.

AWS Cognito - User stuck in CONFIRMED and email_verified = false

How do I go about email verifying a user who is CONFIRMED yet email_verified is false?
The scenario is roughly an agent signs up user on their behalf, and I confirm the user through the admin call adminConfirmSignUp. At that point, the user cannot change their password because of the email_verified flag being false.
I can't call resendConfirmationCode because the user is already confirmed.
I can't call forgotPassword because the email_verified flag is false.
The best I can think of is deleting the user account and calling signUp (prompting them to re-enter their password or a new password), hence recreating their account.
Using the AWS CLI you can update the email_verified attribute:
aws cognito-idp admin-update-user-attributes
--user-pool-id eu-west-xxxxxx
--username xxxxyyyy#example.com
--user-attributes Name=email_verified,Value=true
Here is the official documentation: https://awscli.amazonaws.com/v2/documentation/api/latest/reference/cognito-idp/admin-update-user-attributes.html
You can change email_verified, phone_number_verified and other attributes by calling adminUpdateUserAttributes without any lambdas and triggers:
'use strict'
var AWS = require('aws-sdk')
AWS.config.update({
accessKeyId: 'YOUR_ACCESS_KEY_HERE',
secretAccessKey: 'YOUR_SECRET_ACCESS_KEY_HERE',
region: 'us-east-1' // change region if required
});
var CognitoIdentityServiceProvider = AWS.CognitoIdentityServiceProvider
var client = new CognitoIdentityServiceProvider({
apiVersion: '2016-04-19',
region: 'us-east-1' // change region if required
})
client.adminUpdateUserAttributes({
UserAttributes: [{
Name: 'phone_number_verified',
Value: 'true'
}, {
Name: 'email_verified',
Value: 'true'
}
// other user attributes like phone_number or email themselves, etc
],
UserPoolId: 'COGNITO_USER_POOL_ID_HERE',
Username: 'USERNAME'
}, function(err) {
if (err) {
console.log(err, err.stack)
} else {
console.log('Success!')
}
})
Currently, Cognito does not allow an external agent to update the email_verified and phone_verified attributes on behalf of the user. The only way these can be marked as true is through a code verification process which can be done by the end user. The exception to this is with admin level APIs, as answers below describe, but those shouldn't be done from client side.
The process is this: user signs-in and gets an access token. They then call GetUserAttrbuteVerificationCode API with the attribute they want to verify. This will deliver a code to the user, which can be used by calling VerifyUserAttribute which will flip the attribute as verified.
You can now programmatically set email_verified to true using the Pre-Signup lambda trigger and modifying the returned event with event.response.autoVerifyEmail = true;
It's not in the docs yet but referenced on this github issue. Also read working with cognito lambda triggers.
Here is the Another Approach you can use to create users by Agents.
You can Use AdminCreateUser on the Behalf of user. By calling this API user will be created with a temp Password which will be sent to the user Email Address. (i.e. User will be in Force_Change_Password state). Now use RespondToAuthChallenge API to change the Password.
Note: You need to set "email_verified" attribute in attribute List. to make sure user email will be verified.
Here is the Code Example in NodeJS:
var params = {
UserPoolId: process.env.userPoolId, /* required */
Username: email,//'STRING_VALUE', /* required */
DesiredDeliveryMediums: [
"EMAIL",
/* more items */
],
ForceAliasCreation: false,
UserAttributes: [{
Name: 'email_verified',
Value: 'True'
},/* any other Attributes*/],
};
cognitoidentityserviceprovider.adminCreateUser(params, function (err, data) {
if (err) {
console.log(err, err.stack);
reject(err); // an error occurred
}
else {
console.log(data);
resolve(data);
}// successful response
});
});
It was giving an error message: 'No email provided but email_verified was true', code: 'InvalidParameterException'.
So I added also email attribute into attributes list.
const params = {
UserPoolId: this.userPoolId /* required */,
Username: username /* required */,
TemporaryPassword: password,
DesiredDeliveryMediums: ['EMAIL'],
ForceAliasCreation: false,
UserAttributes: [
{
Name: 'email_verified' /* required */,
Value: 'true',
},
{
Name: 'email' /* required */,
Value: email,
},
],
};
then create the user with these params
cognitoidentityserviceprovider.adminCreateUser(
params,
(err, data) => {
console.log(data);
if (err) {
console.log(err);
reject(err);
throw new BadRequestException(err);
}
// an error occurred
else resolve(data); // successful response
},
);
Trigger on pre-registration this lambda function (Node.js v6):
exports.handler = function(event, context) {
event.response.autoConfirmUser = true;
event.response.autoVerifyEmail = true;
event.response.autoVerifyPhone = true;
context.done(null, event);
};
Using the "Configure test event" you can test it first with this payload
{
"version": 1,
"triggerSource": "PreSignUp_SignUp",
"region": "<region>",
"userPoolId": "<userPoolId>",
"userName": "<userName>",
"callerContext": {
"awsSdk": "<calling aws sdk with version>",
"clientId": "<apps client id>"
},
"request": {
"userAttributes": {
"email": "usertestsns06#yopmail.com"
},
"validationData": {
"k1": "v1",
"k2": "v2"
}
},
"response": {
"autoConfirmUser": false,
"autoVerifyEmail": false,
"autoVerifyPhone": false
}
}
Now when you create the user from the API those verifications flags should be true.
verify user email on aws cognito with python using boto3
response =client.get_user_attribute_verification_code(AccessToken='eyJraWQiOiJtTEM4Vm......',AttributeName='email')
response = client.verify_user_attribute( AccessToken='eyJraWQiOiJtTEM......', AttributeName='email', Code='230433')
Here is the Official Documentation.
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-idp.html