I have a login component which when a user logs in, the current User details is stored in a local Storage variable. So when login is successful will store the current User details in a local Storage Variable and navigate to dashboard, i have used the local Storage variable to get the user details and display in Header of webpage, but view is not changing once i refresh the page i will..
login() {
this.authenticationService.login(this.model.username,
this.model.password)
.subscribe(
data => {
this.activeModal.dismiss();
this.router.navigate(['dashboard']);
},
error => {
this.alertService.error(error);
});
}
In Service
login(username: string, password: string) {
return this.http.post('/api/authenticate', JSON.stringify({ username:
username, password: password }))
.map((response: Response) => {
// login successful if there's a jwt token in the response
let user = response.json();
if (user && user.token) {
// store user details and jwt token in local storage to keep
user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
});
}
getCurrentUser() {
return JSON.parse(localStorage.getItem('currentUser'));
}
In Navigation Component
constructor(private authenticationService: AuthenticationService) {
getUser() {
this.currentUser = this.authenticationService.getCurrentUser();
}
}
View
<li *ngIf="currentUser">Welcome {{currentUser.firstName}}
</li>
<li *ngIf="currentUser">Logout</li>
<li *ngIf="!currentUser">Login
</li>
<li *ngIf="!currentUser">Register</li>
Solution I found is to use DoCheck lifecycle hook.
ngDoCheck gets called to check the changes in the directives in addition to the default algorithm
ngDoCheck() {
this.getUser();
}
Related
I need to get the jwtToken from the Auth.signUp. Is this possible if i enable autoSignIn:{enabled:true}?
const signUp = async () => {
await Auth.signUp({
username: email,
password,
attributes: {
email, // optional
name,
},
autoSignIn:{
enabled: true
}
})
.then((data) => {
console.log(data.user); //user.signInUserSession is null
})
.catch((err) => {
if (err.message) {
setInvalidMessage(err.message);
}
console.log(err);
});
await Auth.currentAuthenticatedUser()
.then(user =>{
console.log(user)
})
.catch(error => {
console.log(error) //"User is not authenticated"
})
};
I call I want the jwttoken from the userSession data for conditional rendering and I store the token in my router.js. The response object from Auth.signUp contains a CognitoUser which has a signInUserSession value but its's null.
EDIT: Tried to call Auth.currentAuthenticatedUser() after but yields an error that user is not authenticated. But when i restart my app, the user will be authenticated. I still cant authenticate user on the same app "instance"
import { Auth, Hub } from 'aws-amplify';
const listener = (data) => {
switch (data.payload.event) {
case 'autoSignIn':
console.log('auto sign in successful');
console.log(data.payload) //returns user data including session and tokens.
//other logic with user data
break;
}
};
Above is the code to initalize the Hub listener provided by amplify api. Ater user presses sign up, I called to get user session data when user is automatically signed in.
Hub.listen('auth', listener)
I am new in Reactjs and I am working on "login" module, I integrated the login module successfully, and Now I want if the user enters the correct email and password then the email should be in session, And if the user is not logged in he can't see any further page, How can I do this? Here is my current code
const data = {
email: email,
password: password
};
axios.post("https://xxxxxxxxxxx/Checklogin/", data).then(function (response) {
if (response.data.msg == "wrong") {
$("#errormsg4").show("slow").delay(5000).fadeOut();
} else {
//"response.data.email"should be in session
}
});
To store the email in a session in React, as you specified, you can use the sessionStorage API. The sessionStorage API allows you to store key-value pairs in the user's browser. The data is stored in the session, which means it will only be available for the current tab and will be deleted when the user closes the tab.
Here is an example of how you can use the sessionStorage API to store the email in a session:
const data = {
email: email,
password: password
};
axios.post("https://xxxxxxxxxxx/Checklogin/", data).then(function (response) {
if (response.data.msg == "wrong") {
$("#errormsg4").show("slow").delay(5000).fadeOut();
} else {
// Store the email in the session
sessionStorage.setItem("email", response.data.email);
}
});
To check if the user is logged in, you can use the sessionStorage.getItem() method to retrieve the email from the session. If the getItem() method returns a non-null value, it means that the user is logged in and has an email stored in the session.
Here is an example of how you can use the sessionStorage.getItem() method to check if the user is logged in:
const email = sessionStorage.getItem("email");
if (email) {
// The user is logged in
} else {
// The user is not logged in
}
I hope this helps!
I am using firebase phone-authentication in my ionic 4 app. I have successfully implemented jwt authentication. If the token is available I redirect users to the main page else redirecting to the login page.
But here comes the problem on the login page. If the user is new(coming for the first time) then I want to redirect to the details page to get some other data like email, name, else (old user) redirect to the main page.
The problem is I don't have different buttons for login and signup in my app. The same login is used for both login and register
What is the best solution to check if the user is new or old? The last solution is to check the user in the database and redirect accordingly.
Here is my code
authentication.service.ts
authenticationState = new BehaviorSubject(false);
constructor(private storage: StorageService, private plt: Platform, private router: Router) {
this.plt.ready().then(() => {
this.checkToken();
});
}
checkToken() {
this.storage.get(TOKEN_KEY).then(res => {
if (res) {
this.authenticationState.next(true);
}
})
}
login() {
return this.storage.set(TOKEN_KEY, 'Bearer 1234567').then(() => {
this.authenticationState.next(true);
});
}
logout() {
return this.storage.clear().then(() => {
this.authenticationState.next(false);
this.router.navigate(['home'])
});
}
isAuthenticated() {
return this.authenticationState.value;
}
app.component.ts
constructor(private authenticationService: AuthenticationService){
this.authenticationService.authenticationState.subscribe(state => {
if (state) {
this.router.navigate(['menu/items']);
} else {
this.router.navigate(['home']);
}
});
}
home.page.ts
if(old user) {
// redirect to main page
}
else {
redirect to details page
}
I want to show the user name on the home page when he authenticates, so on the backend and at the login endpoint i put a user object in the json response (res.json) containing the name and email of the user thats going to be sent to the client side as a response to the login redux action that will get the user object from res.data and send it to the reducer that will save that user object to the redux state . When i login everything is working fine the data is displayed like i want but when i change any random thing about anything else and the page refresh when i save i get the error that the user data is not available
TypeError: Cannot read property 'name' of undefined" from user.name
so the user data is not saved in the state permanently.
I thought there where a problem with the mongodb but everything is fine
i got the mapstatetoprops like i should the proptypes and the connect method but my components dont have a constructor.
the backend code for sending the data
if (isMatch) {
// User matched
// Create JWT Payload
const payload = {
id: user.id,
name: user.first_name + " " + user.last_name
};
// Sign token
jwt.sign(
payload,
keys.secretOrKey,
{
expiresIn: 31556926 // 1 year in seconds
},
(err, token) => {
res.json({
success: true,
token: "Bearer " + token,
user: {
name: user.first_name + " " + user.last_name,
email: user.email
}
});
}
);
}
frontend :
render() {
const { user } = this.props.auth;
return (
<div style={{ height: "75vh" }} className="container valign-wrapper">
<div className="row">
<div className="col s12 center-align">
<h4>
<b>Hey there,</b> {user.name}
</h4>
</div>
</div>
</div>
);
}
}
WelcomeDashboard.propTypes = {
auth: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
auth: state.auth
});
export default connect(
mapStateToProps,
{ logoutUser }
)(WelcomeDashboard);
I expect the user data to always be available and don't get lost and undifined whenever i make changes and the page refreshes
TypeError: Cannot read property 'name' of undefined" when the page
refreshes from "{user.name}
but when i logout and login again i don't get the error only when i change some code
Because you are having rest-full API implementation, you cannot get any help from your backend. So it is not the issue with MongoDB.
When going through your questions I have a few suggestions to get rid of this issue.
You can save the current redux state into your browser local storage. Below code segment shows how to do it for your authReducer.
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
// your authReducer here
const authPersistConfig = {
key: 'auth',
storage: storage,
};
export default persistReducer(authPersistConfig, authReducer);
In the main component that shows after authentication (like dashboard or nav bar or the main App), you can fire another API call to validation your current JWT token and bring back the user details as you do in login request. (JWT token should be saved in local storage)
Those are a few options, you can choose one that you are very familiar with.
Hope this will help you.
I am working on login functionality for my Angular 2 app. I've got it working with a MockMackend and fakeBackendProvider. Now I'm in the process of connecting to our actual API. I am running into an issue with that, though.
First off, let me show what I have that IS working by using the MockBackend and fakeBackendProvider.
This is my authentication service function:
login(username: string, password: string) {
return this.http.post('/api/authenticate', JSON.stringify({ username: username, password: password}))
.map((response: Response) => {
// login successful if there's a jwt token in the response
const user = response.json();
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
});
}
Again, then, in my login component, I am calling that function like this:
login() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password)
.subscribe(
data => {
this.router.navigate(['/']);
console.log('User logged in as: ' + this.model.username);
},
error => {
this.alertService.error(error);
this.loading = false;
});
this.authenticationService.username = this.model.username;
}
Again, all of the above IS working.
So, I assume all I should need to do is replace '/api/authenticate' in the login function, with our actual api + api string. So this is what I've been trying:
login(username: string, password: string) {
return this.http.post('https://api.somesite.com&apikey=843c-4932-ckd33', JSON.stringify({ username: username, password: password}))
.map((response: Response) => {
// login successful if there's a jwt token in the response
const user = response.json();
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
});
}
This isn't working. In the console I get a "ERR_NAME_NOT_RESOLVED" error. Any ideas here?