@meshmakers / shared-auth
OAuth2/OIDC认证库,用于Angular应用 angular-oauth2-oidc.
安装
npm install @meshmakers/shared-auth
快速入门
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { provideMmSharedAuth, authorizeInterceptor } from '@meshmakers/shared-auth';
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(withInterceptors([authorizeInterceptor])),
provideMmSharedAuth(),
]
};
// app.component.ts
import { Component, inject, OnInit } from '@angular/core';
import { AuthorizeService } from '@meshmakers/shared-auth';
@Component({...})
export class AppComponent implements OnInit {
private readonly authorizeService = inject(AuthorizeService);
async ngOnInit() {
await this.authorizeService.initialize({
issuer: 'https://your-identity-provider.com/',
redirectUri: window.location.origin,
clientId: 'your-client-id',
scope: 'openid profile email',
wellKnownServiceUris: ['https://api.your-service.com']
});
}
}
API参考
AuthorizeService
身份验证的主要服务。
信号(推荐)
| 信号 | 类型 | 描述 |
|---|---|---|
isAuthenticated | Signal<boolean> | 当前认证状态 |
user | Signal<IUser | null> | 当前用户信息 |
accessToken | Signal<string | null> | OAuth访问令牌 |
userInitials | Signal<string | null> | 用户首字母(例如“JD”) |
issuer | Signal<string | null> | OAuth发行者URL |
sessionLoading | Signal<boolean> | 会话加载状态 |
roles | Signal<string[]> | 用户角色(计算) |
// Usage in template
@if (authorizeService.isAuthenticated()) {
<p>Welcome, {{ authorizeService.user()?.name }}</p>
}
// Usage in TypeScript
const isAuth = this.authorizeService.isAuthenticated();
const roles = this.authorizeService.roles();
方法
| 方法 | 描述 |
|---|---|
initialize(options) | 用configuration初始化OAuth |
uninitialize() | 清理OAuth会话 |
login() | 启动OAuth登录流程 |
logout() | 注销用户 |
isInRole(role) | 检查用户是否有指定的角色 |
getAccessTokenSync() | 同步获取当前访问令牌 |
getServiceUris() | 获取配置好的服务uri |
警卫
路线保护的功能保护装置。
import { authorizeGuard, authorizeMatchGuard } from '@meshmakers/shared-auth';
const routes: Routes = [
// Basic authentication check
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [authorizeGuard]
},
// With role requirement
{
path: 'admin',
component: AdminComponent,
canActivate: [authorizeGuard],
data: { roles: ['AdminPanelManagement'] }
},
// Lazy-loaded module
{
path: 'reports',
loadChildren: () => import('./reports/routes'),
canMatch: [authorizeMatchGuard]
}
];
| 警卫 | 类型 | 描述 |
|---|---|---|
authorizeGuard | CanActivateFn | 带可选角色检查的路由激活 |
authorizeChildGuard | CanActivateFn | 子路径保护 |
authorizeMatchGuard | CanMatchFn | 惰性负载匹配保护 |
authorizeDeactivateGuard | 函数 | 总是允许停用 |
拦截器
自动添加承载令牌到HTTP请求。
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { authorizeInterceptor } from '@meshmakers/shared-auth';
providers: [
provideHttpClient(withInterceptors([authorizeInterceptor]))
]
拦截器添加 Authorization: Bearer <token> 标题:
- 同源请求(相对url)
- 配置请求
wellKnownServiceUris
它还可以从过期的访问令牌中恢复:当一个带有令牌的请求
回来 401则刷新令牌,并使用new重新尝试一次请求
持票人。刷新是单次飞行(并发401共享一次刷新) 401
在刷新完成后到达,重用其结果而不是开始
另一个。重试本身永远不会重试。没有令牌的请求表示服务运行状况
报告(/health,它需要自AB#6739以来的承载,但从未刷新过 401)和令牌
端点本身不受影响,如果刷新失败,则保留原始端点 401 到达
调用者。
TenantTopologyService
await inject(TenantTopologyService).load(rootTenantId) 返回哪个用户的租户位于应用根目录下
(topologyLeaves, topologyDirectChildren, topologyTenantIds)或 topologyKnown: false 结果有原因;它
从来没有抛出。将每个未知结果映射到“仅限令牌租户”。看到
文档/ README.md.
错误的分类
authorizationRefusal(error) 讲述了一个 401 和一个 403 分开后输入了一个错误 unknown,
因此,每个主机都可以用自己的话表达结果,而无需再次编写状态检查。
import { authorizationRefusal } from '@meshmakers/shared-auth';
switch (authorizationRefusal(error)) {
case 'forbidden': return this.translate.instant('pipeline.forbidden');
case 'unauthorized': return this.translate.instant('pipeline.unauthorized');
default: return null; // not an authorization problem — leave it to the caller
}
状态是结构化读取的,必须是a number,因此一个重新抛出的错误丢失了它的
HttpErrorResponse 原型还能分类,而身体只会携带 "403" 没有。
UI组件
LoginAppBarSectionComponent
为应用程序栏预先构建的登录/注销组件。可通过次要入口点获得 @meshmakers/shared-auth/login-ui (需要剑道UI)。
import { LoginAppBarSectionComponent } from '@meshmakers/shared-auth/login-ui';
@Component({
imports: [LoginAppBarSectionComponent],
template: `
<mm-login-app-bar-section
[showRegister]="true"
(register)="onRegister()">
</mm-login-app-bar-section>
`
})
可观察性:会话标识(ab# 7327)
选择加入:一个应用程序可以告诉它的浏览器监控(Dash0 RUM) 谁签到,哪个租户签到. 这样的应用程序
没有选择加入看到没有变化,和 @dash0/sdk-web 不是必需的(它是一个 可选 类使用的对等依赖项
@meshmakers/shared-auth/dash0 入口点)。
// app.config.ts — after the Dash0 SDK was initialised (init()) in main.ts
import { provideMmSharedAuth } from '@meshmakers/shared-auth';
import { provideDash0SessionIdentity } from '@meshmakers/shared-auth/dash0';
providers: [provideMmSharedAuth(), provideDash0SessionIdentity()]
| 属性 | 价值 |
|---|---|
user.id | sub 索赔 |
user.name | 用户名 |
user.email | 电子邮件地址(当标识没有时省略) |
octo.tenant.id | 当前访问令牌的租户(与后端服务相同的密钥) |
- 当: 在登录后和每次租户切换(就地令牌交换和重定向回退)之后设置,仅当
标识实际上已更改(令牌刷新不会重复);会话结束时清除(注销);
session_terminated,token_refresh_error、跨选项卡注销、重定向租户切换前的重置)。页面 登录前的加载保持匿名。 - 从不违背诺言: 水槽是从一个地方开出来的
effect()通过用户和令牌租户信号;中的例外 它被捕获并作为一个被记录下来console.warn使用固定文本(没有名称,没有电子邮件)。 - 隐私: 姓名和电子邮件是个人数据,发送到Dash0(欧盟地区)。只在应用程序和 数据保护信息所涵盖的环境(决定2026-10-22,ab# 7326)。
- 其他监控工具: 提供你自己的
SessionIdentitySink({ set(identity), clear() })下SESSION_IDENTITY_SINK主要入口点的标记;Dash0适配器只是其中一个实现。
配置选项
interface AuthorizeOptions {
issuer?: string; // Identity Provider URL
redirectUri?: string; // Redirect after login
postLogoutRedirectUri?: string; // Redirect after logout
clientId?: string; // OAuth client ID
scope?: string; // OAuth scopes
showDebugInformation?: boolean; // Enable debug logging
sessionChecksEnabled?: boolean; // Enable session checks
wellKnownServiceUris?: string[]; // APIs that should receive auth token
}
用户界面
interface IUser {
sub: string; // Subject (user ID)
name: string; // Display name
given_name: string | null; // First name
family_name: string | null; // Last name
email: string | null; // Email address
role: string[] | null; // User roles
idp: string; // Identity provider
}
角色
预定义角色常量:
import { Roles } from '@meshmakers/shared-auth';
if (authorizeService.isInRole(Roles.AdminPanelManagement)) {
// Admin access
}
Roles.FileViewer / Roles.FileManagement 管理平台文件系统(浏览+下载/管理);
旁边 Roles.ReportingViewer / Roles.ReportingManagement (AB#6171决定D5)。它们是由
System.Identity.Bootstrap;一次性身份迁移将它们授予匹配的每个持有者
报告的作用。
详细的文档
看到 文档/ README.md 以获取完整的API参考和使用示例。
体系结构
shared-auth/
├── src/ # Main entry point (@meshmakers/shared-auth)
│ ├── public-api.ts
│ └── lib/
│ ├── authorize.service.ts # Core OAuth2/OIDC service
│ ├── authorize.guard.ts # Functional route guards
│ ├── authorize.interceptor.ts # Functional HTTP interceptor
│ ├── roles.ts # Role enum
│ └── mm-login-app-bar-section/ # Component (internal, not exported)
│
└── login-ui/ # Secondary entry point (@meshmakers/shared-auth/login-ui)
└── src/
├── public-api.ts
└── mm-login-app-bar-section/ # LoginAppBarSectionComponent (Kendo-dependent)
入口点
| 入口点 | 导入路径 | 描述 |
|---|---|---|
| 主要 | @meshmakers/shared-auth | 核心认证服务,守卫,拦截器(没有Kendo依赖) |
| 登录界面 | @meshmakers/shared-auth/login-ui | LoginAppBarSectionComponent(需要Kendo UI) |
| Dash0 | @meshmakers/shared-auth/dash0 | provideDash0SessionIdentity() (需要可选peer @dash0/sdk-web) |
依赖关系
- 角21 (core, common/http, router)
- angular-oauth2-oidc v20 (OAuth2/OIDC客户端)
- @progress / kendo-angular -*(可选,仅用于登录界面入口点)
构建和测试
# Build
npm run build:shared-auth
# Lint
npm run lint:shared-auth
# Run tests
npm run test:shared-auth
文件和测试标准
- 所有开发人员文档必须用英语编写
- 每次代码更改都必须包含更新的文档 -更新自述文件。医学博士,克劳德。医学博士,文档/ README。在添加、修改或删除功能时使用
- 必须执行单元测试和集成测试 每次代码更改之后
- 必须更新现有的测试 当被测试代码的行为发生变化时
- 必须添加新的测试 当实现新的特性、组件或服务时
- 永远不要提交测试失败的代码