> For the complete documentation index, see [llms.txt](https://guide-angular.wishtack.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://guide-angular.wishtack.io/angular/routing/route-guards.md).

# Route Guards

Les "Guards" permettent de contrôler **l'accès à une "route"** *(e.g. autorisation)* ou le **départ depuis une "route"** *(e.g. enregistrement ou publication obligatoire avant départ)*.

{% hint style="danger" %}
**Les "Guards" ne doivent en aucun cas être considérés comme un mécanisme de sécurité.**

La gestion de **permission des accès aux ressources doit se faire au niveau des APIs HTTP** : <https://blog.wishtack.com/api-rest-bonnes-pratiques-et-securite/>.

Les "Guards" servent à améliorer la "User eXperience" en évitant par exemple l'accès à des "routes" qui ne fonctionneraient pas car l'accès aux données serait rejeté par l'API.
{% endhint %}

## Configuration

Les "Guards" sont ajoutés au niveau de la configuration du "Routing" :

```typescript
export const appRouteList = [
    {
        path: 'cart',
        loadChildren: './views/cart/cart-routing.module#CartRoutingModule',
        canActivate: [
            IsSignedInGuard
        ]
    },
    {
        path: 'signin',
        component: SigninViewComponent,
        canActivate: [
            IsNotSignedInGuard
        ]
    },
    {
        path: 'profile',
        component: ProfileViewComponent,
        canDeactivate: [
            IsNotDirtyGuard
        ]
    }
]
```

## `CanActivate`

Une "Guard" d'activation est un service qui implémente l'**interface `CanActivate`**.

Ce service doit donc **implémenter la méthode `canActivate`**.\
Cette méthode est **appelée à chaque demande d'accès à la "route"** ; elle doit alors **retourner une valeur de type `boolean` ou `Promise<boolean>` ou `Observable<boolean>`** indiquant si l'accès à la "route" est autorisé ou non.

Il est donc possible d'attendre le résultat d'un traitement asynchrone pour décider d'autoriser l'accès ou non.

{% tabs %}
{% tab title="is-signed-in.guard.ts" %}

```typescript
@Injectable({
    providedIn: 'root'
})
export class IsSignedInGuard implements CanActivate {

    constructor(private _session: Session) {
    }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        return this._session.isSignedIn();
    }

}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
En cas de refus d'accès, il est possible de **rediriger l'utilisateur vers une autre "route"** "manuellement" en injectant le service "Router" par exemple :

```typescript
    constructor(private _router: Router,
                private _session: Session) {
    }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {

        const isSignedIn = this._session.isSignedIn();

        if (isSignedIn !== true) {
            this._router.navigate([...]);
        }

        return isSignedIn;

    }
```

{% endhint %}

## `CanDeactivate`

Les "Guards" de désactivation sont **couplées aux composants** car elles doivent **communiquer avec le composant** pour établir leur décision d'accès.

Une "Guard" de désactivation est un service qui implémente l'**interface `CanDeactivate`**.

Ce service doit donc **implémenter la méthode `canDeactivate`**.\
Cette méthode est **appelée à chaque fois que l'utilisateur souhaite quitter la route** *(clic sur un lien ou déclenchement automatique)* ; elle doit alors **retourner une valeur de type `boolean` ou `Promise<boolean>` ou `Observable<boolean>`** indiquant si l'accès à la "route" est autorisé ou non.

Contrairement au "Guards" d'activation, cette "Guard" prend en **premier paramètre l'instance du composant**. C'est pour cette raison que l'interface `CanDeactivate` est générique.

{% hint style="warning" %}
La "Guard" appelle la méthode `isDirty` du composant `ProfileViewComponent` pour décider d'autoriser ou non l'utilisateur à quitter la route.

Malheureusement, la "Guard" est fortement couplée avec le composant `ProfileViewComponent`.

```typescript
@Injectable({
    providedIn: 'root'
})
export class IsNotDirtyGuard implements CanDeactivate<ProfileViewComponent> {

    canDeactivate(component: ProfileViewComponent,
                  currentRoute: ActivatedRouteSnapshot,
                  currentState: RouterStateSnapshot,
                  nextState?: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
        return component.isDirty();
    }

}
```

```typescript
export class ProfileViewComponent {

    isDirty() {
        return false;
    }

}
```

{% endhint %}

{% hint style="success" %}
Pensez à associer la "Guard" à une interface plutôt qu'au composant directement.

```typescript
export interface IsDirty {
    isDirty(): boolean | Observable<boolean>;
}

@Injectable({
    providedIn: 'root'
})
export class IsNotDirtyGuard implements CanDeactivate<IsDirty> {

    canDeactivate(component: IsDirty,
                  currentRoute: ActivatedRouteSnapshot,
                  currentState: RouterStateSnapshot,
                  nextState?: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
        return component.isDirty();
    }

}
```

```typescript
export class ProfileViewComponent implements IsDirty {

    isDirty() {
        return false;
    }

}
```

{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://guide-angular.wishtack.io/angular/routing/route-guards.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
