What prevents us from returning Observable.of(false) in the catch block within the canActivate function?

In order to protect certain routes (admin), I utilize the canActivate feature. In this scenario, I employ an authGuard class/function:

The issue arises when attempting to return an observable of boolean using: return Observable.of(false);. This approach does not yield the expected results and triggers the following Error:

Argument of type '(err: any) => Observable | Observable' is not assignable to parameter of type '(err: any, caught: Observable) => ObservableInput'. Type 'Observable | Observable' is not assignable to type 'ObservableInput'. Type 'Observable' is not assignable to type 'ArrayLike'. Property 'length' is missing in type 'Observable'.

Research on a similar issue was conducted, but the solutions found were not completely applicable. One suggested hint or solution recommended using .throw(err);

Upon switching the return statement to: return Observable.throw(err);, the error disappears. However, it fails to return false as required for route protection.

A potential root cause could be related to a type mismatch, yet attempts to rectify it have been unsuccessful while trying to maintain the use of observable.of(false).

canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean> | Promise<boolean> | boolean {
        return this.userService.getAdminAuth()
        .map( (res) => {
            if ( res === true) {
                return true;
            } else {
                ......
                return false;
            }
        })
        .catch( (err) => {
            if ( err.status === 403 ) {
                console.log(`403:  ${err.status}`);
                return this.userService.refreshToken()
                    .map( (res) => {
                        console.log(`Res RefreshToken: ${res}`);
                    });
            }
            return Observable.of(false); // protect route!
        });
}

Functions within user.service.ts:

....

isAdminAuthenticated = false;

public getAdminAuth() {
    console.log('Saved token: ' + localStorage.getItem('ac_token') );
    if ( this.isAdminAuthenticated === true ) {
        return Observable.of(true);
    } else {
        return this.http.get(
           'URL', { 
              headers: new HttpHeaders({"Accept": "application/json"}), 
              withCredentials: true, 
              observe: "response" 
           }
        )
        .map((res) => {
            if (res.status === 200) {
                this.isAdminAuthenticated = true;
                return true;
            } else {
                return false;
            }
        }, (err) => {
            console.log('Error: ' + err);
            return false;
        });
    }
}


refreshToken() {
    return this.http.get(
        'URL', 
        { 
            headers: new HttpHeaders(
                {
                    "Accept": "application/json",
                    "Authorization" : "Bearer " + localStorage.getItem('ac_token')
                }
            ), 
            withCredentials: true, 
            observe: "response" 
        }
    )
}

If the refreshToken function is modified to:

refreshToken() {
        return this._http.get(
            'URL', 
            { 
                headers: new HttpHeaders(
                    {
                        "Accept": "application/json",
                        "Authorization" : "Bearer " + localStorage.getItem('ac_token')
                    }
                ), 
                withCredentials: true, 
                observe: "response" 
            }
        ).map( (res) => {
            console.log(`Res: ${JSON.stringify(res)}` );
        }), (err) => {
            console.log(`Err: ${JSON.stringify(err)}` );
        };
}

An error message indicates:

ERROR in src/app/admin.guard.ts(38,9): error TS2322: Type 'Observable' is not assignable to type 'boolean | Promise | Observable'. Type 'Observable' is not assignable to type 'Observable'. Type 'boolean | {}' is not assignable to type 'boolean'. Type '{}' is not assignable to type 'boolean'. src/app/service.guard.ts: error TS2339: Property 'map' does not exist on type '(err: any) => boolean'.

Answer №1

It is recommended to utilize return Observable.throw(false) instead. The usage of of signifies success, whereas throw indicates an error.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unlock hidden Google secrets within your Angular application using Google Secret Manager

Can the Google Secret Manager API be accessed with a simple API call using an API key? https://secretmanager.googleapis.com/v1/projects/*/secrets/*?key=mykey returns a 401 unauthenticated error. While the Node.js server powering the Angular app uses the c ...

Unable to retrieve data from Angular service to component

