I have the following Angular and Node JS as follows
Interceptor
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";
import { AuthService } from "../Services/auth.service";
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService : AuthService) {}
intercept(req: HttpRequest<any>, next: HttpHandler) {
//console.log(this.authService.getAuthToken())
const authToken = this.authService.getAuthToken();
const authRequest = req.clone({
headers: req.headers.set("Authorization", authToken)
});
console.log("authRequest");
return next.handle(authRequest);
}
}
service
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { api_url } from '../Models/global-url.model';
import { LoginModel } from '../Models/login_details.model';
import { ResponseFromServer } from '../Models/response.model';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private token : string;
//Password is asish for all users
constructor(private http: HttpClient) { }
checkUserLogin(loginDetails: LoginModel) {
console.log(loginDetails);
this.http.post<{response: any}>(api_url "login/loginUser", loginDetails).subscribe((result: ResponseFromServer) => {
console.log(result.token);
this.token = result.token;
console.log(this.token);
});
}
getAuthToken() {
return this.token;
}
}
User Defined Middleware in Node JS :-
const jwt = require('jsonwebtoken');
const s_token = require('../tokens/auth-token');
//const authFunction = (req, res, next) => {
module.exports = (req, res, next) => {
console.log(req);
var message = '';
try {
const token = req.headers.authorization;
console.log(token);
jwt.verify(token, s_token);
next();
} catch (err) {
message = "Auth Failed";
console.log(err); //JsonWebTokenError: Error jwt must be provided => user is not logged in
res.status(401).json(message);
// res.json(message); //Check the error message that occurs in browser console, while using this without status
}
}
login.js in Node Router :-
router.post('/loginUser', async (req, res, next) => {
const loginDetails = req.body;
console.log(loginDetails);
var { userId, stored_password,userEmailId,token,status_code } = '';
var message = '';
var response = '';
//console.log(loginDetails);
query = `SELECT * FROM tbl_users WHERE (tum_email = $1 OR tum_mobile = $1)`;
params = [loginDetails.username];
// await db.query(query, params, (err, result) => {
// if(err) {
// console.log(err);
// response = 'f0';
// message = "Internal Server Error. Please reload the page and try again.";
// } else if(result.rows.length) {
// //console.log(result.rows.length);
// userId = result.rows[0].tum_email;
// password = result.rows[0].tum_password;
// response = 's1';
// message = "";
// } else {
// response = 'f1';
// message = "User with the given user id does not exist. Please register here";
// }
// });
try {
const result = await db.query(query, params);
if(result.rowCount == 0 ) {
response = 'f1';
message = "User with the given user id does not exist. Please register here";
} else {
userId = result.rows[0].tum_id;
userEmailId = result.rows[0].tum_id;
stored_password = result.rows[0].tum_password;
try {
if ((await argon2.verify(stored_password, loginDetails.password))) {
//password matches
response = 'success';
const session_data = {
userId: userId,
email: userEmailId
}
token = jwt.sign(session_data, s_token, {expiresIn:'1hr'});
//console.log(token);
} else {
response = 'f2';
message = "Entered password is wrong. Please enter the correct password, or reset it";
}
} catch (err) {
console.log(err);
response = 'f0';
message = "Internal Server Error. Please reload the page and try again, or contact an Administrator";
}
}
} catch (err) {
console.log(err);
response = 'f0';
message = "Internal Server Error. Please reload the page and try again, or contact an Administrator";
}
const json_object = {
token: token,
response: response,
message:message
}
if(token != '') {
status_code = 200;
} else {
status_code = 401;
}
res.status(status_code).json(json_object);
//console.log("response =" response " & message = " message);
});
login.component.ts
import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
import { AuthData } from 'src/app/Models/auth_data.model';
import { LoginModel } from 'src/app/Models/login_details.model';
import { ResponseFromServer } from 'src/app/Models/response.model';
import { AuthService } from 'src/app/Services/auth.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
isSubmitted = false;
isValid = true;
isLoading = false;
response_from_server = new ResponseFromServer();
constructor(private authService: AuthService) {
}
ngOnInit(): void {
this.response_from_server.response = 's1';
}
loginUser(loginData: NgForm) {
this.isSubmitted = true;
if(loginData.invalid) {
this.isValid = false;
//console.log("Validation Errors");
return;
}
const loginDetails : LoginModel = {
username : loginData.value.username,
password: loginData.value.password
}
this.authService.checkUserLogin(loginDetails);
}
}
Whenever I try to login , the error TypeError: Cannot read properties of undefined (reading 'length') is thrown.
The data is not even sent to the server side. It is stuck before return next.handle(authRequest);.
I tried console.log() almost everywhere to see where I am getting the mistake, and to which part, the data movement is getting done. Looks like the email and password are not even going through, to the Node JS server. Using console.log(result.token) in login.service.ts does not have any value.
Where am I going wrong ?
CodePudding user response:
The problem is most likely happening because your trying to add the Authorization header before the user is logged-in.
In that situation authToken is undefined and you are assigning it to the header anyways.
You could solve it just adding a guard in your intercept method to first check if you have an authToken before attaching it to the request.
intercept(req: HttpRequest<any>, next: HttpHandler) {
const authToken = this.authService.getAuthToken();
if(!authToken) { // <--- not logged-in skip adding the header
return next.handle(req);
}
const authRequest = req.clone({
headers: req.headers.set("Authorization", authToken)
});
return next.handle(authRequest);
}
Cheers
