Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions backend/src/api/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ router.post('/login', async (req, res) => {
}

const user = userToToken(foundUser);
const token = sign(user, getJWTSecret(), { expiresIn: '2h' });
const token = sign(user, getJWTSecret(), { expiresIn: '4h' });
const expiresAt = addHours(2);

res.status(200).send({ token, user, expiresAt });
Expand All @@ -53,7 +53,7 @@ router.post('/register', async (req, res) => {
const savedUser = await dalUser.create(body);

const user = userToToken(savedUser);
const token = sign(user, getJWTSecret(), { expiresIn: '2h' });
const token = sign(user, getJWTSecret(), { expiresIn: '4h' });
const expiresAt = addHours(2);

res.status(200).send({ token, user, expiresAt });
Expand Down
24 changes: 18 additions & 6 deletions backend/src/utils/auth.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { NextFunction, Request, Response } from 'express';
import { sign, verify } from 'jsonwebtoken';
import { Role, UserModel } from '../models/User';
import { UserModel, Role } from '../models/User';
import { v4 as uuidv4 } from 'uuid';
import hmacSHA256 from 'crypto-js/hmac-sha256';
import dalUser from '../repository/dalUser';
Expand All @@ -11,6 +10,7 @@ import { ProjectModel } from '../models/Project';
import { NotFoundError } from '../errors/client.errors';
import { addUserToProject } from './project.helpers';
import { ApplicationError } from '../errors/base.errors';
import { sign, verify, TokenExpiredError, JsonWebTokenError } from 'jsonwebtoken';

export interface Token {
email: string;
Expand Down Expand Up @@ -50,15 +50,27 @@ export const isAuthenticated = async (
) => {
try {
if (!req.headers.authorization) {
return res.status(400).end('No authorization header found!');
return res.status(401).json({ message: 'Authorization header is missing' });
}

const token = req.headers.authorization.replace('Bearer ', '');

if (!token) {
return res.status(401).json({ message: 'Bearer token not found' });

}
res.locals.user = verify(token, getJWTSecret()) as Token;

next();
} catch (e) {
return res.status(403).end('Unable to authenticate!');
} catch (error) {
if (error instanceof TokenExpiredError) {
return res.status(401).json({ message: 'Token expired' });
} else if (error instanceof JsonWebTokenError) {
return res.status(401).json({ message: 'Invalid token' });
} else {
console.error('Error in isAuthenticated middleware:', error);
return res.status(500).json({ message: 'Internal server error' });
}
}
};

Expand Down Expand Up @@ -224,7 +236,7 @@ export const signInUserWithSso = async (

export const generateSessionToken = (userModel: UserModel): any => {
const user = userToToken(userModel);
const token = sign(user, getJWTSecret(), { expiresIn: '2h' });
const token = sign(user, getJWTSecret(), { expiresIn: '4h' });
const expiresAt = addHours(2);
return { token, user, expiresAt };
};
24 changes: 18 additions & 6 deletions frontend/src/app/utils/interceptor.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpResponse,
HttpErrorResponse,
} from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { tap, timeout } from 'rxjs/operators';
import { Observable, of, throwError } from 'rxjs';
import { catchError, tap, timeout } from 'rxjs/operators';
import { UserService } from '../services/user.service';
import { environment } from 'src/environments/environment';
import { Router } from '@angular/router';

export const DEFAULT_TIMEOUT = 30000;

@Injectable()
export class APIInterceptor implements HttpInterceptor {
private cache: Map<string, HttpResponse<any>>;

constructor(public auth: UserService) {
constructor(public auth: UserService, private router: Router) {
this.cache = new Map();
}

Expand Down Expand Up @@ -52,10 +54,20 @@ export class APIInterceptor implements HttpInterceptor {
this.cache.set(apiReq.urlWithParams, httpEvent.clone());
}
})
)
.pipe(
catchError((error: HttpErrorResponse) => {
if (error.status === 401) {
// Token expired or invalid, clear user data and navigate to login
this.auth.logout();
this.router.navigate(['/login']);
}
return throwError(() => error);
})
);
}

shouldCache(req: HttpRequest<any>): boolean {
return req.method === 'GET' && req.headers.get('cache') === 'true';
}
}
}
Loading