Angular2 and Web API session control - html

i'm doing a login service. But i'm only capable of doing login, but i want to make a session to control the login's.
Where is my login.component.ts:
#Component({
selector: 'login',
templateUrl: './app/login/login.component.html'
})
export class LoginComponent implements OnInit {
model: any = {};
loading = false;
returnUrl: string;
constructor(
private route: ActivatedRoute,
private router: Router,
private utilizadorService: UtilizadoresService,
private alertService: AlertService) { }
ngOnInit() {
// reset login status
this.utilizadorService.logout();
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
}
login() {
console.log("Login! ");
this.loading = true;
this.utilizadorService.login(this.model.email, this.model.password).subscribe(
data => {
this.alertService.success('Login successful', true);
this.router.navigate(['/profile']);
},
error => {
this.alertService.error(error._body);
this.loading = false;
});
}
}
and there is my utilizadores.serice.ts, where is the login/register function:
#Injectable()
export class UtilizadoresService {
constructor(private _http: Http) {}
private RegenerateData = new Subject<number>();
// Observable string streams
RegenerateData$ = this.RegenerateData.asObservable();
AnnounceChange(mission: number) {
this.RegenerateData.next(mission);
}
LoadData(): Promise<IUtilizadores[]> {
return this._http.get('/api/utilizadores')
.toPromise()
.then(response => this.extractArray(response))
.catch(this.handleErrorPromise);
}
Add(model: IUtilizadores) {
let headers = new Headers({
'Content-Type':
'application/json; charset=utf-8'
});
let options = new RequestOptions({ headers: headers });
delete model["id"];
let body = JSON.stringify(model);
return this._http.post('/api/utilizadores/', body, options).toPromise().catch(this.handleErrorPromise);
}
Update(model: IUtilizadores) {
let headers = new Headers({
'Content-Type':
'application/json; charset=utf-8'
});
let options = new RequestOptions({ headers: headers });
let body = JSON.stringify(model);
return this._http.put('/api/utilizadores/', body, options).toPromise().catch(this.handleErrorPromise);
}
Delete(id: number) {
return this._http.delete('/api/utilizadores/?id=' + id).toPromise().catch(this.handleErrorPromise);
}
login(email: string, password: string) {
return this._http.post('/api/utilizadores/login', { email: email, password: password })
.map((response: Response) => {
let utilizador = response.json();
if (utilizador) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(utilizador));
}
});
}
logout() {
// remove user from local storage to log user out
// localStorage.removeItem('id_token');
localStorage.removeItem('currentUser');
}
public authenticated() {
// Check if there's an unexpired JWT
// This searches for an item in localStorage with key == 'id_token'
return tokenNotExpired();
}
protected extractArray(res: Response, showprogress: boolean = true) {
let data = res.json();
return data || [];
}
protected handleErrorPromise(error: any): Promise<void> {
try {
error = JSON.parse(error._body);
} catch (e) {
}
let errMsg = error.errorMessage
? error.errorMessage
: error.message
? error.message
: error._body
? error._body
: error.status
? `${error.status} - ${error.statusText}`
: 'unknown server error';
console.error(errMsg);
return Promise.reject(errMsg);
}
}
export interface IUtilizadores {
id: number,
email: string,
nickname: string,
password: string
}
I'm doing this for a school project, so i dont want to work with Auth0, and i'm using VS 2015 and microsoft SQL server

Related

JWT token removed from header on reload. How to fix it?

