I'm using abp-nav-items
in the abp-nav-items I have the logout button so now do I need to write custom component for SSO to logout?
Logout process should also require another custom logic. Here is how you can manage that part:
import { UserMenuService } from '@abp/ng.theme.shared';
import { eUserMenuItems } from '@volosoft/abp.ng.theme.lepton-x';
import { APP_INITIALIZER, inject, NgModule } from '@angular/core';
@NgModule({
...
providers: [
...
{ provide: APP_INITIALIZER, useFactory: userMenuFactory },
...
],
bootstrap: [AppComponent],
})
export class AppModule {}
function userMenuFactory() {
const userMenu = inject(UserMenuService);
userMenu.patchItem(eUserMenuItems.Logout, {
action: () => {
console.log('Custom logout action');
},
});
}
Hi I'm going to write this custom guard, correct me if i'm wrong, thanks.
import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, } from '@angular/router'; import { Observable } from 'rxjs'; import { OktaAuthService } from './okta-auth.service'; // Your OktaAuthService import { OAuthService } from 'angular-oauth2-oidc'; // ABP's OAuthService
@Injectable({ providedIn: 'root', }) export class CustomAuthGuard implements CanActivate { constructor( private oktaAuthService: OktaAuthService, private oAuthService: OAuthService, private router: Router ) {}
canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean> | Promise<boolean> | boolean { return this.checkAuthentication(state.url); }
private async checkAuthentication(returnUrl: string): Promise<boolean> { const isOktaAuthenticated = await this.oktaAuthService.isAuthenticated(); const hasValidAccessToken = this.oAuthService.hasValidAccessToken();
if (isOktaAuthenticated || hasValidAccessToken) { return true; } else { // Redirect to your custom login page or handle unauthenticated access this.router.navigate(['/login'], { queryParams: { returnUrl } }); return false; }} }
Hello again, your implementation is correct, but using both OktaAuthService and OAuthService might be redundant unless your app requires multiple authentication providers (e.g., Okta for some users and OAuth2 for others).
If both services are needed, consider abstracting authentication logic into a single service to simplify maintenance. Otherwise, removing the unnecessary check can reduce complexity.
The authGuard also utilizes the angular-oauth2-oidc library, as I mentioned earlier. You can refer to the implementation here: https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/oauth/src/lib/guards/oauth.guard.ts
Since authGuard follows the logic of this library, you may need to adjust or replace it based on your specific authentication flow.
Regarding permissionGuard, it should not cause any issues. Could you verify your logic and let me know if the issue persists?
I'm thinking you are saying like this below
async hasLoggedIn(): Promise<boolean> { const authStatus = await this.oktaAuth.isAuthenticated(); return authStatus || this.oAuthService.hasValidAccessToken(); }
this.authService.hasLoggedIn().then(isLoggedIn => {
});
Yes, this is what I mean.
For the granted policies response that you shared, the okta library should not cause a problem. However, I did not see <MyProjectName>.Dashboard.Host and <MyProjectName>.Dashboard.Tenant permissions that is checked by the guard. Is this right?
I am assuming that oAuthService is from angular-oauth2-oidc library. So, you should be able to use this as you have mentioned at the beginning
this.oktaAuth.isAuthenticated().then(async (authStatus) => {
if (authStatus) {
// Authenticated successfully
}
});
Hello, yes you are right. You will need to handle this part according to the library you use.
The permission guard only checks the required permissions that you give for the route. However, dashboard component checks for MyProjectName.Dashboard.Host and MyProjectName.Dashboard.Tenant permissions exceptionally.
Here is the reference for the check: https://github.com/abpframework/abp/blob/2201ee1c349da9dff2a0a333434e660f436b0851/npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts#L47
So now the question is: why is the event handler you suggested - this.window.addEventListener('storage', (event) => { ... }) is not fired for the passive tab. As we found out, Permission Guards does not affect this. Do you have any idea what else I could check?
If the XSRF token is managed by the framework, it should update automatically using the approach I mentioned earlier. This should detect login/logout actions and redirect the passive tab to the home page when you log in from the active tab.
If the passive tab is not redirecting and requires a re-login, there might be another issue. I have not been able to reproduce this, so could you check if there is any custom logic preventing the expected behavior?
As you have mentioned, tab-2 uses an invalid XSRF token value. It either uses the old value expecting the new one, or uses the new one and complains about anyway. Could you try storing the value with an alternative way and notify me again?
I am sorry for the delay in getting back to you.
I assume you are using abp-modal for selecting items. Based on your logic, you can open another modal on top of the existing one to add new items that are not in the list.
Here is an example that may guide you through the process:
<!-- Your current modal -->
<abp-modal [(visible)]="isRoleListModalOpen">
<ng-template #abpHeader>
<h3>{{ 'Role List' }}</h3>
</ng-template>
<ng-template #abpBody>
<ul>
<li *ngFor="let role of roles">{{ role }}</li>
</ul>
<button (click)="openAddRoleModal()" class="btn btn-primary">
{{ 'Add New Role' }}
</button>
</ng-template>
<ng-template #abpFooter>
<button type="button" class="btn btn-secondary" (click)="isRoleListModalOpen = false">
{{ 'Close' }}
</button>
</ng-template>
</abp-modal>
<!-- The modal that will open when you click on add button -->
<abp-modal [(visible)]="isAddRoleModalOpen">
<ng-template #abpHeader>
<h3>{{ 'Add New Role' }}</h3>
</ng-template>
<ng-template #abpBody>
<input [(ngModel)]="newRole" placeholder="Enter role name" class="form-control" />
</ng-template>
<ng-template #abpFooter>
<button (click)="saveRole()" class="btn btn-primary" [disabled]="!newRole">
{{ 'Save' }}
</button>
<button type="button" class="btn btn-secondary" (click)="isAddRoleModalOpen = false">
{{ 'Cancel' }}
</button>
</ng-template>
</abp-modal>
You can also get a reference from this documentation: https://abp.io/docs/latest/framework/ui/angular/modal
Let me know if you need further clarification.
Thank you for sharing more details. However, I did not see anything that would cause this cyclical re-login problem in these files. That is why, I suspected whether you have implemented another guard on the home route.