Open Closed

Error refreshing token [Login and Timeout issues] #3177


0
DJudge created

Hi,

We have been facing two critical issues and would appreciate your prompt help. We'll provide a detailed description of our app and how to reproduce the issue.

We use ABP for the backend and Angular as the client for the frontend. Our Angular app uses Office-JS technology to create a Microsoft Word Add-in.

The connection and API calls from the Angular app and ABP are working flawlessly throughout the app. However, only two issues are still happening and we don't know how to resolve them.

When the timeout expires, an error message is displayed in the console log and users will be kicked of the app. After that, trying to call the Login function again doesn't work, and trying to click the button to redirect to ABP login page doesn't work as the connection has been lost. It works only after several quick clicks on the button or when we close and restart the app.

Can you please help us understand why this happens and how can we resolve it? Can we handle that error using ABP or Angular?

We suspect that perhaps we're not implementing the login logic correctly. Can you please take a look on how we implement it and advice if we need to change anything?

  1. We use this variable (function) to check if the user is logged in or not: get hasLoggedIn(): boolean { return this.oAuthService.hasValidAccessToken(); }

  2. We check the variable hasLoggedIn in the homepage to display different UIs accordingly: <div *ngIf="hasLoggedIn"> <!-- User is logged in, show the application menus, etc --> </div> <div *ngIf="!hasLoggedIn"> <!-- User is not logged in, show the splash screen with login button to direct to ABP login page --> </div>

  3. When users click on Login button, the following function is called that will redirect to ABP login page: Login(event: any) { event.target.disabled = true; this.authService.navigateToLogin(); }

Can you please advice if that's the recommended way to check if users are logged in? We noticed that hasLoggedIn is being called constantly when we debug it, but perhaps that's how it's intended to be.

Summary of our questions:

  1. How to handle or resolve the token refresh error mentioned above?
  2. Are we checking for logged in users correctly?
  3. When it comes to tracking timeout before it expires, do we handle that in Angular or in ABP? Can you share any resources on how to do so please?
  4. Sometimes the token expiry timeout happens before the specified time, instead of 30 seconds it happens after 15 is that normal?
  5. After the timeout issue happens, clicking the login page to redirect to ABP login page doesn't work and the button must be clicked several times quickly for it to work, any suggestions of the reason?
  • ABP Framework version: v4.3.2
  • UI type: Angular / MVC
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): yes
  • Exception message and stack trace: Error refreshing token
  • Steps to reproduce the issue:
    1. Set the Access Token Lifetime to a small value for testing: 30 seconds.
    2. Wait until the timeout expires, two error messages will appear in the console log:
      1. Error: POST https://localhost:44363/connect/token 400
      2. Error refreshing token

Thank you for your help.


