@memberjunction/ng-auth-services 6.1.0-edge.2 → 6.1.0-edge.4

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.
Files changed (30) hide show
  1. package/LICENSE +180 -4
  2. package/README.md +58 -1
  3. package/dist/lib/auth-provider-catalog.d.ts +103 -0
  4. package/dist/lib/auth-provider-catalog.d.ts.map +1 -0
  5. package/dist/lib/auth-provider-catalog.js +186 -0
  6. package/dist/lib/auth-provider-catalog.js.map +1 -0
  7. package/dist/lib/auth-services.module.d.ts +33 -3
  8. package/dist/lib/auth-services.module.d.ts.map +1 -1
  9. package/dist/lib/auth-services.module.js +64 -18
  10. package/dist/lib/auth-services.module.js.map +1 -1
  11. package/dist/lib/catalog-environment.d.ts +50 -0
  12. package/dist/lib/catalog-environment.d.ts.map +1 -0
  13. package/dist/lib/catalog-environment.js +87 -0
  14. package/dist/lib/catalog-environment.js.map +1 -0
  15. package/dist/lib/login-picker.component.d.ts +72 -0
  16. package/dist/lib/login-picker.component.d.ts.map +1 -0
  17. package/dist/lib/login-picker.component.js +284 -0
  18. package/dist/lib/login-picker.component.js.map +1 -0
  19. package/dist/lib/providers/mjexplorer-cognito-provider.service.d.ts.map +1 -1
  20. package/dist/lib/providers/mjexplorer-cognito-provider.service.js +4 -1
  21. package/dist/lib/providers/mjexplorer-cognito-provider.service.js.map +1 -1
  22. package/dist/lib/providers/mjexplorer-msal-provider.service.d.ts +16 -0
  23. package/dist/lib/providers/mjexplorer-msal-provider.service.d.ts.map +1 -1
  24. package/dist/lib/providers/mjexplorer-msal-provider.service.js +28 -0
  25. package/dist/lib/providers/mjexplorer-msal-provider.service.js.map +1 -1
  26. package/dist/public-api.d.ts +3 -0
  27. package/dist/public-api.d.ts.map +1 -1
  28. package/dist/public-api.js +4 -0
  29. package/dist/public-api.js.map +1 -1
  30. package/package.json +7 -6
@@ -1,47 +1,93 @@
1
- import { NgModule } from '@angular/core';
1
+ import { NgModule, InjectionToken } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import { MJAuthBase } from './mjexplorer-auth-base.service';
4
4
  import { AngularAuthProviderFactory } from './AngularAuthProviderFactory';
5
5
  import { MJMagicLinkProvider } from './providers/mjexplorer-magic-link-provider.service';
6
6
  import { MJGlobal } from '@memberjunction/global';
7
+ import { AuthProviderCatalog } from './auth-provider-catalog';
8
+ import { mergeCatalogEnvironment } from './catalog-environment';
9
+ import { MJLoginPickerComponent } from './login-picker.component';
7
10
  // Import our generic redirect component
8
11
  import { RedirectComponent } from './redirect.component';
9
12
  import * as i0 from "@angular/core";
10
13
  // Export the generic redirect component for backward compatibility
11
14
  export { RedirectComponent };
15
+ /**
16
+ * Injection token carrying how authentication resolved for this page load.
17
+ *
18
+ * A login surface injects this to decide whether to render the multi-provider picker or the
19
+ * single sign-in button, and whether to start the login flow immediately after a picker
20
+ * choice caused a reload.
21
+ */
22
+ export const MJ_AUTH_PROVIDER_RESOLUTION = new InjectionToken('MJ_AUTH_PROVIDER_RESOLUTION');
23
+ /** The resolution used when no catalog is supplied — i.e. the pre-existing single-provider path. */
24
+ const NO_CATALOG_RESOLUTION = { active: null, choices: [], showPicker: false, autoLogin: false };
12
25
  /**
13
26
  * Extensible authentication module that supports N providers
14
27
  * Uses MJGlobal ClassFactory pattern for dynamic provider creation
15
28
  */
