I have created a login section using Vuex and Axios to authenticate the login by allowing the user to enter the email and password. I have created and stored the variables I need by using a getter. I have also, placed the tokens I needed into a function, post url and console.
But, know I need to show the responses according to the tokens being seen in the inspector/console.
What I need is to show the error messages when the user tries to login. So, when the console responds showing 200 (email and password is correct) I need it to store that token, when the console responds showing 400 (incorrect/missing characters in either email or password) I need it to print out the error messages that I have already placed with an array, lastly, when the console responds showing 401 (both email and password incorrect) I need it to print out the messageFour that is in the array.
HTML:
<template>
<form>
<div class="login">
<div>
<input type="text" v-model="email" placeholder="Email" class="eSection" id="email">
<p v-for="message in errorM" :key="message.errorM" v-show="message in errorM">
{{ message }}
</p>
<input type="password" v-model="password" placeholder="Password" class="pSection" id="password">
<p v-for="message in errorM" :key="message.errorM">
{{message}}
</p>
<button type="button" class="log" #click="login">LogIn</button>
</div>
</div>
</form>
</template>
Javascript:
<script>
import axios from 'axios';
export default {
data() {
return {
email: "test#gmail.com",
password: "123456",
flag: false,
errorM:[],
errorMessages: [
{
messageOne: "The email that has been entered is incorrect. Please try again!"
},
{
messageTwo: "Email/Password is missing. Please try again!"
},
{
messageThree: "The password that has been entered is incorrect. Please try again!"
},
{
messageFour: "Both Email and Password that have been entered are incorrect!"
},
]
}
},
methods: {
login: function (index) {
axios.post(`https://api.ticket.co/auth/login`, {
email: this.email,
password: this.password
})
.then(response => {
// JSON responses are automatically parsed.
console.log(response.data)
console.log(response.status)
})
.catch(e => {
console.log(e)
console.log(e.response.status)
var vueObject = this
switch (e.response.status) {
case 400:
if(!vueObject.email || !vueObject.password){
vueObject.errorM.push(vueObject.errorMessages.messageTwo)
};
if(!vueObject.email){
vueObject.errorM.push(vueObject.errorMessages.messageOne)
};
if(!vueObject.password){
vueObject.errorM.push(vueObject.errorMessages.messageThree)
};
break;
case 401:
if(vueObject.email && vueObject.password == ""){
vueObject.errorM.push(vueObject.errorMessages.messageFour)
}
break;
}
})
},
},
}
</script>
Many thanks!
It's not clear from the description what's not working, so I'll just point out some issues I see.
One thing to mention is, there is no evidence of you using vuex, no getters, no setters, no state.
Most notable is that you have the messages defined as an array of objects, which makes it difficult to look up
instead of this, which is harder to look up:
errorMessages: [
{
messageOne: "The email that has been entered is incorrect. Please try again!"
},
// etc... {}, {}, {}
]
... you should do
errorMessages: {
messageOne: "The email that has been entered is incorrect. Please try again!",
messageTwo: "Email/Password is missing. Please try again!",
messageThree: "The password that has been entered is incorrect. Please try again!",
messageFour: "Both Email and Password that have been entered are incorrect!",
}
so that you can find a message using this.errorMessages.messageTwo
Or better yet, define it outside of your vue component, since you're not using them in your template
const MESSAGE_INCORRECTEMAIL = "The email that has been entered is incorrect. Please try again!";
const MESSAGE_MISSINGFIELD = "Email/Password is missing. Please try again!";
const MESSAGE_INCORRECTPASSWORD = "The password that has been entered is incorrect. Please try again!";
const MESSAGE_INCORRECTEMAILPASSWORD = "Both Email and Password that have been entered are incorrect!";
and then just call them as MESSAGE_MISSINGFIELD from your script
From security standpoint, it's a bad idea to indicate whether the username or the password is wrong, as it makes hacking easier by confirming what usernames exist.
You can determine if the user had errors or fields are missing before sending the form for remote processing.
to do that, you would call
login: function (index) {
if (this.email.trim() === '' || vueObject.password.trim() === ''){
this.errorM.push(MESSAGE_MISSINGFIELD);
return // <- prevents further execution
}
// repeat for other local validations before remote request
// ... then process request
axios.post(`https://api.ticket.co/auth/login`, {
anyway, you might also need t break your question up into individual errors you encounter.
Related
I created a form to contact me on my website, for that I use EmailJS.
However when I try to send myself a mail through the contact form I got a 400 Error The service ID is invalid.
I followed every steps of that tutorial as I haven't use EmailJS before https://blog.mailtrap.io/react-send-email/
Here is my Contact component
class Contact extends React.Component {
constructor(props) {
super(props);
this.state = { feedback: '', name: 'Name', email: 'email#example.com' };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
render() {
return (
<form className="test-mailing">
<h1>Let's see if it works</h1>
<div>
<textarea
id="test-mailing"
name="test-mailing"
onChange={this.handleChange}
placeholder="Post some lorem ipsum here"
required
value={this.state.feedback}
style={{width: '100%', height: '150px'}}
/>
</div>
<input type="button" value="Submit" className="btn btn--submit" onClick={this.handleSubmit} />
</form>
)
}
handleChange(event) {
this.setState({feedback: event.target.value})
}
handleSubmit() {
const templateId = 'template_id';
this.sendFeedback(templateId, {message_html: this.state.feedback, from_name: this.state.name, reply_to: this.state.email})
}
sendFeedback (templateId, variables) {
window.emailjs.send(
'gmail', templateId,
variables
).then(res => {
console.log('Email successfully sent!')
})
// Handle errors here however you like, or use a React error boundary
.catch(err => console.error('Oh well, you failed. Here some thoughts on the error that occured:', err))
}
}
And here is what I added in my index.html
`<script type="text/javascript"
src="https://cdn.jsdelivr.net/npm/emailjs-com#2.3.2/dist/email.min.js"></script>
<script type="text/javascript">
(function(){
emailjs.init("my_user_ID_here"); // Obtain your user ID at the dashboard https://dashboard.emailjs.com/integration
})();
`
To fix this, I had to swap out 'gmail' with my service ID.
sendFeedback (templateId, variables) {
window.emailjs.send(
***serviceID here***, templateId,
variables
).then(res => {
console.log('Email successfully sent!')
})
// Handle errors here however you like, or use a React error boundary
.catch(err => console.error('Oh well, you failed. Here some thoughts on the error that occured:', err))
}
The JavaScript console in my web browser helped identify this.
That was happening to me, and it was because I didn't have the account activated.
when you log in, click on 'email services' and select, for example, gmail with your account
pd: google translate
Had the same problem.
To fix it,
I had to paste NOT the 'gmail' string itself but the service_id which
is below the icon gmail
in the EmailJS website after log in. Everyone has its own specific number. Also the template_id is important to put the id generated for your template.
When you want to publish your project it is advisable to place your special ids to the .env file to stay secure.
Please try to check whether you are using the right integration id, check the id token you are using with the one under integration id on the dashboard, this was my issue
Might as well share a quick fix that would probably save someone's time. I just had the same issue while using the code below.
const notifyOwnerOfGuest = async () => {
const userId = 'user_...';
const serviceId = 'service_...';
const templateId = 'template_...';
const accessToken = 'e2e1...';
const postfields = {
user_id: userId,
service_id: serviceId,
template_id: templateId,
accessToken,
};
const response = await fetch('https://api.emailjs.com/api/v1.0/email/send', {
method: 'POST',
body: JSON.stringify(postfields),
// should explicitly add the header content-type here
});
if (!response.ok) throw await response.text();
};
I just explicitly added a Content-type header like so
headers: {
'Content-Type': 'application/json',
},
and now it works.
I'm trying to store the access token into the createStore (index.js) and then redirect the user to go to another webpage once they login.
For this I need to create a mutation within mutations.js so that I can set the access token and set the refresh token. The refresh should be like a time stamp.
The test.vue is where the login code is to validate the user.
So, basically I need to create a function, set the access token, set the refrefresh token and then redirect the user to another webpage once they pressh the login button.
Many thanks in advance!
index.js:
import vuex from 'vuex';
import mutations from './mutations';
const createStore = () =>{
return new vuex.Store({
state: {
accessToken: "halo",
access_token: response.data.access_token,
refresh: response.data.refresh_token
},
getters:{
accessToken(state, getters){
return state.accessToken;
}
},
mutations
});
};
export default createStore;
mutations.js:
const mutations = {
setToken(state, token) {
state.accessToken = token;
}
}
export default mutations;
test.vue:
<template>
<form>
<div class="login">
<div>
<input name="email" type="text" v-model="email" v-validate="'required'" placeholder="Email" class="eSection" id="email">
<p v-show="wrong.email">
Email is missing or incorrect. Please try again!
</p>
<i name="emailFormat" type="text" v-validate="'required|emailFormat'" placeholder="Email" class="eSection" id="email"></i>
<p v-show="wrong.emailFormat">
Not valid email!
</p>
<input name="password" type="password" v-model="password" v-validate="'required'" placeholder="Password" class="pSection"
id="password">
<p v-show="wrong.password">
Password is missing or incorrect. Please try again!
</p>
<p v-show="wrong.all">
Login Details Incorrect!
</p>
<button type="button" class="log" #click="login">LogIn</button>
</div>
</div>
</form>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
email: "test#gmail.com",
password: "123456",
flag: false,
wrong: {
email: false,
emailFormat: false,
password: false,
all: false
},
}
},
methods: {
login: function (index) {
this.wrong.email = false;
this.wrong.password = false;
this.wrong.all = false;
this.wrong.emailFormat = false;
axios.post(`https://api.ticket.co/auth/login`, {
email: this.email,
password: this.password
})
.then(response => {
// JSON responses are automatically parsed.
console.log(response.data)
console.log(response.status)
})
.catch(e => {
console.log(e)
console.log(e.response.status)
var vueObject = this
switch (e.response.status) {
case 400:
if (!vueObject.email) {
console.log(1)
this.wrong.email = true;
} else if (!vueObject.emailFormat) {
console.log(2)
this.wrong.emailFormat = true;
};
if (!vueObject.password) {
console.log(3)
this.wrong.password = true;
}
break;
case 401:
console.log(4)
this.wrong.all = true;
break;
}
})
},
},
}
</script>
I think there are two possible solution for this problem.
First: you can use vue-router. In that case, there will be no
page refresh, just component change. That way untill you refresh
the page, every vuex state will live. (But its not the best
solution).
Second; You can write a rest call, what is give you back the actual
user token, if the user authenticated. So only this rest api call use
session authentication and / or CSRF token (check wiki if you
don't know it). One of the most elegant way if you use axios
interceptor (run before every axios call), what will get the token if
the user is authenticated. Check this github comment for futher
information. (Make sure, that session timeout is longer then token
lifetime :) )
I am trying to create a simple login system on my website which does not require any registration process. I will be setting the username and password for each client to use.
Basically, the idea is to have a login page that allows clients to access and view files and information (instead of using email).
The problem with the code below is that the 'username' and 'password' are hardcoded i.e easily viewed with the 'inspect element' feature.
Since I am a newbie, I was wondering if I can create a simple secure system without making use of database and php.
HTML:
<form name="login" class="form">
<p class="title">Client Dashboard</p>
<p class="login-description">This dashboard allows you to manage your project and files</p>
<input type="text" name="userid" placeholder="Username" class="text-field"/>
<input type="password" name="pswrd" placeholder="Password" class="text-field"/>
<input type="submit" class="button" onclick="check(this.form)" value="Login"/>
</form>
Javascript:
function check(form) { /*function to check userid & password*/
/*the following code checkes whether the entered userid and password are matching*/
if(form.userid.value == "johnsmith" && form.pswrd.value == "password123") {
window.open('dashboard.html')/*opens the target page while Id & password matches*/
}
else {
alert("Error Password or Username")/*displays error message*/
}
}
Although this is dangerous for client side code to have login credentials, you can store user info in Array of objects then check if the array has those values.
var users = [{
username: 'admin',
password: 'abc123'
},{
username: 'user1',
password: '321cba'
}];
var index = users.indexof(function (user) {
return users.username === user.username &&
users.password === user.password;
})
if (index !== -1) {
window.open('dashboard.html')/*opens the target page while Id & password matches*/
}
else {
alert("Error Password or Username"
)/*displays error message*/
I am attempting to create a login and a register page using ReactJS + Redux. Currently once a user registers, the user's object with the registered info are stored inside an array:
const userDataReducer = function(users = [], action){
switch (action.type){
case 'ADD_USER':
return[{
username: action.username,
email: action.email,
name: action.name,
password: action.password
}, ...users]
and once it is registered, the user enters the username and password in the login form and submits it:
verifyLoginUser(){
event.preventDefault()
if(this.props.actions.verifyUser(this.props.loginUser.username, this.props.loginUser.password)){
console.log('LOGGED IN')
} else {
console.log('NOT LOGGED IN')
}
}
and inside userDataReducer.js verifies with the following:
case 'VERIFY_USER':
let isVerified = false;
users.forEach((user)=> {
if(user.username === action.username && user.password === action.password){
isVerified = true;
return false;
}
});
return isVerified;
The actions are:
addUser: function(username, email, name, password) {
return {
type: 'ADD_USER',
username: username,
email: email,
name: name,
password: password
}
},
verifyUser: function(username, password){
return {
type: 'VERIFY_USER',
username: username,
password: password
}
}
Currently, if a user tries to login and click submit, it just continues to return 'LOGGED IN' in any cases.
In ReactJS + Redux, is this the correct way to go about creating Login and Register pages just via front-end? Any guidance or insight would be greatly appreciated. Thank you in advance.
"Login and register just via front-end" probably goes against everything in the book, so if you are looking for implementing good practices, that might be a good place to start - https://www.quora.com/Is-it-possible-to-do-client-side-only-javascript-authentication
Regarding React and Redux, your code looks good. I would just point out 2 things about your actions:
It is a good practice for actions to contain a payload property - https://github.com/acdlite/flux-standard-action
VERIFY_USER is only reading data, not storing. So you don't actually need an action there, nor does the code need to live in a reducer. That code should probably be a method of your authentication component.
I have a user profile view where users can edit their profile information. Everything below works great and the update is successful. However, when I logout of the account and login with a different user account, the update fails and returns an Access denied error. It isn't until I refresh the page that I can edit the profile information again with the second account.
I know this case is very rare and a user would not normally be logging out of one account, logging in with another and trying to update their profile but I would like to better understand why this is happening. Is the client token not flushed when a user logs out or is there something else that's being preserved that requires a complete reload of the page?
On client JS:
Template.user_profile_form.events({
'click #submit_profile_btn': function(evt) {
evt.preventDefault();
var first_name = $('#profile_first_name').val()
,last_name = $('#profile_last_name').val()
,email = $('#profile_email').val()
,email_lower_case = email.toLowerCase()
,gravatar_hash = CryptoJS.MD5(email_lower_case)
;
gravatar_hash = gravatar_hash.toString(CryptoJS.enc.Hex);
// TODO need to create user sessions so that when you log out and log back in, you have a fresh session
Meteor.users.update({_id: this.userId }, {
$set: {
profile: {
first_name: first_name,
last_name: last_name,
gravatar_hash: gravatar_hash
}
}
}, function(error) {
if (!error) {
Session.set('profile_edit', 'success');
Meteor.setTimeout(function() {
Session.set('profile_edit', null);
}, 3000);
} else {
Session.set('profile_edit', 'error');
Template.user_profile_form.error_message = function() {
return error.reason;
};
}
});
Meteor.call('changeEmail', email);
}
});
The server JS:
Meteor.publish('list-all-users', function () {
return Meteor.users.find({_id: this.userId }, {
fields: {
profile: 1,
emails: 1
}
});
});
Meteor.methods({
sendEmail: function(to, from, subject, text) {
this.unblock();
Email.send({
to: to,
from: from,
subject: subject,
text: text
});
},
changeEmail: function(newEmail) {
// TODO Need to validate that new e-mail does not already exist
Meteor.users.update(Meteor.userId(), {
$set: {
emails: [{
address: newEmail,
verified: false
}]
}
});
}
});
The template:
<template name="user_profile_form">
<h2>Update Profile</h2>
<div id="profile-form">
{{#if success}}
<div class="alert alert-success">
<strong>Profile updated!</strong> Your profile has been successfully updated.
</div>
{{/if}}
{{#if error}}
<div class="alert alert-error">
<strong>Uh oh!</strong> Something went wrong and your profile was not updated. {{error_message}}.
</div>
{{/if}}
<p>
{{#each profile}}
<input type="text" id="profile_first_name" placeholder="First Name" value="{{first_name}}">
<input type="text" id="profile_last_name" placeholder="Last Name" value="{{last_name}}">
{{/each}}
<input type="email" id="profile_email" placeholder="Email" value="{{email_address}}">
</p>
</div>
<div id="submit-btn">
<input type="submit" id="submit_profile_btn" class="btn btn-primary">
</div>
</template>
The Meteor logout function does almost nothing. It certainly does not tear down Session state or the rest of your app's context. Your code must reset these variables during your app's logout event. A manual refresh of the page causes the client side JavaScript to reload wiping out existing Session data.
If you don't want to mess with the accounts-ui template internals you can use the following pattern (CoffeeScript code) to clear individual variables from the Session:
Deps.autorun (c) ->
user = Meteor.user()
if user
# Setup code on login (if required)
else if not user
# Clear session on logout
Session.set "profile_edit", undefined