I'm trying to setup a Vue2js app with node.js/express, using JWT authentication.
When signing in token is generated (with bearer) and stored in the client-side (Vuex) successfully.
When reload token somehow dissapers from header and I don't know why?
So when calling fetchAccountFromToken function from helpers/token.js I have below error on the server side:
"TypeError: Cannot read property 'split' of undefined"
helpers/token.js
export function fetchAccountFromToken(token) {
return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString('utf-8'))['user']
}
And I have this code in server.js
app.post('/login', async (req, res) => {
if (req.body == null) {
res.status(401).json({ error: 'Invalid login. Please try again' })
} else {
const userService = new UserService()
const token = await userService.loginUser({
email: req.body.email,
password: req.body.password
})
console.log(token)
if (token) {
res.json({ token })
} else {
res.status(401).json({ error: 'Invalid login. Please try again' })
}
}
})
UserService.js
export default class UserService {
async loginUser(loginUserRequest) {
const { email, password } = loginUserRequest
const userRepository = new UserRepository()
const userDto = await userRepository.getUserByEmail(email)
if (userDto.email === email && userDto.password === password) {
let user = {
id: userDto.id,
email: userDto.email,
firstName: userDto.firstName,
lastName: userDto.lastName,
role: userDto.role
}
return jwt.sign({ user }, 'the_secret_key') //secret key je za validacijo tokena
}
return null
// return res.status(401).json({ error: 'Invalid login. Please try again.'}) // NEEDS to send error if credentials don't match !!!! //
}
UserRepository.js
export default class UserRepository {
async getUserByEmail(email) {
let dbContext = new DbContext()
try {
const query = 'SELECT id, email, password, firstName, lastName, role FROM accounts WHERE email = ?'
const users = await dbContext.query(query, [email])
return users[0]
} finally {
dbContext.close()
}
}
And I have this code in the VueX store module user.js:
export const state = {
user: null
}
export const mutations = {
SET_USER_DATA(state, data) {
console.log('logging in with data data:', data)
let { token } = data
localStorage.setItem('token', token)
let tokenPayloadJson = atob(token.split('.')[1])
let tokenPayload = JSON.parse(tokenPayloadJson)
let user = tokenPayload.user
state.user = user
localStorage.setItem('user', JSON.stringify(user))
console.log('called set user data')
axios.defaults.headers.common['Authorization'] = `Bearer ${data.token}`
},
CLEAR_USER_DATA() {
localStorage.removeItem('token')
localStorage.removeItem('user')
location.reload()
}
}
export const actions = {
login({ commit }, credentials) {
return axios
.post('//localhost:3000/login', credentials)
.then(({ data }) => {
commit('SET_USER_DATA', data)
})
},
fetchUser(id) {
return AccountService.getUser(id)
.then(response => {
return response.data
})
},
logout({ commit }) {
commit('CLEAR_USER_DATA')
}
}
export const getters = {
loggedIn(state) {
return !!state.user
}
}
I don't see storing the token to VueX, just saving it to localStorage. Additionally I don't see how you are reading it from it (neither localStorage nor VueX store). You can load it from localStorage when initializing the store like this:
export const state = {
user: localStorage.getItem('user'),
token: localStorage.getItem('token')
}

how can I do login form for angular?

I am trying to create a login form for my website. I'm using agular , express and mongoDB
Here's my controller of login function:
loginUser: (req, res) => {
User.findOne({
username: req.body.login_username
})
.then(user => {
bcrypt.compare(req.body.login_password, user.password)
.then(result => {
if (result) {
req.body.login_username = user.username
res.json({
message: "Success!",
added: true
});
} else {
console.log('Failed login attempt')
res.json({
message: "Error!",
error: err
});
}
}).catch(console.error, console.log(req.body.login_password, user.password))
})
}
and here is my login components:
userID: string;
userData: any;
loginUser: any;
error = "";
constructor(
private router: Router,
private route: ActivatedRoute,
private httpService: HttpService
) {}
ngOnInit() {
this.userID = this.route.snapshot.paramMap.get("id");
this.getSingleUser();
this.loginUser = { username: "", password: "" };
}
getSingleUser() {
let observable = this.httpService.getOneUser(this.userID);
observable.subscribe((data) => {
this.userData = data;
});
}
onSubmit() {
let observable = this.httpService.loginUser(this.loginUser);
observable.subscribe((data: any) => {
console.log("Wrong");
if (data.error) {
this.error = data.error.errors.name.message;
} else {
this.getSingleUser();
this.router.navigate([""]);
}
});
}
When I click on button my terminal getting an error like this:
undefined $2b$20$8DmOjsDm3h5q/jEq9lNauezUdFYdL6EBt9gjmCu8/0DU0kAnSSIA2
Error: data and hash arguments required
at Object.compare (/Users/nhannguyen/Desktop/personal_project/instagram/node_modules/bcrypt/bcrypt.js:208:17)
at /Users/nhannguyen/Desktop/personal_project/instagram/node_modules/bcrypt/promises.js:29:12
at new Promise ()
at Object.module.exports.promise (/Users/nhannguyen/Desktop/personal_project/instagram/node_modules/bcrypt/promises.js:20:12)
at Object.compare (/Users/nhannguyen/Desktop/personal_project/instagram/node_modules/bcrypt/bcrypt.js:204:25)
at /Users/nhannguyen/Desktop/personal_project/instagram/server/controllers/users.js:65:24
at processTicksAndRejections (internal/process/task_queues.js:97:5)
Please add .catch(console.error) after the .then() to catch the full error.
After that check if the values are really there and if not, check if the body-parser plugin is installed

Angular2 Authentication : there's something wrong with POST request?

Hi I am trying to authenticate users and once the server gives user's information, I want to use the information of the user.
But for some reasons, even though I did the log in process without any error and I can see from developer's tool that the POST request has been successful, I can't quite set currentUser in my localStorage (giving me null if I console.log it)
What am I doing wrong?
This is my authentication service.
export class AuthenticationService {
constructor(private http: Http, private router: Router) { }
login(email: string, password: string): Observable<User>{
const headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
headers.append('Access-Control-Allow-Headers', 'Content-Type');
headers.append('Access-Control-Allow-Methods', 'post');
headers.append('Access-Control-Allow-Origin', '*');
headers.append("X-Requested-With", "XMLHttpRequest");
let options = new RequestOptions({ headers: headers });
let body = new URLSearchParams();
body.set('email', email);
body.set('password', password);
return this.http.post(`${environment.baseurl}` + '/api/v2/member/login', body, options)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let user = res.json();
if (user && user.token) {
localStorage.setItem('currentUser', JSON.stringify(user));
}
return user.data || {};
}
logout() {
// remove user from local storage to log user out
localStorage.removeItem('currentUser');
}
private handleError(error: any) {
if (error.status === 401) {
return Observable.throw(error.status);
} else {
return Observable.throw(error.status || 'Server error');
}
}
}
And this is my log-in component
export class LoginPageComponent implements OnInit {
constructor(private location: Location,
private route: ActivatedRoute,
private router: Router,
private authenticationService: AuthenticationService,
private alertService: AlertService) {
}
model: any = {};
loading = false;
returnUrl: string;
error = '';
ngOnInit() {
// get return url from route parameters or default to '/'
this.returnUrl = this.route.snapshot.queryParams['main'] || '/';
}
currentUser: User;
login() {
this.loading = true;
this.authenticationService.login(this.model.email, this.model.password)
.subscribe(
data => {
this.currentUser = data;
this.router.navigate([this.returnUrl]);
},
error => {
this.error = "Wrong ID or PW";
this.loading = false;
});
}
backClicked() {
this.location.back();
}
}
And this is my home component
export class MainComponent {
onClick() {
this.auth.logout() //if user clicks logout button
}
currentUser: User;
users: User[] = [];
items: Object[] = [];
constructor(private authguard: AuthGuard, private auth:AuthenticationService) {
this.currentUser = JSON.parse(localStorage.getItem('currentUser'));
console.log(localStorage.getItem('currentUser')); //Printing null
}
}
And the model for user information is this.
export interface User {
birthday: number;
email:string;
genderType:string;
memberType: string;
name: string;
phone: string;
}
What im receiving
Why is it printing null?
Thank you!
Mistakes you made
passing email and password as URLSearchParams.
You are adding all the headers to your login method which is not necessary
The service should contain method as below
login(body: any, options?: RequestOptionsArgs): Observable<Response> {
return this.http.post('loginUrl', body);
}
Component should contain the below code
login() {
let user ={
email : this.model.email
password : this.model.password)
}
this.loading = true;
this.authenticationService.login(user)
.subscribe(data => {
this.authenticationService.extractData(data);///call to store token in the localstorage
this.router.navigate([this.returnUrl]);
},
error => {
this.error = "Wrong ID or PW";
this.loading = false;
});
}

Nativescript application-settings to persist a JSON value

I'm new to nativescript and angular 2 development. Currently, in the application that i'm building, HTTP post returns a JSON object like
[
{
"firstname": "test",
"isauth": true,
"lastname": "client",
"roleid": 10,
"rolename": "",
"userid": 3507,
"username": ""
}
]
I'm required to somehow save the userid (returned by Backendservice.apiUrl) value from the above response in login.component.ts and use that to pass to another API (Backendservice.requesturl ) that I'll be calling from another component(invoked clientmaster.component.ts). How do I do this on {N} + angular2.
Can I use applicationsettings setstring to persist the userid value and use it when I make the next call?If that's possible how do I parse the JSON response from the observable and save the userid value ?
I know that I can use flatmap to make chained http requests. But I'm not quite sure about how to do it and i'm very new to angular 2 development and RxJs observable concepts.
Here's my code:
login.service.ts
login(user: User) {
let headers = new Headers();
//In the headers object, the Content-Type specifies that the body represents JSON.
headers.append("Content-Type", "application/json");
let urlSearchParams = new URLSearchParams();
urlSearchParams.append('username', user.username);
urlSearchParams.append('pwd', user.password);
let body = urlSearchParams.toString();
console.log("body"+body);
return this.http.post(
BackendService.apiUrl,
body,
{headers: headers })
.map((response ) => {
response.json();
// login successful if there's a jwt token in the response
console.log("RESPONSE: "+response.url);
console.log("response json "+response.status);
var body = response.json();
console.log("JSON BODY: ",JSON.stringify(body));
}
)
.catch(this.handleErrors);
}
getAssociatedRequest(){
let headers = new Headers();
//call made to the next URL
return this.http.get(
BackendService.requestUrl
)
.map((response: Response) => {
// login successful if there's a jwt token in the response
console.log("RESPONSE: ",response);
var body = response.json();
console.log("JSON BODY: ",JSON.stringify(body));
alert(JSON.stringify(body));}
)
.catch(this.handleErrors);
}
logoff() {
BackendService.token = "";
}
handleErrors(error: Response) {
console.log(JSON.stringify(error.json()));
return Observable.throw(error);
}
}
login.component.ts
import { Component, ElementRef, OnInit, ViewChild } from "#angular/core";
.....
.....
#Component({
selector: "vp-login",
moduleId: module.id,
providers: [LoginService],
templateUrl: "./login.component.html",
styleUrls: ["./login.component.css", "./login.css"],
})
export class LoginComponent implements OnInit {
user: User;
isAuthenticating = false;
constructor(private router: Router,
private loginService : LoginService,
private page: Page) {
this.user = new User();
}
ngOnInit() {
this.page.actionBarHidden = true;
}
login() {
if (getConnectionType() === connectionType.none) {
alert("Vessel-Pro requires an internet connection to log in.");
return;
}
try {
this.loginService.login(this.user)
.subscribe(
() => {
this.isAuthenticating = false;
this.router.navigate(["/clientMaster"]);
},
(error) => {
alert("Unfortunately we could not find your account.");
this.isAuthenticating = false;
}
);
} catch (error) {
console.log(error.message);
}
}
}
clientmaster.component.ts
import { Component, ElementRef, OnInit, ViewChild } from "#angular/core";
import { alert, LoginService, User } from "../shared";
...
#Component({
selector: "clientMaster",
moduleId: module.id,
templateUrl: './clientmaster.component.html',
styleUrls: ["./clientmaster.component.css"],
providers: [LoginService]
})
export class ClientMasterComponent implements OnInit{
isLoading = false;
constructor(private router: Router,
private LoginService: LoginService,
private page: Page) {}
ngOnInit(){
this.page.actionBarHidden = true;
}
/**
* gotoSRTPage
*/
public gotoSRTPage() {
this.router.navigate(["srtDetails"])
}
loadsrt(){
// alert("OK");
if (getConnectionType() === connectionType.none) {
alert("Oops!! looks like your device is not connected to the internet ");
return;
}
this.LoginService.getAssociatedRequest()
.subscribe(
(response) => {
console.log("Success Response" + response)
},
(error) => { console.log("Error happened", error.message)},
() => { console.log("srt is completed")
}
);

Angular 2:Not able to get a token in another component which is stored in local storege

I have one application which include login and home component,
login.service.ts
let body = JSON.stringify(data);
console.log("logged in user",body);
return this._http.post('http://localhost:8080/api/user/authenticate', body, { headers: contentHeaders })
.map(res => res.json())
.map((res) => {
var token1:any = res;
console.log(token1);
if (token1.success) {
localStorage.setItem('auth_token', token1.token);
this.LoggedIn = true;
}
return res.success;
});
}
isLoggedIn() {
return this.LoggedIn;
}
in this service i am getting token in variable token1 and isLogged method contain
constructor(private _http: Http) {
this.LoggedIn = !!localStorage.getItem('auth_token'); }
Login.component.ts
login(event, username, password)
{
this.loginService.login(username, password)
.subscribe(
response => {
this.router.navigate(['/home']);
alert("login successfull");
},
error => {
alert(error.text());
console.log(error.text());
}
);
From this login i can able to authenticate and and its routing to home component,
Home.serice.ts
getClientList()
{
let headers = new Headers();
headers.append('Content-Type', 'application/json');
let authToken = localStorage.getItem('auth_token');
headers.append('X-auth-Token', 'authToken')
return this._http.get('http://localhost:8080/api/v1/client/list?isClient=Y', {headers})
.map(res => res.json())
}
Home.component.ts
onTestGet()
{
this._httpService.getClientList()
.subscribe(
data => this.getData = JSON.stringify(data),
error => alert(error),
() => console.log("finished")
);
}
now question is how can i access that token in home component which is in token1 varible(login) i have tired to getitem token.but i am getting token null.please anybody help me.
thanks in advance
localStorage.getItem('auth_token')
This should work, but you are getting null, because lifecycle of the data different.
I suggest you to use Subject construction for this purpose, especially you already have service with data.
Example:
loginInfo$ = new Subject();
private _logininfo = null;
getLoginData () {
if(!_logininfo) {
this.http..... { this._loginInfo = data;
this.loginInfo$.next(data); }
return this.loginInfo$.first()
}
else return Observable.of(this._logininfo);
}
So now, your service at the same time storage of data and handler for missing login.