Skip to content

Commit

Permalink
fix(auth): fix public access with cas inpn and other bugs
Browse files Browse the repository at this point in the history
Several fixes:
- Fix direct public access with query param when INPN CAS authentification is configured
- Fix flaky login and logout - ref #3353
- Use AuthGuard rather than UserCasGuard on NavHomeComponent, and remove UserCasGuard definition
- Handle the case where a user is no more authentified server-side but still authentified client-side, by calling frontend logout()

Chore:
- Remove unused Router and AuthService from ModuleService constructor
  • Loading branch information
VincentCauchois authored and Christophe-Ramet committed Feb 6, 2025
1 parent 7b530dd commit 8d27d8e
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 56 deletions.
3 changes: 1 addition & 2 deletions frontend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function createTranslateLoader(http: HttpClient) {
import { UserDataService } from './userModule/services/user-data.service';
import { NotificationDataService } from './components/notification/notification-data.service';

import { UserCasGuard, UserPublicGuard } from '@geonature/modules/login/routes-guard.service';
import { UserPublicGuard } from '@geonature/modules/login/routes-guard.service';

export function loadConfig(injector) {
const configService = injector.get(ConfigService);
Expand Down Expand Up @@ -111,7 +111,6 @@ export function initApp(injector) {
],
providers: [
AuthService,
UserCasGuard,
AuthGuard,
ModuleService,
ToastrService,
Expand Down
11 changes: 5 additions & 6 deletions frontend/src/app/modules/login/login/login.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,11 @@ export class LoginComponent implements OnInit {
}

ngOnInit() {
if (this.config.CAS_PUBLIC.CAS_AUTHENTIFICATION) {
// if token not here here, redirection to CAS login page
const url_redirection_cas = `${this.config.CAS_PUBLIC.CAS_URL_LOGIN}?service=${this.config.API_ENDPOINT}/gn_auth/login_cas`;
if (!this._authService.isLoggedIn()) {
document.location.href = url_redirection_cas;
}
if (this.casLogin) {
// Try to navigate to the home page, and may then be redirected to the CAS login page by the AuthGuard in a second step
// this is done because the route 'login', associated to the current component LoginComponent, is not protected by any guard
// while the route '' is well protected, by the AuthGuard
this.router.navigate(['']);
}
}

Expand Down
35 changes: 0 additions & 35 deletions frontend/src/app/modules/login/routes-guard.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,38 +71,3 @@ export class UserPublicGuard implements CanActivate {
return true;
}
}

@Injectable()
export class UserCasGuard implements CanActivate, CanActivateChild {
/*
A guard used to prevent public user from accessing certain routes :
- Used to prevent public user from accessing the "/user" route in which the user can see and change its own information
*/

constructor(
private _router: Router,
public authService: AuthService,
public _configService: ConfigService,
private _httpclient: HttpClient
) {}
canActivateChild(
childRoute: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {
return this.canActivate();
}

async canActivate(): Promise<boolean> {
let res: boolean = false;
if (this._configService.CAS_PUBLIC.CAS_AUTHENTIFICATION) {
let data = await this._httpclient
.get(`${this._configService.API_ENDPOINT}/auth/get_current_user`)
.toPromise();
data = { ...data };
this.authService.manageUser(data);
res = this.authService.isLoggedIn();
return res;
}
return true;
}
}
8 changes: 2 additions & 6 deletions frontend/src/app/routing/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ import { HomeContentComponent } from '../components/home-content/home-content.co
import { PageNotFoundComponent } from '../components/page-not-found/page-not-found.component';
import { AuthGuard } from '@geonature/routing/auth-guard.service';
import { ModuleGuardService } from '@geonature/routing/module-guard.service';
import {
SignUpGuard,
UserCasGuard,
UserPublicGuard,
} from '@geonature/modules/login/routes-guard.service';
import { SignUpGuard, UserPublicGuard } from '@geonature/modules/login/routes-guard.service';
import { SignUpComponent } from '../modules/login/sign-up/sign-up.component';

import { UserManagementGuard } from '@geonature/modules/login/routes-guard.service';
Expand Down Expand Up @@ -40,7 +36,7 @@ const defaultRoutes: Routes = [
{
path: '',
component: NavHomeComponent,
canActivate: [UserCasGuard],
canActivate: [AuthGuard],
canActivateChild: [AuthGuard],
children: [
{
Expand Down
19 changes: 16 additions & 3 deletions frontend/src/app/routing/auth-guard.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
RouterStateSnapshot,
} from '@angular/router';
import { Injectable, Injector } from '@angular/core';
import { HttpClient } from '@angular/common/http';

import { AuthService } from '@geonature/components/auth/auth.service';
import { ModuleService } from '@geonature/services/module.service';
import { ConfigService } from '@geonature/services/config.service';
Expand All @@ -15,7 +17,10 @@ import { RoutingService } from './routing.service';
export class AuthGuard implements CanActivate, CanActivateChild {
constructor(
private _router: Router,
private _injector: Injector
private _injector: Injector,
private _httpclient: HttpClient,
private config: ConfigService,
private _authService: AuthService
) {}

async redirectAuth(route, state) {
Expand All @@ -38,12 +43,20 @@ export class AuthGuard implements CanActivate, CanActivateChild {
return false;
});
if (data) {
await authService.manageUser(data).toPromise();
authService.manageUser(data);
const modules = await moduleService.loadModules().toPromise();
routingService.loadRoutes(modules, route._routerState.url);
routingService.loadRoutes(modules, route._routerState.url.replace('access=public', ''));
} else {
return false;
}
} else if (configService.CAS_PUBLIC.CAS_AUTHENTIFICATION) {
const url_redirection_cas = `${configService.CAS_PUBLIC.CAS_URL_LOGIN}?service=${configService.API_ENDPOINT}/gn_auth/login_cas`;
document.location.href = url_redirection_cas;
let data = await this._httpclient
.get(`${this.config.API_ENDPOINT}/auth/get_current_user`)
.toPromise();
data = { ...data };
this._authService.manageUser(data);
} else {
this._router.navigate(['/login'], {
queryParams: { ...route.queryParams, ...{ route: state.url.split('?')[0] } },
Expand Down
16 changes: 12 additions & 4 deletions frontend/src/app/services/module.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Injectable, Injector } from '@angular/core';
import { AuthService } from '@geonature/components/auth/auth.service';
import { DataFormService } from '@geonature_common/form/data-form.service';
import { Observable, of, BehaviorSubject } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
Expand Down Expand Up @@ -29,12 +29,20 @@ export class ModuleService {

constructor(
private _api: DataFormService,
private _router: Router
private _injector: Injector
) {}

loadModules(): Observable<any[]> {
return this._api.getModulesList([]).pipe(
catchError((err) => of([])), // TODO: error MUST be handled in case we are logged! (typically, api down)
catchError((err) => {
// Handling 401 UNAUTHORIZED error which means one is not logged in server-side
// and thus should be ensured one is correctly logged out client-side
if (err.status === 401) {
const authService = this._injector.get(AuthService);
authService.logout();
}
return of([]); // TODO: error MUST be handled in case we are logged! (typically, api down)
}),
tap((modules) => {
this.modules = modules;
this.shouldLoadModules = false;
Expand Down

0 comments on commit 8d27d8e

Please sign in to comment.