16
29
  export class AuthServicesModule {
17
- static forRoot(environment) {
30
+ /**
31
+ * Wires the authentication provider into DI.
32
+ *
33
+ * @param environment The app's compiled environment. Typed loosely on purpose: every app
34
+ * declares its own environment shape (`MJEnvironmentConfig` and downstream equivalents
35
+ * are interfaces, which TypeScript will not assign to an indexed record), so narrowing
36
+ * this parameter would break every existing caller. It is narrowed once, below.
37
+ * @param catalog Optional pre-auth provider catalog. Defaults to whatever the app preloaded
38
+ * via {@link AuthProviderCatalog.Preload} in its bootstrap entry point — passing it
39
+ * explicitly is for tests and for apps that source the catalog some other way. Callers
40
+ * must NOT pass `AuthProviderCatalog.GetPreloaded()` themselves: Angular's compiler
41
+ * requires every `imports` entry to be statically analyzable, and a function call in
42
+ * the argument list fails AOT with "Value could not be determined statically".
43
+ *
44
+ * When the catalog is empty — an older server, a failed fetch, or a deployment that
45
+ * never adopted the entity — resolution falls back to `environment.AUTH_TYPE` and
46
+ * behaviour is byte-for-byte what it was before the catalog existed, which is what
47
+ * keeps every existing deployment working untouched.
48
+ */
49
+ static forRoot(environment, catalog) {
50
+ const env = environment;
18
51
  const providers = [];
19
- const configuredType = environment.AUTH_TYPE?.toLowerCase();
52
+ const configuredType = env['AUTH_TYPE']?.toLowerCase();
53
+ const resolvedCatalog = catalog ?? AuthProviderCatalog.GetPreloaded();
20
54
  // Coexistence resolution: a single Explorer deployment can serve both SSO
21
55
  // users and magic-link guests. If a magic-link session token is present for
22
56
  // this page load (URL fragment from /redeem, or stored earlier this tab), use
23
57
  // the magic-link provider regardless of the configured primary IdP. Otherwise
24
- // use the configured AUTH_TYPE. This auto-falls-back to the IdP once a guest's
25
- // token is gone (expired/logged out), so the normal login button works again.
58
+ // use the catalog selection, then the configured AUTH_TYPE. This auto-falls-back
59
+ // to the IdP once a guest's token is gone (expired/logged out), so the normal
60
+ // login button works again.
26
61
  const magicLinkActive = MJMagicLinkProvider.hasSessionToken();
27
- const authType = magicLinkActive ? MJMagicLinkProvider.PROVIDER_TYPE : configuredType;
62
+ // The catalog resolves which provider this load uses; it never overrides an active
63
+ // magic-link session, which is a property of THIS page load rather than a configured choice.
64
+ const resolution = resolvedCatalog.length ? AuthProviderCatalog.Resolve(resolvedCatalog) : NO_CATALOG_RESOLUTION;
65
+ providers.push({ provide: MJ_AUTH_PROVIDER_RESOLUTION, useValue: resolution });
66
+ const catalogType = resolution.active?.driverClass?.toLowerCase();
67
+ const authType = magicLinkActive ? MJMagicLinkProvider.PROVIDER_TYPE : (catalogType ?? configuredType);
28
68
  if (!authType) {
29
- console.error('No AUTH_TYPE specified in environment');
69
+ console.error('No authentication provider available: the server published no catalog and no AUTH_TYPE is set in the environment');
30
70
  return {
31
71
  ngModule: AuthServicesModule,
32
- providers: []
72
+ providers: providers
33
73
  };
34
74
  }
35
- if (magicLinkActive && authType !== configuredType) {
36
- console.log(`[Auth] Magic-link session token detected — using the magic-link provider for this load (configured primary: '${configuredType ?? 'none'}').`);
75
+ if (magicLinkActive && authType !== (catalogType ?? configuredType)) {
76
+ console.log(`[Auth] Magic-link session token detected — using the magic-link provider for this load (configured primary: '${catalogType ?? configuredType ?? 'none'}').`);
37
77
  }
38
- // Use the factory to get provider-specific Angular services
39
- // This uses the static method on each provider class for extensibility
40
- const angularServices = AngularAuthProviderFactory.getProviderAngularServices(authType, environment);
41
- providers.push(...angularServices);
42
78
  // Get the provider class from ClassFactory for extensibility
43
79
  const registration = MJGlobal.Instance.ClassFactory.GetRegistration(MJAuthBase, authType);
44
80
  const providerClass = registration?.SubClass;
81
+ // A catalog-selected provider takes its settings from metadata rather than from the compiled
82
+ // environment, so the driver receives the row's values overlaid on the app's environment.
83
+ // Magic-link is excluded: its session is established by the redeem flow, not by catalog config.
84
+ const effectiveEnvironment = resolution.active && !magicLinkActive
85
+ ? mergeCatalogEnvironment(environment, resolution.active, providerClass)
86
+ : environment;
87
+ // Use the factory to get provider-specific Angular services
88
+ // This uses the static method on each provider class for extensibility
89
+ const angularServices = AngularAuthProviderFactory.getProviderAngularServices(authType, effectiveEnvironment);
90
+ providers.push(...angularServices);
45
91
  if (providerClass) {
46
92
  // Add the provider itself
47
93
  providers.push({
@@ -56,7 +102,7 @@ export class AuthServicesModule {
56
102
  providers.push(AngularAuthProviderFactory);
57
103
  return {
58
104
  ngModule: AuthServicesModule,
59
- providers
105
+ providers: providers
60
106
  };
61
107
  }
62
108
  static ɵfac = function AuthServicesModule_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AuthServicesModule)(); };
@@ -66,10 +112,10 @@ export class AuthServicesModule {
66
112
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AuthServicesModule, [{
67
113
  type: NgModule,
68
114
  args: [{
69
- imports: [CommonModule],
115
+ imports: [CommonModule, MJLoginPickerComponent],
70
116
  declarations: [RedirectComponent],
71
- exports: [RedirectComponent]
117
+ exports: [RedirectComponent, MJLoginPickerComponent]
72
118
  }]
73
119
  }], null, null); })();
74
- (function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(AuthServicesModule, { declarations: [RedirectComponent], imports: [CommonModule], exports: [RedirectComponent] }); })();
120
+ (function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(AuthServicesModule, { declarations: [RedirectComponent], imports: [CommonModule, MJLoginPickerComponent], exports: [RedirectComponent, MJLoginPickerComponent] }); })();
75
121
  //# sourceMappingURL=auth-services.module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-services.module.js","sourceRoot":"","sources":["../../src/lib/auth-services.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAuB,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,oDAAoD,CAAC;AACzF,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,wCAAwC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;;AAEzD,mEAAmE;AACnE,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAE7B;;;GAGG;AAMH,MAAM,OAAO,kBAAkB;IAC7B,MAAM,CAAC,OAAO,CAAC,WAAgB;QAE7B,MAAM,SAAS,GAAU,EAAE,CAAC;QAC5B,MAAM,cAAc,GAAG,WAAW,CAAC,SAAS,EAAE,WAAW,EAAE,CAAC;QAE5D,0EAA0E;QAC1E,4EAA4E;QAC5E,8EAA8E;QAC9E,8EAA8E;QAC9E,+EAA+E;QAC/E,8EAA8E;QAC9E,MAAM,eAAe,GAAG,mBAAmB,CAAC,eAAe,EAAE,CAAC;QAC9D,MAAM,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC;QAEtF,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;YACvD,OAAO;gBACL,QAAQ,EAAE,kBAAkB;gBAC5B,SAAS,EAAE,EAAE;aACd,CAAC;QACJ,CAAC;QAED,IAAI,eAAe,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,gHAAgH,cAAc,IAAI,MAAM,KAAK,CAAC,CAAC;QAC7J,CAAC;QAED,4DAA4D;QAC5D,uEAAuE;QACvE,MAAM,eAAe,GAAG,0BAA0B,CAAC,0BAA0B,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QACrG,SAAS,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC;QAEnC,6DAA6D;QAC7D,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,eAAe,CACjE,UAAU,EACV,QAAQ,CACT,CAAC;QACF,MAAM,aAAa,GAAG,YAAY,EAAE,QAAQ,CAAC;QAE7C,IAAI,aAAa,EAAE,CAAC;YAClB,0BAA0B;YAC1B,SAAS,CAAC,IAAI,CAAC;gBACb,OAAO,EAAE,UAAU;gBACnB,QAAQ,EAAE,aAAa;aACxB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,+CAA+C,QAAQ,EAAE,CAAC,CAAC;QAC3E,CAAC;QAED,yBAAyB;QACzB,SAAS,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAE3C,OAAO;YACL,QAAQ,EAAE,kBAAkB;YAC5B,SAAS;SACV,CAAC;IACJ,CAAC;4GAxDU,kBAAkB;4DAAlB,kBAAkB;gEAJnB,YAAY;;iFAIX,kBAAkB;cAL9B,QAAQ;eAAC;gBACR,OAAO,EAAE,CAAC,YAAY,CAAC;gBACvB,YAAY,EAAE,CAAC,iBAAiB,CAAC;gBACjC,OAAO,EAAE,CAAC,iBAAiB,CAAC;aAC7B;;wFACY,kBAAkB,mBAHd,iBAAiB,aADtB,YAAY,aAEZ,iBAAiB","sourcesContent":["import { NgModule, ModuleWithProviders } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { MJAuthBase } from './mjexplorer-auth-base.service';\nimport { AngularAuthProviderFactory } from './AngularAuthProviderFactory';\nimport { MJMagicLinkProvider } from './providers/mjexplorer-magic-link-provider.service';\nimport { MJGlobal } from '@memberjunction/global';\n\n// Import our generic redirect component\nimport { RedirectComponent } from './redirect.component';\n\n// Export the generic redirect component for backward compatibility\nexport { RedirectComponent };\n\n/**\n * Extensible authentication module that supports N providers\n * Uses MJGlobal ClassFactory pattern for dynamic provider creation\n */\n@NgModule({\n imports: [CommonModule],\n declarations: [RedirectComponent],\n exports: [RedirectComponent]\n})\nexport class AuthServicesModule {\n static forRoot(environment: any): ModuleWithProviders<AuthServicesModule> {\n\n const providers: any[] = [];\n const configuredType = environment.AUTH_TYPE?.toLowerCase();\n\n // Coexistence resolution: a single Explorer deployment can serve both SSO\n // users and magic-link guests. If a magic-link session token is present for\n // this page load (URL fragment from /redeem, or stored earlier this tab), use\n // the magic-link provider regardless of the configured primary IdP. Otherwise\n // use the configured AUTH_TYPE. This auto-falls-back to the IdP once a guest's\n // token is gone (expired/logged out), so the normal login button works again.\n const magicLinkActive = MJMagicLinkProvider.hasSessionToken();\n const authType = magicLinkActive ? MJMagicLinkProvider.PROVIDER_TYPE : configuredType;\n\n if (!authType) {\n console.error('No AUTH_TYPE specified in environment');\n return {\n ngModule: AuthServicesModule,\n providers: []\n };\n }\n\n if (magicLinkActive && authType !== configuredType) {\n console.log(`[Auth] Magic-link session token detected — using the magic-link provider for this load (configured primary: '${configuredType ?? 'none'}').`);\n }\n\n // Use the factory to get provider-specific Angular services\n // This uses the static method on each provider class for extensibility\n const angularServices = AngularAuthProviderFactory.getProviderAngularServices(authType, environment);\n providers.push(...angularServices);\n\n // Get the provider class from ClassFactory for extensibility\n const registration = MJGlobal.Instance.ClassFactory.GetRegistration(\n MJAuthBase,\n authType\n );\n const providerClass = registration?.SubClass;\n\n if (providerClass) {\n // Add the provider itself\n providers.push({\n provide: MJAuthBase,\n useClass: providerClass\n });\n } else {\n console.error(`No provider class registered for auth type: ${authType}`);\n }\n\n // Add the factory itself\n providers.push(AngularAuthProviderFactory);\n\n return {\n ngModule: AuthServicesModule,\n providers\n };\n }\n}\n"]}
1
+ {"version":3,"file":"auth-services.module.js","sourceRoot":"","sources":["../../src/lib/auth-services.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAuB,cAAc,EAAY,MAAM,eAAe,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,oDAAoD,CAAC;AACzF,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,OAAO,EAAE,mBAAmB,EAA+B,MAAM,yBAAyB,CAAC;AAC3F,OAAO,EAAE,uBAAuB,EAAiC,MAAM,uBAAuB,CAAC;AAC/F,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,wCAAwC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;;AAEzD,mEAAmE;AACnE,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAE7B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,IAAI,cAAc,CAAyB,6BAA6B,CAAC,CAAC;AAErH,oGAAoG;AACpG,MAAM,qBAAqB,GAA2B,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAEzH;;;GAGG;AAMH,MAAM,OAAO,kBAAkB;IAC7B;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,OAAO,CAAC,WAAgB,EAAE,OAAkC;QACjE,MAAM,GAAG,GAAG,WAAsC,CAAC;QACnD,MAAM,SAAS,GAAe,EAAE,CAAC;QACjC,MAAM,cAAc,GAAI,GAAG,CAAC,WAAW,CAAwB,EAAE,WAAW,EAAE,CAAC;QAC/E,MAAM,eAAe,GAAG,OAAO,IAAI,mBAAmB,CAAC,YAAY,EAAE,CAAC;QAEtE,0EAA0E;QAC1E,4EAA4E;QAC5E,8EAA8E;QAC9E,8EAA8E;QAC9E,iFAAiF;QACjF,8EAA8E;QAC9E,4BAA4B;QAC5B,MAAM,eAAe,GAAG,mBAAmB,CAAC,eAAe,EAAE,CAAC;QAE9D,mFAAmF;QACnF,6FAA6F;QAC7F,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC;QACjH,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,2BAA2B,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;QAE/E,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;QAClE,MAAM,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,WAAW,IAAI,cAAc,CAAC,CAAC;QAEvG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,kHAAkH,CAAC,CAAC;YAClI,OAAO;gBACL,QAAQ,EAAE,kBAAkB;gBAC5B,SAAS,EAAE,SAAoB;aAChC,CAAC;QACJ,CAAC;QAED,IAAI,eAAe,IAAI,QAAQ,KAAK,CAAC,WAAW,IAAI,cAAc,CAAC,EAAE,CAAC;YACpE,OAAO,CAAC,GAAG,CAAC,gHAAgH,WAAW,IAAI,cAAc,IAAI,MAAM,KAAK,CAAC,CAAC;QAC5K,CAAC;QAED,6DAA6D;QAC7D,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,eAAe,CACjE,UAAU,EACV,QAAQ,CACT,CAAC;QACF,MAAM,aAAa,GAAG,YAAY,EAAE,QAAQ,CAAC;QAE7C,6FAA6F;QAC7F,0FAA0F;QAC1F,gGAAgG;QAChG,MAAM,oBAAoB,GACxB,UAAU,CAAC,MAAM,IAAI,CAAC,eAAe;YACnC,CAAC,CAAC,uBAAuB,CAAC,WAAW,EAAE,UAAU,CAAC,MAAM,EAAE,aAAqD,CAAC;YAChH,CAAC,CAAC,WAAW,CAAC;QAElB,4DAA4D;QAC5D,uEAAuE;QACvE,MAAM,eAAe,GAAG,0BAA0B,CAAC,0BAA0B,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;QAC9G,SAAS,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC;QAEnC,IAAI,aAAa,EAAE,CAAC;YAClB,0BAA0B;YAC1B,SAAS,CAAC,IAAI,CAAC;gBACb,OAAO,EAAE,UAAU;gBACnB,QAAQ,EAAE,aAAa;aACxB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,+CAA+C,QAAQ,EAAE,CAAC,CAAC;QAC3E,CAAC;QAED,yBAAyB;QACzB,SAAS,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAE3C,OAAO;YACL,QAAQ,EAAE,kBAAkB;YAC5B,SAAS,EAAE,SAAoB;SAChC,CAAC;IACJ,CAAC;4GA5FU,kBAAkB;4DAAlB,kBAAkB;gEAJnB,YAAY;;iFAIX,kBAAkB;cAL9B,QAAQ;eAAC;gBACR,OAAO,EAAE,CAAC,YAAY,EAAE,sBAAsB,CAAC;gBAC/C,YAAY,EAAE,CAAC,iBAAiB,CAAC;gBACjC,OAAO,EAAE,CAAC,iBAAiB,EAAE,sBAAsB,CAAC;aACrD;;wFACY,kBAAkB,mBAHd,iBAAiB,aADtB,YAAY,EAAE,sBAAsB,aAEpC,iBAAiB,EAAE,sBAAsB","sourcesContent":["import { NgModule, ModuleWithProviders, InjectionToken, Provider } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { MJAuthBase } from './mjexplorer-auth-base.service';\nimport { AngularAuthProviderFactory } from './AngularAuthProviderFactory';\nimport { MJMagicLinkProvider } from './providers/mjexplorer-magic-link-provider.service';\nimport { MJGlobal } from '@memberjunction/global';\nimport type { PublicAuthProviderInfo } from '@memberjunction/core';\nimport { AuthProviderCatalog, type AuthProviderResolution } from './auth-provider-catalog';\nimport { mergeCatalogEnvironment, type CatalogEnvironmentMapper } from './catalog-environment';\nimport { MJLoginPickerComponent } from './login-picker.component';\n\n// Import our generic redirect component\nimport { RedirectComponent } from './redirect.component';\n\n// Export the generic redirect component for backward compatibility\nexport { RedirectComponent };\n\n/**\n * Injection token carrying how authentication resolved for this page load.\n *\n * A login surface injects this to decide whether to render the multi-provider picker or the\n * single sign-in button, and whether to start the login flow immediately after a picker\n * choice caused a reload.\n */\nexport const MJ_AUTH_PROVIDER_RESOLUTION = new InjectionToken<AuthProviderResolution>('MJ_AUTH_PROVIDER_RESOLUTION');\n\n/** The resolution used when no catalog is supplied — i.e. the pre-existing single-provider path. */\nconst NO_CATALOG_RESOLUTION: AuthProviderResolution = { active: null, choices: [], showPicker: false, autoLogin: false };\n\n/**\n * Extensible authentication module that supports N providers\n * Uses MJGlobal ClassFactory pattern for dynamic provider creation\n */\n@NgModule({\n imports: [CommonModule, MJLoginPickerComponent],\n declarations: [RedirectComponent],\n exports: [RedirectComponent, MJLoginPickerComponent]\n})\nexport class AuthServicesModule {\n /**\n * Wires the authentication provider into DI.\n *\n * @param environment The app's compiled environment. Typed loosely on purpose: every app\n * declares its own environment shape (`MJEnvironmentConfig` and downstream equivalents\n * are interfaces, which TypeScript will not assign to an indexed record), so narrowing\n * this parameter would break every existing caller. It is narrowed once, below.\n * @param catalog Optional pre-auth provider catalog. Defaults to whatever the app preloaded\n * via {@link AuthProviderCatalog.Preload} in its bootstrap entry point — passing it\n * explicitly is for tests and for apps that source the catalog some other way. Callers\n * must NOT pass `AuthProviderCatalog.GetPreloaded()` themselves: Angular's compiler\n * requires every `imports` entry to be statically analyzable, and a function call in\n * the argument list fails AOT with \"Value could not be determined statically\".\n *\n * When the catalog is empty — an older server, a failed fetch, or a deployment that\n * never adopted the entity — resolution falls back to `environment.AUTH_TYPE` and\n * behaviour is byte-for-byte what it was before the catalog existed, which is what\n * keeps every existing deployment working untouched.\n */\n static forRoot(environment: any, catalog?: PublicAuthProviderInfo[]): ModuleWithProviders<AuthServicesModule> {\n const env = environment as Record<string, unknown>;\n const providers: Provider[] = [];\n const configuredType = (env['AUTH_TYPE'] as string | undefined)?.toLowerCase();\n const resolvedCatalog = catalog ?? AuthProviderCatalog.GetPreloaded();\n\n // Coexistence resolution: a single Explorer deployment can serve both SSO\n // users and magic-link guests. If a magic-link session token is present for\n // this page load (URL fragment from /redeem, or stored earlier this tab), use\n // the magic-link provider regardless of the configured primary IdP. Otherwise\n // use the catalog selection, then the configured AUTH_TYPE. This auto-falls-back\n // to the IdP once a guest's token is gone (expired/logged out), so the normal\n // login button works again.\n const magicLinkActive = MJMagicLinkProvider.hasSessionToken();\n\n // The catalog resolves which provider this load uses; it never overrides an active\n // magic-link session, which is a property of THIS page load rather than a configured choice.\n const resolution = resolvedCatalog.length ? AuthProviderCatalog.Resolve(resolvedCatalog) : NO_CATALOG_RESOLUTION;\n providers.push({ provide: MJ_AUTH_PROVIDER_RESOLUTION, useValue: resolution });\n\n const catalogType = resolution.active?.driverClass?.toLowerCase();\n const authType = magicLinkActive ? MJMagicLinkProvider.PROVIDER_TYPE : (catalogType ?? configuredType);\n\n if (!authType) {\n console.error('No authentication provider available: the server published no catalog and no AUTH_TYPE is set in the environment');\n return {\n ngModule: AuthServicesModule,\n providers: providers as never[]\n };\n }\n\n if (magicLinkActive && authType !== (catalogType ?? configuredType)) {\n console.log(`[Auth] Magic-link session token detected — using the magic-link provider for this load (configured primary: '${catalogType ?? configuredType ?? 'none'}').`);\n }\n\n // Get the provider class from ClassFactory for extensibility\n const registration = MJGlobal.Instance.ClassFactory.GetRegistration(\n MJAuthBase,\n authType\n );\n const providerClass = registration?.SubClass;\n\n // A catalog-selected provider takes its settings from metadata rather than from the compiled\n // environment, so the driver receives the row's values overlaid on the app's environment.\n // Magic-link is excluded: its session is established by the redeem flow, not by catalog config.\n const effectiveEnvironment =\n resolution.active && !magicLinkActive\n ? mergeCatalogEnvironment(environment, resolution.active, providerClass as CatalogEnvironmentMapper | undefined)\n : environment;\n\n // Use the factory to get provider-specific Angular services\n // This uses the static method on each provider class for extensibility\n const angularServices = AngularAuthProviderFactory.getProviderAngularServices(authType, effectiveEnvironment);\n providers.push(...angularServices);\n\n if (providerClass) {\n // Add the provider itself\n providers.push({\n provide: MJAuthBase,\n useClass: providerClass\n });\n } else {\n console.error(`No provider class registered for auth type: ${authType}`);\n }\n\n // Add the factory itself\n providers.push(AngularAuthProviderFactory);\n\n return {\n ngModule: AuthServicesModule,\n providers: providers as never[]\n };\n }\n}\n"]}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @fileoverview Bridges a metadata provider row to the flat `environment` record that the
3
+ * browser auth drivers already consume.
4
+ *
5
+ * Every `MJAuthBase` subclass exposes `static angularProviderFactory(environment)` and reads
6
+ * its settings from prefixed keys on that record (`AUTH0_DOMAIN`, `WORKOS_CLIENTID`, ...).
7
+ * Rather than rewrite each driver to accept a catalog row, the catalog is projected INTO that
8
+ * record — so a provider configured from metadata and one configured from `environment.ts`
9
+ * take an identical code path, and drivers keep working untouched.
10
+ *
11
+ * @module @memberjunction/ng-auth-services
12
+ */
13
+ import type { PublicAuthProviderInfo } from '@memberjunction/core';
14
+ /**
15
+ * Optional hook a provider class may expose when the generic prefixed-key convention does not
16
+ * describe its configuration. MSAL is the built-in example: it reads unprefixed `CLIENT_ID` /
17
+ * `CLIENT_AUTHORITY`, so it maps the catalog row itself.
18
+ */
19
+ export interface CatalogEnvironmentMapper {
20
+ EnvironmentFromCatalog?: (info: PublicAuthProviderInfo) => Record<string, unknown>;
21
+ }
22
+ /**
23
+ * Projects a catalog row onto the conventional prefixed environment keys.
24
+ *
25
+ * The convention — `<DRIVER>_CLIENTID`, `<DRIVER>_DOMAIN`, `<DRIVER>_SCOPES`, plus one key per
26
+ * `clientConfiguration` entry — is exactly what the Auth0, Okta, Cognito and WorkOS drivers
27
+ * already read, so those four need no per-driver mapping at all. A driver that deviates
28
+ * supplies `EnvironmentFromCatalog`.
29
+ *
30
+ * Only defined values are emitted, so a catalog row never blanks out a key the app's compiled
31
+ * environment legitimately supplies. `clientConfiguration` entries are projected FIRST so the
32
+ * modelled columns win a key collision — the same precedence the server enforces in
33
+ * `buildProviderConfig`, where a blob must not silently redefine a described, reviewable column
34
+ * (`{"scopes": "..."}` in the blob would otherwise clobber the parsed `Scopes` column).
35
+ */
36
+ export declare function buildGenericEnvironmentOverlay(info: PublicAuthProviderInfo): Record<string, unknown>;
37
+ /**
38
+ * Produces the environment record to hand a driver for a catalog-selected provider.
39
+ *
40
+ * The app's compiled environment stays the base layer — it carries app-wide settings such as
41
+ * `GRAPHQL_URI` that have nothing to do with the identity provider — and the catalog overlays
42
+ * only the provider's own keys on top. Metadata therefore wins over a stale compiled value for
43
+ * the settings it owns, without the catalog having to restate the whole environment.
44
+ *
45
+ * @param environment The app's compiled environment object.
46
+ * @param info The provider selected from the catalog.
47
+ * @param providerClass The resolved `MJAuthBase` subclass, consulted for a custom mapper.
48
+ */
49
+ export declare function mergeCatalogEnvironment(environment: Record<string, unknown>, info: PublicAuthProviderInfo, providerClass?: CatalogEnvironmentMapper): Record<string, unknown>;
50
+ //# sourceMappingURL=catalog-environment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-environment.d.ts","sourceRoot":"","sources":["../../src/lib/catalog-environment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEnE;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,sBAAsB,CAAC,EAAE,CAAC,IAAI,EAAE,sBAAsB,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpF;AAmBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA6BpG;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,IAAI,EAAE,sBAAsB,EAC5B,aAAa,CAAC,EAAE,wBAAwB,GACvC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOzB"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @fileoverview Bridges a metadata provider row to the flat `environment` record that the
3
+ * browser auth drivers already consume.
4
+ *
5
+ * Every `MJAuthBase` subclass exposes `static angularProviderFactory(environment)` and reads
6
+ * its settings from prefixed keys on that record (`AUTH0_DOMAIN`, `WORKOS_CLIENTID`, ...).
7
+ * Rather than rewrite each driver to accept a catalog row, the catalog is projected INTO that
8
+ * record — so a provider configured from metadata and one configured from `environment.ts`
9
+ * take an identical code path, and drivers keep working untouched.
10
+ *
11
+ * @module @memberjunction/ng-auth-services
12
+ */
13
+ /**
14
+ * `redirectUri` → `REDIRECT_URI`, `apiHostname` → `API_HOSTNAME`, `userPoolId` → `USER_POOL_ID`.
15
+ */
16
+ function camelToUpperSnake(key) {
17
+ return key
18
+ .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
19
+ .replace(/[-\s]+/g, '_')
20
+ .toUpperCase();
21
+ }
22
+ /**
23
+ * The environment-key prefix for a driver: `workos` → `WORKOS`, `magic-link` → `MAGIC_LINK`.
24
+ */
25
+ function environmentPrefix(driverClass) {
26
+ return camelToUpperSnake(driverClass);
27
+ }
28
+ /**
29
+ * Projects a catalog row onto the conventional prefixed environment keys.
30
+ *
31
+ * The convention — `<DRIVER>_CLIENTID`, `<DRIVER>_DOMAIN`, `<DRIVER>_SCOPES`, plus one key per
32
+ * `clientConfiguration` entry — is exactly what the Auth0, Okta, Cognito and WorkOS drivers
33
+ * already read, so those four need no per-driver mapping at all. A driver that deviates
34
+ * supplies `EnvironmentFromCatalog`.
35
+ *
36
+ * Only defined values are emitted, so a catalog row never blanks out a key the app's compiled
37
+ * environment legitimately supplies. `clientConfiguration` entries are projected FIRST so the
38
+ * modelled columns win a key collision — the same precedence the server enforces in
39
+ * `buildProviderConfig`, where a blob must not silently redefine a described, reviewable column
40
+ * (`{"scopes": "..."}` in the blob would otherwise clobber the parsed `Scopes` column).
41
+ */
42
+ export function buildGenericEnvironmentOverlay(info) {
43
+ const prefix = environmentPrefix(info.driverClass);
44
+ const overlay = {};
45
+ for (const [key, value] of Object.entries(info.clientConfiguration ?? {})) {
46
+ if (value !== null && value !== undefined) {
47
+ overlay[`${prefix}_${camelToUpperSnake(key)}`] = value;
48
+ }
49
+ }
50
+ if (info.clientId) {
51
+ overlay[`${prefix}_CLIENTID`] = info.clientId;
52
+ }
53
+ if (info.domain) {
54
+ overlay[`${prefix}_DOMAIN`] = info.domain;
55
+ }
56
+ if (Array.isArray(info.scopes) && info.scopes.length > 0) {
57
+ // The catalog publishes scopes pre-parsed (the server splits the delimited column at the
58
+ // trust boundary). The drivers that read this key — Okta and Cognito — hand it straight to
59
+ // SDK config typed `string[]`. The Array.isArray guard keeps a malformed or older server's
60
+ // string value from reaching those SDKs: this module runs at bootstrap, where the contract
61
+ // is degrade-to-compiled-environment, never throw.
62
+ overlay[`${prefix}_SCOPES`] = info.scopes;
63
+ }
64
+ if (info.issuer) {
65
+ overlay[`${prefix}_ISSUER`] = info.issuer;
66
+ }
67
+ return overlay;
68
+ }
69
+ /**
70
+ * Produces the environment record to hand a driver for a catalog-selected provider.
71
+ *
72
+ * The app's compiled environment stays the base layer — it carries app-wide settings such as
73
+ * `GRAPHQL_URI` that have nothing to do with the identity provider — and the catalog overlays
74
+ * only the provider's own keys on top. Metadata therefore wins over a stale compiled value for
75
+ * the settings it owns, without the catalog having to restate the whole environment.
76
+ *
77
+ * @param environment The app's compiled environment object.
78
+ * @param info The provider selected from the catalog.
79
+ * @param providerClass The resolved `MJAuthBase` subclass, consulted for a custom mapper.
80
+ */
81
+ export function mergeCatalogEnvironment(environment, info, providerClass) {
82
+ const overlay = typeof providerClass?.EnvironmentFromCatalog === 'function'
83
+ ? providerClass.EnvironmentFromCatalog(info)
84
+ : buildGenericEnvironmentOverlay(info);
85
+ return { ...environment, ...overlay, AUTH_TYPE: info.driverClass };
86
+ }
87
+ //# sourceMappingURL=catalog-environment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-environment.js","sourceRoot":"","sources":["../../src/lib/catalog-environment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAaH;;GAEG;AACH,SAAS,iBAAiB,CAAC,GAAW;IACpC,OAAO,GAAG;SACP,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,WAAW,EAAE,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,WAAmB;IAC5C,OAAO,iBAAiB,CAAC,WAAW,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,8BAA8B,CAAC,IAA4B;IACzE,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACnD,MAAM,OAAO,GAA4B,EAAE,CAAC;IAE5C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,mBAAmB,IAAI,EAAE,CAAC,EAAE,CAAC;QAC1E,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC1C,OAAO,CAAC,GAAG,MAAM,IAAI,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC;QACzD,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,MAAM,WAAW,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;IAChD,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IAC5C,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,yFAAyF;QACzF,2FAA2F;QAC3F,2FAA2F;QAC3F,2FAA2F;QAC3F,mDAAmD;QACnD,OAAO,CAAC,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IAC5C,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IAC5C,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CACrC,WAAoC,EACpC,IAA4B,EAC5B,aAAwC;IAExC,MAAM,OAAO,GACX,OAAO,aAAa,EAAE,sBAAsB,KAAK,UAAU;QACzD,CAAC,CAAC,aAAa,CAAC,sBAAsB,CAAC,IAAI,CAAC;QAC5C,CAAC,CAAC,8BAA8B,CAAC,IAAI,CAAC,CAAC;IAE3C,OAAO,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;AACrE,CAAC","sourcesContent":["/**\n * @fileoverview Bridges a metadata provider row to the flat `environment` record that the\n * browser auth drivers already consume.\n *\n * Every `MJAuthBase` subclass exposes `static angularProviderFactory(environment)` and reads\n * its settings from prefixed keys on that record (`AUTH0_DOMAIN`, `WORKOS_CLIENTID`, ...).\n * Rather than rewrite each driver to accept a catalog row, the catalog is projected INTO that\n * record — so a provider configured from metadata and one configured from `environment.ts`\n * take an identical code path, and drivers keep working untouched.\n *\n * @module @memberjunction/ng-auth-services\n */\n\nimport type { PublicAuthProviderInfo } from '@memberjunction/core';\n\n/**\n * Optional hook a provider class may expose when the generic prefixed-key convention does not\n * describe its configuration. MSAL is the built-in example: it reads unprefixed `CLIENT_ID` /\n * `CLIENT_AUTHORITY`, so it maps the catalog row itself.\n */\nexport interface CatalogEnvironmentMapper {\n EnvironmentFromCatalog?: (info: PublicAuthProviderInfo) => Record<string, unknown>;\n}\n\n/**\n * `redirectUri` → `REDIRECT_URI`, `apiHostname` → `API_HOSTNAME`, `userPoolId` → `USER_POOL_ID`.\n */\nfunction camelToUpperSnake(key: string): string {\n return key\n .replace(/([a-z0-9])([A-Z])/g, '$1_$2')\n .replace(/[-\\s]+/g, '_')\n .toUpperCase();\n}\n\n/**\n * The environment-key prefix for a driver: `workos` → `WORKOS`, `magic-link` → `MAGIC_LINK`.\n */\nfunction environmentPrefix(driverClass: string): string {\n return camelToUpperSnake(driverClass);\n}\n\n/**\n * Projects a catalog row onto the conventional prefixed environment keys.\n *\n * The convention — `<DRIVER>_CLIENTID`, `<DRIVER>_DOMAIN`, `<DRIVER>_SCOPES`, plus one key per\n * `clientConfiguration` entry — is exactly what the Auth0, Okta, Cognito and WorkOS drivers\n * already read, so those four need no per-driver mapping at all. A driver that deviates\n * supplies `EnvironmentFromCatalog`.\n *\n * Only defined values are emitted, so a catalog row never blanks out a key the app's compiled\n * environment legitimately supplies. `clientConfiguration` entries are projected FIRST so the\n * modelled columns win a key collision — the same precedence the server enforces in\n * `buildProviderConfig`, where a blob must not silently redefine a described, reviewable column\n * (`{\"scopes\": \"...\"}` in the blob would otherwise clobber the parsed `Scopes` column).\n */\nexport function buildGenericEnvironmentOverlay(info: PublicAuthProviderInfo): Record<string, unknown> {\n const prefix = environmentPrefix(info.driverClass);\n const overlay: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(info.clientConfiguration ?? {})) {\n if (value !== null && value !== undefined) {\n overlay[`${prefix}_${camelToUpperSnake(key)}`] = value;\n }\n }\n\n if (info.clientId) {\n overlay[`${prefix}_CLIENTID`] = info.clientId;\n }\n if (info.domain) {\n overlay[`${prefix}_DOMAIN`] = info.domain;\n }\n if (Array.isArray(info.scopes) && info.scopes.length > 0) {\n // The catalog publishes scopes pre-parsed (the server splits the delimited column at the\n // trust boundary). The drivers that read this key — Okta and Cognito — hand it straight to\n // SDK config typed `string[]`. The Array.isArray guard keeps a malformed or older server's\n // string value from reaching those SDKs: this module runs at bootstrap, where the contract\n // is degrade-to-compiled-environment, never throw.\n overlay[`${prefix}_SCOPES`] = info.scopes;\n }\n if (info.issuer) {\n overlay[`${prefix}_ISSUER`] = info.issuer;\n }\n\n return overlay;\n}\n\n/**\n * Produces the environment record to hand a driver for a catalog-selected provider.\n *\n * The app's compiled environment stays the base layer — it carries app-wide settings such as\n * `GRAPHQL_URI` that have nothing to do with the identity provider — and the catalog overlays\n * only the provider's own keys on top. Metadata therefore wins over a stale compiled value for\n * the settings it owns, without the catalog having to restate the whole environment.\n *\n * @param environment The app's compiled environment object.\n * @param info The provider selected from the catalog.\n * @param providerClass The resolved `MJAuthBase` subclass, consulted for a custom mapper.\n */\nexport function mergeCatalogEnvironment(\n environment: Record<string, unknown>,\n info: PublicAuthProviderInfo,\n providerClass?: CatalogEnvironmentMapper\n): Record<string, unknown> {\n const overlay =\n typeof providerClass?.EnvironmentFromCatalog === 'function'\n ? providerClass.EnvironmentFromCatalog(info)\n : buildGenericEnvironmentOverlay(info);\n\n return { ...environment, ...overlay, AUTH_TYPE: info.driverClass };\n}\n"]}
@@ -0,0 +1,72 @@
1
+ import { EventEmitter } from '@angular/core';
2
+ import type { PublicAuthProviderInfo } from '@memberjunction/core';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * Reusable, app-agnostic multi-IdP login picker.
6
+ *
7
+ * Presentational by design: it takes a provider catalog in and emits the user's choice out. It
8
+ * owns no routing, no branding, and no knowledge of which app embeds it, so Explorer and any
9
+ * other MJ application get the identical accessible picker by dropping in the element and
10
+ * supplying their own surrounding login surface.
11
+ *
12
+ * Accessibility comes from the shared `mjButton` directive (focus ring, hit target, disabled
13
+ * semantics) rather than from styles restated here, so it cannot drift from the rest of the app.
14
+ *
15
+ * @example
16
+ * ```html
17
+ * <mj-login-picker
18
+ * [Providers]="Catalog"
19
+ * [Busy]="SigningIn"
20
+ * (ProviderSelected)="OnProviderSelected($event)">
21
+ * </mj-login-picker>
22
+ * ```
23
+ */
24
+ export declare class MJLoginPickerComponent {
25
+ /** Providers to offer, already ordered by the caller. */
26
+ Providers: PublicAuthProviderInfo[];
27
+ /** Optional heading rendered above the list. */
28
+ Heading: string | null;
29
+ /** Optional supporting line rendered under the heading. */
30
+ Subheading: string | null;
31
+ /**
32
+ * Disables every row — set while a sign-in is being initiated so a second click cannot
33
+ * start a competing redirect.
34
+ */
35
+ Busy: boolean;
36
+ /**
37
+ * Whether to render the "Powered by MemberJunction" attribution.
38
+ *
39
+ * On by default, and a host-supplied flag rather than a code change, because full
40
+ * white-labelling is a commercial entitlement: a tenant that has paid to remove the
41
+ * attribution must be satisfiable by configuration alone.
42
+ */
43
+ ShowPoweredBy: boolean;
44
+ /**
45
+ * Label for the call to action shown when the catalog published nothing.
46
+ *
47
+ * Lets one component cover all three states — 2+ providers (a list), exactly one (a single
48
+ * primary CTA naming it), and none at all (this generic CTA, for deployments still configured
49
+ * through `mj.config.cjs` / `AUTH_TYPE`). Null renders nothing, which is the prior behaviour
50
+ * for hosts that handle the empty case themselves.
51
+ */
52
+ FallbackCtaLabel: string | null;
53
+ /** Emitted with the chosen provider. The host decides what signing in means. */
54
+ ProviderSelected: EventEmitter<PublicAuthProviderInfo>;
55
+ /** Emitted when the empty-catalog CTA is clicked. The host starts its configured sign-in. */
56
+ FallbackSelected: EventEmitter<void>;
57
+ /** A single option is not a choice — it renders as one primary call to action. */
58
+ get IsSingleProvider(): boolean;
59
+ /** "Continue with Okta" — the conventional modern auth phrasing. */
60
+ LabelFor(provider: PublicAuthProviderInfo): string;
61
+ /**
62
+ * Resolves the icon class for a provider: an explicit `Icon` from metadata wins, otherwise
63
+ * a known brand mapping for the driver, otherwise null (the chip falls back to an initial).
64
+ */
65
+ IconClassFor(provider: PublicAuthProviderInfo): string | null;
66
+ /** Fallback chip content when no icon resolves. */
67
+ InitialFor(provider: PublicAuthProviderInfo): string;
68
+ Select(provider: PublicAuthProviderInfo): void;
69
+ static ɵfac: i0.ɵɵFactoryDeclaration<MJLoginPickerComponent, never>;
70
+ static ɵcmp: i0.ɵɵComponentDeclaration<MJLoginPickerComponent, "mj-login-picker", never, { "Providers": { "alias": "Providers"; "required": false; }; "Heading": { "alias": "Heading"; "required": false; }; "Subheading": { "alias": "Subheading"; "required": false; }; "Busy": { "alias": "Busy"; "required": false; }; "ShowPoweredBy": { "alias": "ShowPoweredBy"; "required": false; }; "FallbackCtaLabel": { "alias": "FallbackCtaLabel"; "required": false; }; }, { "ProviderSelected": "ProviderSelected"; "FallbackSelected": "FallbackSelected"; }, never, never, true, never>;
71
+ }
72
+ //# sourceMappingURL=login-picker.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-picker.component.d.ts","sourceRoot":"","sources":["../../src/lib/login-picker.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,eAAe,CAAC;AAEvE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;;AAiBnE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAgMa,sBAAsB;IACjC,yDAAyD;IAChD,SAAS,EAAE,sBAAsB,EAAE,CAAM;IAElD,gDAAgD;IACvC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAY;IAE3C,2DAA2D;IAClD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE1C;;;OAGG;IACM,IAAI,UAAS;IAEtB;;;;;;OAMG;IACM,aAAa,UAAQ;IAE9B;;;;;;;OAOG;IACM,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEhD,gFAAgF;IACtE,gBAAgB,uCAA8C;IAExE,6FAA6F;IACnF,gBAAgB,qBAA4B;IAEtD,kFAAkF;IAClF,IAAW,gBAAgB,IAAI,OAAO,CAErC;IAED,oEAAoE;IAC7D,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,GAAG,MAAM;IAIzD;;;OAGG;IACI,YAAY,CAAC,QAAQ,EAAE,sBAAsB,GAAG,MAAM,GAAG,IAAI;IAOpE,mDAAmD;IAC5C,UAAU,CAAC,QAAQ,EAAE,sBAAsB,GAAG,MAAM;IAIpD,MAAM,CAAC,QAAQ,EAAE,sBAAsB,GAAG,IAAI;yCAnE1C,sBAAsB;2CAAtB,sBAAsB;CAwElC"}