I created a discord bot that needs to retrieve the user's email to perform some task. However, after I have changed the OAuth scope to email, my returned user property still doesn't have a email property.
this is my sample authorization URL:
https://discord.com/oauth2/authorize?client_id=123456789&scope=email%20bot&permissions=268435506
and this is my test function:
bot.on("message", (msg) => {
console.log(msg.member.user);});
My returned user does not even have a email property.
user {
id: '652349438404198401',
system: null,
locale: null,
flags: UserFlags { bitfield: 0 },
username: 'Geek_.0',
bot: false,
discriminator: '8104',
avatar: 'acba52ce51c54dacbcb2cba257c724af',
lastMessageID: '812447507249889300',
lastMessageChannelID: '809526161964531766'
}
Related
I'm using AWS cognito as a federated identity service to federate Salesforce IDP (we'll have more in the future)
Recently I started getting an "invalid state" error. And after days of research, I found out that:
when the authentication flow starts on cognito there is no error
cognito redirects the user to salesforce
user gets sent back to cognito after login
when the authentication flow starts on salesforce we receive the "invalid_state" error.
user logs in directly over salesforce
salesforce redirects the user to cognito
I need to be able to start the flow from salesforce for the following cases:
the first time user is registered in salesforce
when user reset's password in salesforce
The setup of AWS Cognito via CDK:
const userPool = new UserPool(this, 'duck-user-pool', {
autoVerify: {
email: true,
phone: false,
},
mfa: Mfa.OFF,
mfaSecondFactor: {
sms: false,
otp: false,
},
selfSignUpEnabled: false,
standardAttributes: {
email: {
mutable: true,
required: true,
},
}
});
const salesforceIdP = new CfnUserPoolIdentityProvider(
this,
'salesforceIdP',
{
attributeMapping: {
email: 'email',
family_name: 'family_name',
given_name: 'given_name',
},
providerDetails: {
attributes_request_method: 'GET',
authorize_scopes: 'email openid profile',
oidc_issuer: config.SalesforceBaseUrl,
client_id:
salesforceIdPCredentials.secretValueFromJson(
'CLIENT_ID'
),
client_secret:
salesforceIdPCredentials.secretValueFromJson(
'CLIENT_SECRET'
),
},
providerName: 'salesforce-idp',
providerType: 'OIDC',
userPoolId: userPool.userPoolId,
}
);
const spaClient = userPool.addClient(
'duck-user-pool-client-spa',
{
authFlows: {
userPassword: true,
userSrp: true,
},
generateSecret: false,
refreshTokenValidity: Duration.days(30),
supportedIdentityProviders: [
UserPoolClientIdentityProvider.COGNITO,
UserPoolClientIdentityProvider.custom(
salesforceIdP.providerName
),
],
oAuth: {
callbackUrls: config.CallbackURLs,
flows: {
authorizationCodeGrant: true,
implicitCodeGrant: false,
clientCredentials: false,
},
logoutUrls: config.LogoutURLs,
scopes: [
OAuthScope.EMAIL,
OAuthScope.OPENID,
OAuthScope.PHONE,
OAuthScope.PROFILE,
],
},
}
);
On the salesforce side, configuration was made to redirect the user to following url:
https://sandbox-duck.auth.eu-west-1.amazoncognito.com/oauth2/idpresponse
I've found out cognito is using a query parameter called state (against CSRF attacks) and if the parameter is not in the URL it throws this error.
The setup was working until a month ago but suddenly it stopped working. Is there a way to work around this limitation?
my code:
if(message.content == prefix + "dev"){
const owner = client.users.fetch('462223589043863562');
console.log(owner.user);
console.log(owner.id);
console.log(owner);
message.channel.send(`eggy is the dev of this chad ass bot. Discord: ${owner}`);
logs:
undefined
undefined
Promise {
User {
id: '462223589043863562',
system: false,
locale: null,
flags: UserFlags { bitfield: 64 },
username: 'eggyy',
bot: false,
discriminator: '0001',
avatar: 'a_de18cc5553a2fd2e5fbd3d3e3491595b',
lastMessageID: '865041520075735040',
lastMessageChannelID: '864827452063875125'
}
}
Also, when doing owner.Promise.User.user it gives an error: TypeError: Cannot read property 'User' of undefined.
<client>.users.fetch() returns a promise which you can handle simply by using await. Therefore, in order to resolve it, you can just replace your current owner definition with const owner = client.users.fetch('462223589043863562');.
However, if you are going to use await, you must make your present function async (e.g. client.on('message', async message => {}).
I build an app using aws-amplify that allows login with Cognito users. However, Auth.forgotPassword seems to be sending SMS to mobile device instead of EMAIL. How can I change the behavior such that it sends an email?
Here are related code:
Auth.forgotPassword(this.state.username)
.then(data => this.setState({instruction: 'An email has been sent to your email with a temporary password.', usernameError: false, passwordError: false}))
.catch(err => this.setState({instruction: err.message, usernameError: false, passwordError: false}));
You can configure what you need to verify when forgotPassword API is triggered in the AWS Cognito Console.
Amazon Cognito > Manage User Pool > Choose your pool > General Settings > MFA and verifications > Which attributes do you want to verify?
Also when you trigger the ForgotPassword API you get CodeDeliveryDetails Object in response
const result = await Auth.forgotPassword(username);
console.log(result);
CodeDeliveryDetails: {
"AttributeName": "email",
"DeliveryMedium": "EMAIL",
"Destination": "n***#g***.com"
}
From the result, you get on which medium the code has been delivered and accordingly notify the user in the app.
I am new to mongoDB and mongoose. But what I am trying to do is be able to access the users I have stored in my database by their email, if a user was successfully retrieved the I will compare the password they wrote with the hashed password stored in the database
this is what I have for my Schema
UserSchema
var UserSchema = new Schema({
firstName: { type: String, required: true }, //require makes it so that the fields can't be left blank
lastName: {type: String, required: true},
emailAddress: {type: String, required: true},
password: {type: String, required: true}
});
var User = mongoose.model("User", UserSchema);
I am using the basic-auth package in my routes.js file in order to test this api in postman, this is the part where I am stuck, const user = User.find({'emailAddress': credentials.name, user.emailAddress} ); I am having trouble putting together a query to access user email from the database
//This middle-where function will authenticate users
const authenticateUser = (req, res, next) => {
let message = null;
// Parse the user's credentials from the Authorization header.
const credentials = auth(req);
// If the user's credentials are available...
if (credentials) {
// Attempt to retrieve the user from the data store
// by their email (i.e. the user's "key"
// from the Authorization header).
const user = User.find({'emailAddress': credentials.name, user.emailAddress} );
// If a user was successfully retrieved from the data store...
if (user) {
// Use the bcryptjs npm package to compare the user's password
// (from the Authorization header) to the user's password
// that was retrieved from the data store.
const authenticated = bcryptjs
.compareSync(credentials.pass, user.password);
in this express router I will be returning a user only after being authenticated
//GET /api/users 200, THIS WORKS IN POSTMAN
//This Route returns the currently authenticated user,
router.get('/users', authenticateUser, (req, res) => {
//within the route handler, the current authenticated user's information is retrieved from the Request object's currentUser property:
const user = req.currentUser;
//we use the Response object's json() method to return the current user's information formatted as JSON:
res.json({
firstName: user.firstName,
lastName: user.lastName,
});
});
Can someone help? For reference this is my repo https://github.com/SpaceXar20/rest_api-mongo-p9
here the way you find() is wrong
it should be either a callback or a exec() with async await.. this case just use callbacks
so instead of this code,
const user = User.find({'emailAddress': credentials.name, user.emailAddress} );
use this code
User.find({emailAddress:user.emailAddress},(err,user)={
if(err) throw err;
// do what you please
if (user) {
bcrypt.compare(password,hash,function(err,isMatch){
if(err) callback(err,null);
callback(null,isMatch);
});
} );
I've been struggling with this problem for a couple of days, I am able to create a user but I cannot save their email address under a users node.
register: function(user) {
return auth.$createUser({
email: user.email,
password: user.password
}).then(function(regUser) {
var ref = new Firebase(FIREBASE_URL+'users');
var userInfo = {
key : regUser.uid, // ex: simplelogin:29
date : Firebase.ServerValue.TIMESTAMP,
email : user.email,
}; // user info
ref.child(users).set(userInfo);
});
Here are a couple issues i see:
No specific shild node for each user. You are trying to save the userInfo directly in the users node instead of making a child node under users.
Firebase rules. Without knowing the rules you use i can't know for sure if this applies but can everyone write to that specific node or do you have to be logged in first?
Making the reference. Without knowing what FIREBASE_URL exactly is i can't tell if it's an isuue but if there isn't a / at the end doing + 'users' will give a wrong reference. I suggest using child as Frank also commented.
Resulting code would be something like this (don't forget to check your firebase rules):
register: function(user) {
return auth.$createUser({
email: user.email,
password: user.password
}, function(error) {
if (error) {
//catch possible errors
} else {
//no error, user has been created
//start with logging user in to have firebase write acces
auth.$authWithPassword({
email: user.email,
password: user.password
}, function(error, authData) {
if (error === null) {
//no error so log in succesfull
//Making the firebase reference
var ref = new Firebase(FIREBASE_URL).child("users");
//Get user id
var uid = authData.uid;
//Set data in firebase making a child using the user id
ref.child(uid).set({
key: regUser.uid, // ex: simplelogin:29
date: Firebase.ServerValue.TIMESTAMP,
email: user.email,
});
});
}
)};
}