@processpuzzle/auth 0.0.4 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,11 +13,9 @@ The Auth library provides widgets and services for authentication and authorizat
13
13
  - [auth guard](#authentication-guard)
14
14
 
15
15
  ## Auth Button
16
-
17
16
  The `AuthButtonComponent` is a versatile authentication button that displays different options based on the user's authentication status. It provides a clean, intuitive interface for users to access authentication-related features.
18
17
 
19
18
  ### Features
20
-
21
19
  - Displays a person icon button that opens a dropdown menu
22
20
  - Dynamically shows different menu options based on authentication status
23
21
  - When not authenticated, it shows Login and Register options
@@ -26,7 +24,6 @@ The `AuthButtonComponent` is a versatile authentication button that displays dif
26
24
  - Uses Angular Material components for a consistent UI experience
27
25
 
28
26
  ### Usage
29
-
30
27
  Simply add the component to your template:
31
28
 
32
29
  ```html
@@ -36,7 +33,6 @@ Simply add the component to your template:
36
33
  The component automatically detects the user's authentication status using the `AuthService` and displays the appropriate menu options.
37
34
 
38
35
  #### Example: Adding to a toolbar
39
-
40
36
  ```html
41
37
  <mat-toolbar>
42
38
  <span>My App</span>
@@ -60,7 +56,6 @@ The component automatically detects the user's authentication status using the `
60
56
  - `routes` - The filtered list of authentication routes with titles
61
57
 
62
58
  ### Styling
63
-
64
59
  The component uses Angular Material styling by default. You can target the component with CSS using the `.auth-button` class:
65
60
 
66
61
  ```css
@@ -70,7 +65,6 @@ The component uses Angular Material styling by default. You can target the compo
70
65
  ```
71
66
 
72
67
  ### Customization
73
-
74
68
  The component uses routes defined in `authRoutes` from the auth library. Each route can have the following properties:
75
69
 
76
70
  - `path` - The route path
@@ -81,11 +75,9 @@ The component uses routes defined in `authRoutes` from the auth library. Each ro
81
75
 
82
76
 
83
77
  ## Login Component
84
-
85
78
  The `LoginComponent` provides a user-friendly interface for authentication, allowing users to sign in with their email and password or through Google authentication. It includes form validation, error handling, and visual feedback during the authentication process.
86
79
 
87
80
  ### Features
88
-
89
81
  - Clean, responsive login form with Material Design styling
90
82
  - Email and password authentication with Firebase
91
83
  - Google sign-in integration
@@ -146,7 +138,6 @@ Or create a link in your template:
146
138
  - `getErrorMessage(errorCode: string)` - Converts Firebase error codes to user-friendly messages
147
139
 
148
140
  ### Styling
149
-
150
141
  The component uses Angular Material styling with custom CSS for layout. You can target the component with CSS using the `.login-container` class:
151
142
 
152
143
  ```css
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Silent Check SSO</title>
6
+ </head>
7
+ <body>
8
+ <script>
9
+ parent.postMessage(location.href, location.origin);
10
+ </script>
11
+ </body>
12
+ </html>
@@ -5,7 +5,7 @@
5
5
  "register": "Register",
6
6
  "my_profile": "My Profile"
7
7
  },
8
- "login-form": {
8
+ "login_form": {
9
9
  "title": "Login",
10
10
  "email_label": "Email",
11
11
  "email_err_required": "Email is required",
@@ -17,13 +17,13 @@
17
17
  "signing_in_button": "Signing in...",
18
18
  "google_button": "Sign in with Google"
19
19
  },
20
- "logout-dialog": {
20
+ "logout_dialog": {
21
21
  "title": "Confirm Logout",
22
22
  "content": " Are you sure you want to log out?",
23
23
  "cancel_button": "Cancel",
24
24
  "logout_button": "Logout"
25
25
  },
26
- "registration-form": {
26
+ "registration_form": {
27
27
  "title": "Create Account",
28
28
  "email_label": "Email",
29
29
  "email_placeholder": "Enter your email",
@@ -0,0 +1,220 @@
1
+ import * as i0 from '@angular/core';
2
+ import { signal, computed, Injectable, InjectionToken, makeEnvironmentProviders, inject } from '@angular/core';
3
+ import { RUNTIME_CONFIGURATION } from '@processpuzzle/util';
4
+ import { v4 } from 'uuid';
5
+ import Keycloak from 'keycloak-js';
6
+ import { signInWithEmailAndPassword, getAuth, connectAuthEmulator } from '@angular/fire/auth';
7
+
8
+ // Custom matcher function to match any URL containing 'auth'
9
+ function authMatcher(segments) {
10
+ const hasAuth = segments.some((segment) => segment.path === 'auth');
11
+ if (hasAuth) {
12
+ // Find the index of 'auth' segment
13
+ const authIndex = segments.findIndex((segment) => segment.path === 'auth');
14
+ // Return consumed segments up to and including 'auth'
15
+ return {
16
+ consumed: segments.slice(0, authIndex + 1),
17
+ posParams: {},
18
+ };
19
+ }
20
+ return null;
21
+ }
22
+
23
+ class AuthService {
24
+ _user = signal(undefined, ...(ngDevMode ? [{ debugName: "_user" }] : /* istanbul ignore next */ []));
25
+ user = this._user.asReadonly();
26
+ isAuthenticated = computed(() => (this.user ? !!this.user() : undefined), ...(ngDevMode ? [{ debugName: "isAuthenticated" }] : /* istanbul ignore next */ []));
27
+ // region protected, private helper methods
28
+ throwError(message) {
29
+ throw new Error(message);
30
+ }
31
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: AuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
32
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: AuthService, providedIn: 'root' });
33
+ }
34
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: AuthService, decorators: [{
35
+ type: Injectable,
36
+ args: [{
37
+ providedIn: 'root',
38
+ }]
39
+ }] });
40
+
41
+ class User {
42
+ id;
43
+ _email;
44
+ _password;
45
+ _firstName;
46
+ _lastName;
47
+ _photoUrl;
48
+ constructor(email, id, firstName, lastName, photoUrl) {
49
+ this._email = email;
50
+ this.id = id ?? v4();
51
+ this.firstName = firstName ?? '';
52
+ this.lastName = lastName ?? '';
53
+ this.photoUrl = photoUrl ?? '';
54
+ }
55
+ // region properties
56
+ get email() {
57
+ return this._email;
58
+ }
59
+ set email(email) {
60
+ this._email = email;
61
+ }
62
+ get firstName() {
63
+ return this._firstName;
64
+ }
65
+ set firstName(firstName) {
66
+ this._firstName = firstName;
67
+ }
68
+ get lastName() {
69
+ return this._lastName;
70
+ }
71
+ set lastName(lastName) {
72
+ this._lastName = lastName;
73
+ }
74
+ get password() {
75
+ return this._password;
76
+ }
77
+ set password(password) {
78
+ this._password = password;
79
+ }
80
+ get photoUrl() {
81
+ return this._photoUrl;
82
+ }
83
+ set photoUrl(url) {
84
+ this._photoUrl = url;
85
+ }
86
+ }
87
+
88
+ class KeycloakAuthService extends AuthService {
89
+ config;
90
+ keycloak;
91
+ initPromise = null;
92
+ constructor(config) {
93
+ super();
94
+ this.config = config;
95
+ this.keycloak = new Keycloak({
96
+ clientId: config.clientId,
97
+ realm: config.realm,
98
+ url: config.authServerUrl,
99
+ });
100
+ }
101
+ // region public accessors and mutators
102
+ async authenticate() {
103
+ await this.ensureInitialized();
104
+ return !!this.getCurrentUser();
105
+ }
106
+ async login(redirectUrl) {
107
+ await this.ensureInitialized();
108
+ if (this.isAuthenticated())
109
+ return this.user();
110
+ else {
111
+ await this.keycloak.login({ redirectUri: globalThis.location.origin + '/' + redirectUrl });
112
+ return this.getCurrentUser();
113
+ }
114
+ }
115
+ async logout(redirectUrl) {
116
+ await this.keycloak.logout({ redirectUri: globalThis.location.origin + '/' + redirectUrl });
117
+ this._user.set(undefined);
118
+ }
119
+ getCurrentUser() {
120
+ return this.user();
121
+ }
122
+ getUsername() {
123
+ return this.keycloak.profile?.username || '';
124
+ }
125
+ getUserRoles() {
126
+ return this.keycloak.realmAccess?.roles || [];
127
+ }
128
+ // endregion
129
+ // region protected, private helper methods
130
+ ensureInitialized() {
131
+ this.initPromise ??= this.initKeycloak();
132
+ return this.initPromise;
133
+ }
134
+ async initKeycloak() {
135
+ await this.keycloak.init({
136
+ onLoad: 'check-sso',
137
+ silentCheckSsoRedirectUri: 'http://localhost:4200/assets/auth/silent-check-sso.html',
138
+ });
139
+ // Check if authenticated using the keycloak-js instance directly
140
+ if (this.keycloak.authenticated) {
141
+ const profile = await this.keycloak.loadUserProfile();
142
+ // Map to your User domain model
143
+ const user = new User(profile.email || '', profile.id || '', profile.firstName || '', profile.lastName || '');
144
+ this._user.set(user);
145
+ }
146
+ else {
147
+ this._user.set(undefined);
148
+ }
149
+ }
150
+ }
151
+
152
+ class FirebaseAuthService extends AuthService {
153
+ auth;
154
+ constructor(auth) {
155
+ super();
156
+ this.auth = auth;
157
+ }
158
+ // region public accessors and mutator methods
159
+ authenticate() {
160
+ return Promise.resolve(this.auth.currentUser !== null);
161
+ }
162
+ async login(redirectUrl, email, password) {
163
+ if (email != null && password != null) {
164
+ const userCredential = await signInWithEmailAndPassword(this.auth, email, password);
165
+ const user = new User(userCredential.user.email, userCredential.user.uid, userCredential.user.displayName);
166
+ this._user.set(user);
167
+ return user;
168
+ }
169
+ else
170
+ return undefined;
171
+ }
172
+ logout() {
173
+ return this.auth.signOut();
174
+ }
175
+ getCurrentUser() {
176
+ const currentUser = this.auth.currentUser;
177
+ return new User(currentUser?.email, currentUser?.uid, currentUser?.displayName);
178
+ }
179
+ }
180
+
181
+ function provideFirebaseAuthService(baseConfig, authConfig) {
182
+ const auth = getAuth();
183
+ const pipelineStage = baseConfig.PIPELINE_STAGE ?? 'ci';
184
+ if ((pipelineStage === 'dev' || pipelineStage === 'ci') && authConfig.AUTHENTICATION_SERVICE_ROOT) {
185
+ connectAuthEmulator(auth, authConfig.AUTHENTICATION_SERVICE_ROOT);
186
+ }
187
+ return new FirebaseAuthService(auth);
188
+ }
189
+
190
+ const AUTHENTICATION_CONFIGURATION = new InjectionToken('AUTHENTICATION_CONFIGURATION');
191
+ const AUTHENTICATION_SERVICE = new InjectionToken('AUTHENTICATION_SERVICE');
192
+ function provideAuthenticationService() {
193
+ return makeEnvironmentProviders([
194
+ {
195
+ provide: AUTHENTICATION_SERVICE,
196
+ useFactory: () => {
197
+ const runtimeConfig = inject(RUNTIME_CONFIGURATION);
198
+ const baseConfig = runtimeConfig['BASE_CONFIGURATION'];
199
+ const authConfig = runtimeConfig['AUTHENTICATION_CONFIGURATION'];
200
+ if (authConfig.AUTHENTICATION_PROVIDER === 'keycloak' && authConfig.AUTH_SERVICE_CONFIG) {
201
+ return new KeycloakAuthService(authConfig.AUTH_SERVICE_CONFIG);
202
+ }
203
+ else if (authConfig.AUTHENTICATION_PROVIDER === 'firebase-auth') {
204
+ return provideFirebaseAuthService(baseConfig, authConfig);
205
+ }
206
+ else {
207
+ throw new Error('No AUTHENTICATION_PROVIDER or AUTH_SERVICE_CONFIG configured. Verify your RUNTIME_CONFIGURATION.');
208
+ }
209
+ },
210
+ deps: [RUNTIME_CONFIGURATION],
211
+ },
212
+ ]);
213
+ }
214
+
215
+ /**
216
+ * Generated bundle index. Do not edit.
217
+ */
218
+
219
+ export { AUTHENTICATION_CONFIGURATION, AUTHENTICATION_SERVICE, AuthService, User, authMatcher, provideAuthenticationService };
220
+ //# sourceMappingURL=processpuzzle-auth-domain.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processpuzzle-auth-domain.mjs","sources":["../../../../libs/auth/domain/auth-matcher.ts","../../../../libs/auth/domain/service/auth.service.ts","../../../../libs/auth/domain/user/user.ts","../../../../libs/auth/domain/service/keycloak-auth.service.ts","../../../../libs/auth/domain/service/firebase-auth.service.ts","../../../../libs/auth/domain/service/provide-firebase-auth-service.ts","../../../../libs/auth/domain/service/provide-authentication.service.ts","../../../../libs/auth/domain/processpuzzle-auth-domain.ts"],"sourcesContent":["import { UrlSegment } from '@angular/router';\n\n// Custom matcher function to match any URL containing 'auth'\nexport function authMatcher(segments: UrlSegment[]) {\n const hasAuth = segments.some((segment) => segment.path === 'auth');\n if (hasAuth) {\n // Find the index of 'auth' segment\n const authIndex = segments.findIndex((segment) => segment.path === 'auth');\n // Return consumed segments up to and including 'auth'\n return {\n consumed: segments.slice(0, authIndex + 1),\n posParams: {},\n };\n }\n return null;\n}\n","import { computed, Injectable, signal, Signal, WritableSignal } from '@angular/core';\nimport { User } from '../user/user';\n\n@Injectable({\n providedIn: 'root',\n})\nexport abstract class AuthService {\n protected _user: WritableSignal<User | undefined> = signal<User | undefined>(undefined);\n protected readonly user: Signal<User | undefined> = this._user.asReadonly();\n isAuthenticated: Signal<boolean | undefined> = computed(() => (this.user ? !!this.user() : undefined));\n\n abstract authenticate(): Promise<boolean>;\n\n abstract login(redirectUrl?: string, email?: string, password?: string): Promise<User | undefined>;\n\n abstract logout(redirectUrl?: string): Promise<void>;\n\n abstract getCurrentUser(): User | undefined;\n\n // region protected, private helper methods\n protected throwError(message: string) {\n throw new Error(message);\n }\n // endregion\n}\n","import { BaseEntity } from '@processpuzzle/base-entity';\nimport { v4 as uuidv4 } from 'uuid';\n\nexport class User implements BaseEntity {\n readonly id: string;\n private _email: string | null | undefined;\n private _password: string | null | undefined;\n private _firstName: string | undefined;\n private _lastName: string | undefined;\n private _photoUrl: string | undefined;\n\n constructor(email?: string | null, id?: string, firstName?: string | null, lastName?: string | null, photoUrl?: string | null) {\n this._email = email;\n this.id = id ?? uuidv4();\n this.firstName = firstName ?? '';\n this.lastName = lastName ?? '';\n this.photoUrl = photoUrl ?? '';\n }\n\n // region properties\n public get email(): string | null | undefined {\n return this._email;\n }\n\n public set email(email: string) {\n this._email = email;\n }\n\n public get firstName(): string | undefined {\n return this._firstName;\n }\n\n public set firstName(firstName: string) {\n this._firstName = firstName;\n }\n\n public get lastName(): string | undefined {\n return this._lastName;\n }\n\n public set lastName(lastName: string) {\n this._lastName = lastName;\n }\n\n public get password(): string | null | undefined {\n return this._password;\n }\n\n public set password(password: string) {\n this._password = password;\n }\n\n public get photoUrl(): string | undefined {\n return this._photoUrl;\n }\n\n public set photoUrl(url: string) {\n this._photoUrl = url;\n }\n\n // endregion\n}\n","import { AuthService } from './auth.service';\nimport { User } from '../user/user';\nimport Keycloak from 'keycloak-js';\nimport { KeycloakAuthConfig } from './keycloak-auth.config';\n\nexport class KeycloakAuthService extends AuthService {\n readonly keycloak: Keycloak;\n private initPromise: Promise<void> | null = null;\n\n constructor(protected config: KeycloakAuthConfig) {\n super();\n this.keycloak = new Keycloak({\n clientId: config.clientId,\n realm: config.realm,\n url: config.authServerUrl,\n });\n }\n\n // region public accessors and mutators\n override async authenticate(): Promise<boolean> {\n await this.ensureInitialized();\n return !!this.getCurrentUser();\n }\n\n async login(redirectUrl?: string): Promise<User> {\n await this.ensureInitialized();\n if (this.isAuthenticated()) return this.user() as User;\n else {\n await this.keycloak.login({ redirectUri: globalThis.location.origin + '/' + redirectUrl });\n return this.getCurrentUser() as User;\n }\n }\n\n override async logout(redirectUrl?: string): Promise<void> {\n await this.keycloak.logout({ redirectUri: globalThis.location.origin + '/' + redirectUrl });\n this._user.set(undefined);\n }\n\n override getCurrentUser(): User | undefined {\n return this.user();\n }\n\n getUsername(): string {\n return this.keycloak.profile?.username || '';\n }\n\n getUserRoles(): string[] {\n return this.keycloak.realmAccess?.roles || [];\n }\n // endregion\n\n // region protected, private helper methods\n private ensureInitialized(): Promise<void> {\n this.initPromise ??= this.initKeycloak();\n return this.initPromise;\n }\n\n private async initKeycloak() {\n await this.keycloak.init({\n onLoad: 'check-sso',\n silentCheckSsoRedirectUri: 'http://localhost:4200/assets/auth/silent-check-sso.html',\n });\n\n // Check if authenticated using the keycloak-js instance directly\n if (this.keycloak.authenticated) {\n const profile = await this.keycloak.loadUserProfile();\n\n // Map to your User domain model\n const user = new User(profile.email || '', profile.id || '', profile.firstName || '', profile.lastName || '');\n\n this._user.set(user);\n } else {\n this._user.set(undefined);\n }\n }\n // endregion\n}\n","import { AuthService } from './auth.service';\nimport { Auth, signInWithEmailAndPassword } from '@angular/fire/auth';\nimport { User } from '../user/user';\n\nexport class FirebaseAuthService extends AuthService {\n private readonly auth: Auth;\n\n constructor(auth: Auth) {\n super();\n this.auth = auth;\n }\n\n // region public accessors and mutator methods\n override authenticate(): Promise<boolean> {\n return Promise.resolve(this.auth.currentUser !== null);\n }\n\n public async login(redirectUrl?: string, email?: string, password?: string): Promise<User | undefined> {\n if (email != null && password != null) {\n const userCredential = await signInWithEmailAndPassword(this.auth, email, password);\n const user = new User(userCredential.user.email, userCredential.user.uid, userCredential.user.displayName);\n this._user.set(user);\n return user;\n } else return undefined;\n }\n\n override logout(): Promise<void> {\n return this.auth.signOut();\n }\n\n getCurrentUser(): User | undefined {\n const currentUser = this.auth.currentUser;\n return new User(currentUser?.email, currentUser?.uid, currentUser?.displayName);\n }\n // endregion\n}\n","import { connectAuthEmulator, getAuth } from '@angular/fire/auth';\nimport { FirebaseAuthService } from './firebase-auth.service';\nimport { BaseConfiguration } from '@processpuzzle/util';\nimport { AuthenticationConfiguration } from './provide-authentication.service';\n\nexport function provideFirebaseAuthService(baseConfig: BaseConfiguration, authConfig: AuthenticationConfiguration): FirebaseAuthService {\n const auth = getAuth();\n const pipelineStage = baseConfig.PIPELINE_STAGE ?? 'ci';\n if ((pipelineStage === 'dev' || pipelineStage === 'ci') && authConfig.AUTHENTICATION_SERVICE_ROOT) {\n connectAuthEmulator(auth, authConfig.AUTHENTICATION_SERVICE_ROOT);\n }\n return new FirebaseAuthService(auth);\n}\n","import { EnvironmentProviders, inject, InjectionToken, makeEnvironmentProviders } from '@angular/core';\nimport { KeycloakAuthConfig } from './keycloak-auth.config';\nimport { AuthService } from './auth.service';\nimport { FirebaseAuthConfig } from './firebase-auth.config';\nimport { BaseConfiguration, RUNTIME_CONFIGURATION } from '@processpuzzle/util';\nimport { KeycloakAuthService } from './keycloak-auth.service';\nimport { provideFirebaseAuthService } from './provide-firebase-auth-service';\n\nexport const AUTHENTICATION_CONFIGURATION = new InjectionToken<AuthenticationConfiguration>('AUTHENTICATION_CONFIGURATION');\nexport const AUTHENTICATION_SERVICE = new InjectionToken<AuthService>('AUTHENTICATION_SERVICE');\n\nexport interface AuthenticationConfiguration {\n readonly AUTHENTICATION_PROVIDER?: 'local-auth' | 'firebase-auth' | 'oauth2' | 'keycloak';\n readonly AUTHENTICATION_SERVICE_ROOT?: string;\n readonly AUTH_SERVICE_CONFIG?: KeycloakAuthConfig | FirebaseAuthConfig;\n}\n\nexport function provideAuthenticationService(): EnvironmentProviders {\n return makeEnvironmentProviders([\n {\n provide: AUTHENTICATION_SERVICE,\n useFactory: () => {\n const runtimeConfig = inject(RUNTIME_CONFIGURATION);\n const baseConfig: BaseConfiguration = runtimeConfig['BASE_CONFIGURATION' as keyof typeof runtimeConfig];\n const authConfig: AuthenticationConfiguration = runtimeConfig['AUTHENTICATION_CONFIGURATION' as keyof typeof runtimeConfig];\n if (authConfig.AUTHENTICATION_PROVIDER === 'keycloak' && authConfig.AUTH_SERVICE_CONFIG) {\n return new KeycloakAuthService(authConfig.AUTH_SERVICE_CONFIG as KeycloakAuthConfig);\n } else if (authConfig.AUTHENTICATION_PROVIDER === 'firebase-auth') {\n return provideFirebaseAuthService(baseConfig, authConfig);\n } else {\n throw new Error('No AUTHENTICATION_PROVIDER or AUTH_SERVICE_CONFIG configured. Verify your RUNTIME_CONFIGURATION.');\n }\n },\n deps: [RUNTIME_CONFIGURATION],\n },\n ]);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["uuidv4"],"mappings":"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"}