
Research
/Security News
9 Malicious NuGet Packages Deliver Time-Delayed Destructive Payloads
Socket researchers discovered nine malicious NuGet packages that use time-delayed payloads to crash applications and corrupt industrial control systems.
ngx-access
Advanced tools
Add access control to your components using hierarchical configuration with logical expressions.
<app-sidebar *ngxAccess="'ADMIN'"></app-sidebar>
The app-sidebar component is displayed only if the user has 'ADMIN' access.
<app-salaries *ngxAccess="'ADMIN | HR'; else unauthorized"></app-salaries>
<ng-template #unauthorized>
You do not have enough permissions to display this section.
</ng-template>
The app-salaries component is displayed only if the user has ADMIN OR HR access.
The ADMIN and HR access are evaluated using your custom strategy
import { AccessStrategy } from "ngx-access";
@Injectable()
export class RoleAccessStrategy implements AccessStrategy {
constructor(private userService: UserService) {}
check(role: string): boolean {
return this.userService
.getRoles()
.some((userAccess) => userAccess === role);
}
}
You have full control on how Access Control should be verified, ngx-access doesn't differentiate between User, Role and Permissions based access controls. They're all access controls, you put whatever access control logic you want in your AccessStrategy service.
ngx-access is simply the glue between the logical expression you put in your template and the custom AccessStrategy you define.
The Access strategy can be reactive.
There are predefined strategies provided for some common use cases though. (WIP 🚧)
npm install --save ngx-access
ngx-access version >= 1.4.2 and above has verified compatibility with the following Angular versions.
| Angular version | ngx-access version |
|---|---|
| 11.x | ✅ |
| 10.x | ✅ |
| 9.x | ✅ |
| 8.x | ✅ |
| 7.x | ✅ |
| 6.x | ✅ |
If the version you are using is not listed, please raise an issue in our GitHub repository.
To define your custom access strategy
import { AccessStrategy } from "ngx-access";
@Injectable()
export class PermissionAccessStrategy implements AccessStrategy {
constructor(private userService: UserService) {}
// You have full control on access control logic
check(persmission: string): boolean {
return this.userService
.getPermissions()
.some((userPermission) => userPermission === persmission);
}
}
You can implement a reactive strategy by returning an Observable<boolean>.
import { AccessStrategy } from "ngx-access";
@Injectable()
export class PermissionAccessStrategy implements AccessStrategy {
constructor(private userService: UserService) {}
// You have full control on access control logic
check(persmission: string): Observable<boolean> {
return this.userService
.getPermissions()
.pipe(
map((userPermissions: string[]) =>
userPermissions.some(
(userPermission) => userPermission === persmission
)
)
);
}
}
import { AccessStrategy } from "ngx-access";
import { PermissionAccessStrategy } from "./core/access.service";
@NgModule({
providers: [{ provide: AccessStrategy, useClass: PermissionAccessStrategy }],
})
export class AppModule {}
<input
*ngxAccess="'CanUpdateAll | (CanUpdateUser & CanUpdateUserPassword)'"
type="password"
/>
The input element is displayed only if the user has CanUpdateAll access OR both CanUpdateUser And CanUpdateUserEmail access.
If user has CanUpdateAll access, CanUpdateUser and CanUpdateUserEmail access will not be evaluated.
<form *ngxAccess>
<h1>Update User Form</h1>
<input *ngxAccess="'CanUpdateUserAvatar'" />
<input *ngxAccess="'CanUpdateUserName'" />
<input *ngxAccess="'CanUpdateUserAge'" />
<input *ngxAccess="'CanUpdateUserPassword'" />
</form>
The form (including h1) will be displayed only if the user has one of the access in the inputs beneath.
| Type | Description | Evaluation |
|---|---|---|
| & | Access1 & Access2 | true if user has Access1 AND Access2. |
| | | Access1 | Access2 | true if user has Access1 OR Access2 |
| &/| | Access1 & (Access2 | Access3) | true if user has Access1 AND (Access2 OR Access3) |
You can use AccessService to check if a user is granted an access.
import { Component, OnInit } from "@angular/core";
import { AccessService } from "ngx-access";
@Component({
selector: "app-main",
templateUrl: "./component.html",
styleUrls: ["./component.css"],
})
export class MainComponent {
constructor(private accessService: AccessService) {}
submit() {
if (this.accessService.check("ADMIN | RH")) {
// Send ADMIN | RH specific Payload to backend
}
}
}
You can use AccessGuard as a guard deciding if a route can be activated / loaded depending on the experssion/path you provide.
{
path: "admin",
component: AdminComponent,
canActivate: [AccessGuard],
data: {
access: "ADMIN", // access: "Home.Admin:Read"
redirectTo: "/unauthorized",
// if no 'ADMIN' access, guard refirects to '/unauthorized'
},
},
Full example
import { AccessGuard, AccessModule, AccessStrategy } from "ngx-access";
@NgModule({
imports: [
AccessModule.forRoot({
redirectTo: "/forbidden", // Default path redirected to from Guard when the access is revoked
}),
RouterModule.forRoot([
{
path: "profile",
component: ProfileComponent,
canActivate: [AccessGuard],
data: {
access: "ADMIN",
// if no 'ADMIN' access, guard refirects to '/forbidden' defined at module level
},
},
{
path: "salaries",
loadChildren: () =>
import("./salaries/salaries.module").then((m) => m.SalariesModule),
canLoad: [AccessGuard],
data: {
access: "ADMIN | RH",
// if no 'ADMIN' or 'RH' access, guard refirects to '/not-found'
redirectTo: "/not-found",
},
},
{ path: "forbidden", component: UnauthorizedComponent },
{ path: "not-found", component: NotFoundComponent },
]),
],
providers: [{ provide: AccessStrategy, useClass: MyAccessStrategy }],
})
export class AppModule {}
We can define access controls using external access configuration. This is useful when we want to maintain the access:
First we setup the Access Control configuration by mapping unique IDs with the Access Control Logical Expression to evaluate.
{
"UserForm": "CanReadUser | CanUpdateUser",
"UserMenu": "CanListUsers"
}
In the template we provide the Access Control ID
<input *ngxAccess="':UserForm'" />
<!-- is equivalent to -->
<input *ngxAccess="'CanReadUser | CanUpdateUser'" />
We can use flat configuration that maps IDs with Access Control expressions
export const ACCESS_CONFIGURATION: AccessConfiguration = {
UserForm: "CanReadUser | CanUpdateUser",
UserMenu: "CanListUsers",
};
Or a Hierarchical configuration for better readbility
export const ACCESS_CONFIGURATION: AccessConfiguration = {
User: {
Form: {
Email: {
Read: "CanReadUserEmail",
Update: "CanReadUserEmail & CanUpdateUserEmail",
},
Password: {
Update: "CanUpdateUserPassword",
},
},
},
};
which can be used in the template like this:
<input *ngxAccess="':User.Form.Email.Read'" />
<input type="password" *ngxAccess="':User.Form.Password'" />
app-user-form component below is displayed only if the user has at least one of the Update access defined beneath the User.Form access path, namely: (CanReadUserEmail and CanUpdateUserPassword) or CanUpdateUserAddress access.
<app-user-form *ngxAccess="':User.Form.Update'"></app-user-form>
<!-- is equivalent to -->
<app-user-form
*ngxAccess="'(CanReadUserEmail & CanUpdateUserEmail) | CanUpdateUserAddress'"
></app-user-form>
The access configuration can be set in a module:
import { ACCESS_CONFIGURATION } from "./access-configuration";
@NgModule({
imports: [
AccessModule.forRoot({
access: ACCESS_CONFIGURATION,
}),
],
providers: [{ provide: AccessStrategy, useClass: RoleAccessStrategy }],
})
export class AppModule {}
The access configuration can be in a service:
import { ACCESS_CONFIGURATION } from "./access-configuration";
import { Component } from "@angular/core";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent {
constructor(private accessService: AccessService) {}
ngOnInit() {
this.accessService.setConfiguration(ACCESS_CONFIGURATION);
}
}
You can use logical expression on your access ids
<app-user *ngxAccess=":('UserForm' | 'UserMenu')"></app-user>
You can get the access configuration from your server at startup
import { APP_INITIALIZER } from "@angular/core";
export function loadServerConf(
accessService: AccessService,
http: HttpClient
): () => Promise<void> {
return () => {
// You can have a specific endpoint to load the access configuration specific to the user
const apiConf$ = this.http
.get<AccessModuleConfiguration>("/api/me/access")
.pipe(catchError((_) => of({})));
// You can load the configuration as a static asset
const staticConf$ = this.http
.get<AccessModuleConfiguration>("/assets/access.json")
.pipe(catchError((_) => of({})));
return serverConf$ // or staticConf$
.toPromise()
.then((configuration: AccessConfiguration) => {
accessService.setConfiguration(configuration);
});
};
}
@NgModule({
providers: [
{
provide: APP_INITIALIZER,
useFactory: loadServerConf,
deps: [AccessService, HttpClient],
multi: true,
},
],
})
export class AppModule {}
You can import the access configuration as JSON. Note that the configuration will be part of your application bundle.
{
"compilerOptions": {
"declaration": false,
"resolveJsonModule": true,
"esModuleInterop": true
}
}
{
"UserForm": "CanReadUser | CanUpdateUser",
"UserMenu": "CanListUsers"
}
import access from "./src/assets/access.json";
@NgModule({
imports: [
AccessModule.forRoot({
access,
}),
],
})
export class AppModule {}
MIT © Chihab Otmani
FAQs
Add access control to your components using hierarchical configuration with logical expressions.
We found that ngx-access demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Socket researchers discovered nine malicious NuGet packages that use time-delayed payloads to crash applications and corrupt industrial control systems.

Security News
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.

Security News
Learn the essential steps every developer should take to stay secure on npm and reduce exposure to supply chain attacks.