My service function involves querying the database for products. getPro():any{ this.database.all("SELECT * FROM product").then(rows => { console.log("hello pro hear....") let productList:Product[]=[] for(var row in rows) { ...

Guarding against Angular routes that do not have a component and may include an

Currently, I am in the process of locking down routes by making an API call to check permissions. The existing routes are as follows: { path: '', children: [ { path: '', component: HomeComponent}, { path: ' ...

Attempting to organize a list using Angular 8 CDK Drag and Drop functionality

Currently, I am working on creating a drag and drop list using Angular. However, I am facing an issue with resetting the tables to their initial arrangements. I attempted to utilize transferArrayItem but I am struggling to find a way to reference the table ...

Karma Jasmin is puzzled as to why her tests are failing intermittently, despite the absence of any actual test cases

In this snippet, you will find my oninit method which I am instructed not to modify. ngOnInit(): void { this.setCustomizedValues(); this.sub = PubSub.subscribe('highlightEntity', (subId, entityIdentifier: string) => { ...

The Ionic search bar will only initiate a search once the keyboard is no longer in view

In my Ionic application, I have implemented a search bar to filter and search through a list. The filtering process is triggered as soon as I start typing in the search bar. However, the updated results are not displayed on the screen until I manually hide ...

Angular router.redirect is not able to pass variables as expected

I am facing an issue with the router redirect and template lifecycle while using Stripe checkout in my Angular 5 project. After a user signs up, I trigger the stripe checkout modal. Once the modal receives a payment source token, I perform some additional ...

What is the best way to access a class's private static property in order to utilize it for testing purposes?

Hello, I am currently a beginner in TypeScript and unit testing, so this inquiry may seem elementary to those more experienced. I am attempting to perform unit testing on the code provided below using sinon. Specifically, I am interested in testing whethe ...

Differing preferences for indentation styles can lead to conflicting prett

My eslint setup is as follows: { "env": { "es2020": true, "jest": true }, "extends": [ "eslint:recommended", "plugin:react/recommended", "plugin:import/recommended&q ...

Return the previous value if the filter function returns false in RxJs

In an attempt to optimize performance and reduce unnecessary requests to the server, this code checks if values exist in the store before making additional requests. While the overall logic functions correctly, there is an issue where if the filter returns ...

ngx-emoji mart - The error message "Type 'string' is not assignable" is being displayed

While working on a project involving the @ctrl/ngx-emoji-mart package, I encountered a perplexing issue. The code functioned flawlessly in Stackblitz but when I attempted to run it on my local system, an error surfaced: Type 'string' is not assig ...

Cloud Formation from CDK doesn't pause for addDependency to finish

I'm currently in the process of building a CDK stack and I am fairly new to CDK. My goal is to create a Simple Email Service (SES) ConfigurationSet followed by an EmailIdentity. The issue I encountered is that the creation of the EmailIdentity fails d ...

Change the router outlet to the currently selected tab

We are in the process of conceptualizing a cutting-edge angular 7 application featuring material design (md-tabs) with multiple tabs. Our goal is to enable dynamic tab creation, with each tab representing the content of a specific route. The home page sh ...

Is it possible to incorporate websockets into an Angular Universal 9 app using express-ws and the WebSocket client API?

I am completely puzzled by the behavior I am experiencing, so I have decided to share the Angular Universal server code that is powering my express server. I suspect that there might be something in Angular Universal's rendering engine causing issues ...

Having difficulty transferring types to and from a custom module?

I'm currently faced with an issue while working on a typescript module within a larger monorepo. I am having difficulty importing types from one package into another via node modules. The types are located at ./types, and my package.json contains a ke ...

Unable to enhance Request using Typscript in nodejs

In my middleware, I am attempting to enhance the Request by adding a property called user. However, I encountered this error: Property 'user' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs>' I am trying to u ...

Exploring the terrain of observable data

Understanding how to filter an observable is really challenging for me right now. I have a gadget {name: string, description: string} I possess an observable collection of gadgets [{},{},{}] My goal is to iterate through my observable collection of ga ...

Customize the width of the intl-tel-input field using Angular

Utilizing the Nebular ngx-admin template in my Angular application, along with ng2-tel-input for mobile number input. Below is the HTML code I am using: <div class="form-control-group"> <label class="label" for=" ...

Encountered a problem while attempting to build with ng build --prod. No issues when using ng serve or excluding

My project was working smoothly with ng build --prod until I decided to update the TypeScript version from 2.72 to 2.92 in my package.json file. Now, after the update, an error message pops up: ERROR in Cannot read property 'Symbol(Symbol.iterator ...

Consecutive requests to APIs using RxJs

Is it possible to efficiently make sequential API calls using RxJs? The challenge lies in the fact that the first Observable emits an array, and for each item in this array, a custom URL should be set for the next call. Additionally, certain conditions nee ...