12 Answer(s)
  • 0
    gterdem created
    Support Team

    If you didn't alter the Clock Skew, it won't be a healthy test. Since clock skew defaults to 5 mins, I would suggest setting access token to 6 mins for testing. Or altering the clock skew.

  • 0
    DJudge created

    Thanks for your reply, we understand more about clock skew now. So now we have increased the test time to 6 minutes, the error message will be displayed afterwards, how can we handle it after it expires? Can you please advise how to catch it to display a message to users or how to refresh the token automatically so it doesn't throw that exception again?

  • 0
    gterdem created
    Support Team

    Can you try it on version 5.3 template?

  • 0
    DJudge created

    No we haven't as we did lots of customization in our current ABP template. Has this been solved in 5.3? Is there any way we can solve it on 4.3.2? as we can't afford to do the upgrade now because of too much customization.

  • 0
    gterdem created
    Support Team

    Okay, we'll try to reproduce this issue on v4.3.2 and let you know about the progress.

  • 0
    DJudge created

    Great thanks a lot for your support we appreciate it

  • 1
    muhammedaltug created
    Support Team

    Hello,

    Yes you can use this.oAuthService.hasValidAccessToken(); for checking user login status. If you change your component's changeDetection to ChangeDetectionStrategy.OnPush the getter won't call on user interaction events, after async processes. Also, you can check by subscribing configState.getDeep$('currentUser.id'), if the id is not empty this means the app has authenticated user.

    Example

    import { ChangeDetectionStrategy, Component } from '@angular/core';
    import { ConfigStateService } from '@abp/ng.core';
    import { map } from 'rxjs/operators';
    
    @Component({
        selector: 'app-component',
        template:`~~~~
            &lt;!-- example with checking user id --&gt;
            &lt;div *ngIf=&quot;isAuthenticated$ |&#160;async; else notAuthenticated&quot;&gt;
                authenticated
            &lt;/div&gt;
            &lt;ng-template #notAuthenticated&gt;
                not authenticated
            &lt;/ng-template&gt;
        `,
        changeDetection: ChangeDetectionStrategy.OnPush, 
    })
    export class YourComponent {
    
        isAuthenticated$ = this.configState.getDeep$('currentUser.id').pipe(map(Boolean)); 
        
        constructor(private configState: ConfigStateService) {}
    }
    

    event.target.disabled = true; why did you do that way instead of following way

    @Component({
        selector: 'app-component',
        template: '<button [disabled]="disabled" (click)="makeDisabled()"> myButton </button>'
    })
    export class YourComponent {
        makeDisabled() {
            this.disabled = true;
        }
    }
    

    We can not produce the token refresh error in version 4.3.2. Related video link

  • 0
    DJudge created

    Hi muhammedaltug thanks a lot for your reply. Your suggestion about disabling the button works better thanks. We watched the video, I think the main difference in our case is that we are using a standalone Angular app with Office-JS so it's not build inside ABP like your test project.

    We will create a sample project with our code in both ABP and Angular sides and share it with you in github, perhaps it'll shed some light on the problem that we're facing.

    Will update this post once we create the project, thanks.

  • 0
    gterdem created
    Support Team

    We watched the video, I think the main difference in our case is that we are using a standalone Angular app with Office-JS so it's not build inside ABP like your test project.

    So, your angular application is not ABP, that's why you couldn't update to 5.3 also. Do I understand correctly?

  • 0
    DJudge created

    Hi gterdam, yes the Angular application was created separately and we installed ABP libraries and proxies to get it to work. However, the only reason why we are not updating to 5.3 is that we did lots of customizations in ABP side and it will cost us to do the upgrade process to get everything to work well with the Angular app. Is updating to 5.3 the only option to solve this?

    We have recorded this video to show the error message in action and also to show the angular app code parts for the login, hopefully, it will make it easier to detect the problem: error and code video link

    We noticed that the problem happens mostly with slower internet connections, it doesn't happen all the time. For the purpose of catching it on localhost, I set the value of timeout to a small value. But it shows the same error when it happens with larger values sometimes.

    It seems that it might be a problem in our Angular app and the way we connect with ABP, but we can't identify where is the issue.

    One suggestion that might help you and us understand the problem, we created our Angular app using the following link: https://www.initgrep.com/posts/javascript/angular/microsoft-office-addin-using-angular-cli

    If you created the app the same way and get it to connect and login with ABP, perhaps this will show us the right way to do things? The steps are straightforward to get it to run on Word.

    Otherwise, we have created a sample app using the link above, it has some ABP errors that we couldn't fix, if you fixed it will run exactly as our main application and then you can identify the problem: https://github.com/DesertfireOnline/ABP-Word-Addin-Sample

    Thanks for your help and please let us know if you require further information.

  • 1
    muhammedaltug created
    Support Team

    Hello,

    I opened a pull request for ABP implementation.

    • I added guards for checking authentication, checking internet explorer, and check is the desktop version. And I added related components
    • I make a component named AppLayoutComponent for use in authenticated pages (Using router-outlet in ngIf is not best practice. It can cause reconstruct components every change detection)
    • I added an example for forcing the router to navigate the same route (using location.reload function is not a good idea for SPAs)
    • Modified app routing by using created guards and components.

    After these changes, you can navigate to the login page by clicking the log-in button page one time. You don't need to check explorer, desktop version, and login status in the component (Your layout component only includes layout methods and layout components).

    I tried to reproduce your error but I can't reproduce it (I added a custom network throttling configuration upload 1kb download 1kb).

    Can you share the backend log with the related token endpoint whose HTTP status is 400?

    Can you inform us about what is the client's AbsoluteRefreshTokenLifetime, SlidingRefreshTokenLifetime?

  • 0
    DJudge created

    Hi muhammedaltug,

    AbsoluteRefreshTokenLifetime: 31536000, we haven't set the SlidingRefreshTokenLifetime value so it's the default value?

    We appreciate your help in the sample project and after testing and reviewing your code we think it's cleaner and has a better structure in handling login and routing than our current structure.

    We're planning to implement your changes in our main project structure, it will take some time so we will keep the ticket open till we get back to you with the result. We will send the backend log then as well if the error still happens.

    Thanks again for your efforts.