@memberjunction/ng-auth-services 6.1.0-edge.1 → 6.1.0-edge.3

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
@@ -0,0 +1,284 @@
1
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { MJButtonDirective } from '@memberjunction/ng-ui-components';
3
+ import * as i0 from "@angular/core";
4
+ const _forTrack0 = ($index, $item) => $item.name;
5
+ function MJLoginPickerComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
6
+ i0.ɵɵelementStart(0, "h3", 1);
7
+ i0.ɵɵtext(1);
8
+ i0.ɵɵelementEnd();
9
+ } if (rf & 2) {
10
+ const ctx_r0 = i0.ɵɵnextContext();
11
+ i0.ɵɵadvance();
12
+ i0.ɵɵtextInterpolate(ctx_r0.Heading);
13
+ } }
14
+ function MJLoginPickerComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
15
+ i0.ɵɵelementStart(0, "p", 2);
16
+ i0.ɵɵtext(1);
17
+ i0.ɵɵelementEnd();
18
+ } if (rf & 2) {
19
+ const ctx_r0 = i0.ɵɵnextContext();
20
+ i0.ɵɵadvance();
21
+ i0.ɵɵtextInterpolate(ctx_r0.Subheading);
22
+ } }
23
+ function MJLoginPickerComponent_For_5_Conditional_2_Template(rf, ctx) { if (rf & 1) {
24
+ i0.ɵɵelement(0, "i");
25
+ } if (rf & 2) {
26
+ i0.ɵɵclassMap(ctx);
27
+ } }
28
+ function MJLoginPickerComponent_For_5_Conditional_3_Template(rf, ctx) { if (rf & 1) {
29
+ i0.ɵɵtext(0);
30
+ } if (rf & 2) {
31
+ const provider_r3 = i0.ɵɵnextContext().$implicit;
32
+ const ctx_r0 = i0.ɵɵnextContext();
33
+ i0.ɵɵtextInterpolate1(" ", ctx_r0.InitialFor(provider_r3), " ");
34
+ } }
35
+ function MJLoginPickerComponent_For_5_Conditional_6_Template(rf, ctx) { if (rf & 1) {
36
+ i0.ɵɵelementStart(0, "span", 11);
37
+ i0.ɵɵtext(1, "Default");
38
+ i0.ɵɵelementEnd();
39
+ } }
40
+ function MJLoginPickerComponent_For_5_Template(rf, ctx) { if (rf & 1) {
41
+ const _r2 = i0.ɵɵgetCurrentView();
42
+ i0.ɵɵelementStart(0, "button", 7);
43
+ i0.ɵɵlistener("click", function MJLoginPickerComponent_For_5_Template_button_click_0_listener() { const provider_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.Select(provider_r3)); });
44
+ i0.ɵɵelementStart(1, "span", 8);
45
+ i0.ɵɵconditionalCreate(2, MJLoginPickerComponent_For_5_Conditional_2_Template, 1, 2, "i", 9)(3, MJLoginPickerComponent_For_5_Conditional_3_Template, 1, 1);
46
+ i0.ɵɵelementEnd();
47
+ i0.ɵɵelementStart(4, "span", 10);
48
+ i0.ɵɵtext(5);
49
+ i0.ɵɵelementEnd();
50
+ i0.ɵɵconditionalCreate(6, MJLoginPickerComponent_For_5_Conditional_6_Template, 2, 0, "span", 11);
51
+ i0.ɵɵelementStart(7, "span", 12);
52
+ i0.ɵɵelement(8, "i", 13);
53
+ i0.ɵɵelementEnd()();
54
+ } if (rf & 2) {
55
+ let tmp_14_0;
56
+ const provider_r3 = ctx.$implicit;
57
+ const ctx_r0 = i0.ɵɵnextContext();
58
+ i0.ɵɵclassProp("mj-login-picker__row--default", provider_r3.isDefault && !ctx_r0.IsSingleProvider);
59
+ i0.ɵɵproperty("variant", ctx_r0.IsSingleProvider ? "primary" : "secondary")("disabled", ctx_r0.Busy)("ariaLabel", ctx_r0.LabelFor(provider_r3));
60
+ i0.ɵɵadvance(2);
61
+ i0.ɵɵconditional((tmp_14_0 = ctx_r0.IconClassFor(provider_r3)) ? 2 : 3, tmp_14_0);
62
+ i0.ɵɵadvance(3);
63
+ i0.ɵɵtextInterpolate(ctx_r0.LabelFor(provider_r3));
64
+ i0.ɵɵadvance();
65
+ i0.ɵɵconditional(provider_r3.isDefault && !ctx_r0.IsSingleProvider ? 6 : -1);
66
+ } }
67
+ function MJLoginPickerComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
68
+ const _r4 = i0.ɵɵgetCurrentView();
69
+ i0.ɵɵelementStart(0, "button", 14);
70
+ i0.ɵɵlistener("click", function MJLoginPickerComponent_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r4); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.FallbackSelected.emit()); });
71
+ i0.ɵɵtext(1);
72
+ i0.ɵɵelementEnd();
73
+ } if (rf & 2) {
74
+ const ctx_r0 = i0.ɵɵnextContext();
75
+ i0.ɵɵproperty("disabled", ctx_r0.Busy);
76
+ i0.ɵɵadvance();
77
+ i0.ɵɵtextInterpolate1(" ", ctx_r0.FallbackCtaLabel, " ");
78
+ } }
79
+ function MJLoginPickerComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
80
+ i0.ɵɵelementStart(0, "p", 6);
81
+ i0.ɵɵtext(1, "Powered by MemberJunction");
82
+ i0.ɵɵelementEnd();
83
+ } }
84
+ /**
85
+ * Brand keys the picker knows how to render as a coloured chip. Anything else falls back to a
86
+ * neutral chip with the provider's Font Awesome icon (or its initial).
87
+ */
88
+ const BRAND_ICON_CLASSES = {
89
+ msal: 'fa-brands fa-microsoft',
90
+ microsoft: 'fa-brands fa-microsoft',
91
+ google: 'fa-brands fa-google',
92
+ okta: 'fa-solid fa-circle-half-stroke',
93
+ auth0: 'fa-solid fa-shield-halved',
94
+ cognito: 'fa-brands fa-aws',
95
+ workos: 'fa-solid fa-building-lock',
96
+ 'magic-link': 'fa-solid fa-wand-magic-sparkles'
97
+ };
98
+ /**
99
+ * Reusable, app-agnostic multi-IdP login picker.
100
+ *
101
+ * Presentational by design: it takes a provider catalog in and emits the user's choice out. It
102
+ * owns no routing, no branding, and no knowledge of which app embeds it, so Explorer and any
103
+ * other MJ application get the identical accessible picker by dropping in the element and
104
+ * supplying their own surrounding login surface.
105
+ *
106
+ * Accessibility comes from the shared `mjButton` directive (focus ring, hit target, disabled
107
+ * semantics) rather than from styles restated here, so it cannot drift from the rest of the app.
108
+ *
109
+ * @example
110
+ * ```html
111
+ * <mj-login-picker
112
+ * [Providers]="Catalog"
113
+ * [Busy]="SigningIn"
114
+ * (ProviderSelected)="OnProviderSelected($event)">
115
+ * </mj-login-picker>
116
+ * ```
117
+ */
118
+ export class MJLoginPickerComponent {
119
+ /** Providers to offer, already ordered by the caller. */
120
+ Providers = [];
121
+ /** Optional heading rendered above the list. */
122
+ Heading = 'Log in';
123
+ /** Optional supporting line rendered under the heading. */
124
+ Subheading = null;
125
+ /**
126
+ * Disables every row — set while a sign-in is being initiated so a second click cannot
127
+ * start a competing redirect.
128
+ */
129
+ Busy = false;
130
+ /**
131
+ * Whether to render the "Powered by MemberJunction" attribution.
132
+ *
133
+ * On by default, and a host-supplied flag rather than a code change, because full
134
+ * white-labelling is a commercial entitlement: a tenant that has paid to remove the
135
+ * attribution must be satisfiable by configuration alone.
136
+ */
137
+ ShowPoweredBy = true;
138
+ /**
139
+ * Label for the call to action shown when the catalog published nothing.
140
+ *
141
+ * Lets one component cover all three states — 2+ providers (a list), exactly one (a single
142
+ * primary CTA naming it), and none at all (this generic CTA, for deployments still configured
143
+ * through `mj.config.cjs` / `AUTH_TYPE`). Null renders nothing, which is the prior behaviour
144
+ * for hosts that handle the empty case themselves.
145
+ */
146
+ FallbackCtaLabel = null;
147
+ /** Emitted with the chosen provider. The host decides what signing in means. */
148
+ ProviderSelected = new EventEmitter();
149
+ /** Emitted when the empty-catalog CTA is clicked. The host starts its configured sign-in. */
150
+ FallbackSelected = new EventEmitter();
151
+ /** A single option is not a choice — it renders as one primary call to action. */
152
+ get IsSingleProvider() {
153
+ return this.Providers.length === 1;
154
+ }
155
+ /** "Continue with Okta" — the conventional modern auth phrasing. */
156
+ LabelFor(provider) {
157
+ return `Continue with ${provider.displayName || provider.name}`;
158
+ }
159
+ /**
160
+ * Resolves the icon class for a provider: an explicit `Icon` from metadata wins, otherwise
161
+ * a known brand mapping for the driver, otherwise null (the chip falls back to an initial).
162
+ */
163
+ IconClassFor(provider) {
164
+ if (provider.icon) {
165
+ return provider.icon.startsWith('fa-') ? provider.icon : (BRAND_ICON_CLASSES[provider.icon.toLowerCase()] ?? null);
166
+ }
167
+ return BRAND_ICON_CLASSES[provider.driverClass?.toLowerCase()] ?? null;
168
+ }
169
+ /** Fallback chip content when no icon resolves. */
170
+ InitialFor(provider) {
171
+ return (provider.displayName || provider.name || '?').charAt(0).toUpperCase();
172
+ }
173
+ Select(provider) {
174
+ if (!this.Busy) {
175
+ this.ProviderSelected.emit(provider);
176
+ }
177
+ }
178
+ static ɵfac = function MJLoginPickerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MJLoginPickerComponent)(); };
179
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJLoginPickerComponent, selectors: [["mj-login-picker"]], inputs: { Providers: "Providers", Heading: "Heading", Subheading: "Subheading", Busy: "Busy", ShowPoweredBy: "ShowPoweredBy", FallbackCtaLabel: "FallbackCtaLabel" }, outputs: { ProviderSelected: "ProviderSelected", FallbackSelected: "FallbackSelected" }, decls: 8, vars: 5, consts: [[1, "mj-login-picker"], [1, "mj-login-picker__heading"], [1, "mj-login-picker__subheading"], ["role", "group", 1, "mj-login-picker__list"], ["mjButton", "", "size", "lg", "type", "button", 1, "mj-login-picker__row", 3, "variant", "mj-login-picker__row--default", "disabled", "ariaLabel"], ["mjButton", "", "variant", "primary", "size", "lg", "type", "button", 1, "mj-login-picker__row", "mj-login-picker__row--fallback", 3, "disabled"], [1, "mj-login-picker__attribution"], ["mjButton", "", "size", "lg", "type", "button", 1, "mj-login-picker__row", 3, "click", "variant", "disabled", "ariaLabel"], ["aria-hidden", "true", 1, "mj-login-picker__chip"], [3, "class"], [1, "mj-login-picker__label"], [1, "mj-login-picker__pill"], ["aria-hidden", "true", 1, "mj-login-picker__chevron"], [1, "fa-solid", "fa-arrow-right"], ["mjButton", "", "variant", "primary", "size", "lg", "type", "button", 1, "mj-login-picker__row", "mj-login-picker__row--fallback", 3, "click", "disabled"]], template: function MJLoginPickerComponent_Template(rf, ctx) { if (rf & 1) {
180
+ i0.ɵɵelementStart(0, "div", 0);
181
+ i0.ɵɵconditionalCreate(1, MJLoginPickerComponent_Conditional_1_Template, 2, 1, "h3", 1);
182
+ i0.ɵɵconditionalCreate(2, MJLoginPickerComponent_Conditional_2_Template, 2, 1, "p", 2);
183
+ i0.ɵɵelementStart(3, "div", 3);
184
+ i0.ɵɵrepeaterCreate(4, MJLoginPickerComponent_For_5_Template, 9, 8, "button", 4, _forTrack0);
185
+ i0.ɵɵelementEnd();
186
+ i0.ɵɵconditionalCreate(6, MJLoginPickerComponent_Conditional_6_Template, 2, 2, "button", 5);
187
+ i0.ɵɵconditionalCreate(7, MJLoginPickerComponent_Conditional_7_Template, 2, 0, "p", 6);
188
+ i0.ɵɵelementEnd();
189
+ } if (rf & 2) {
190
+ i0.ɵɵadvance();
191
+ i0.ɵɵconditional(ctx.Heading ? 1 : -1);
192
+ i0.ɵɵadvance();
193
+ i0.ɵɵconditional(ctx.Subheading ? 2 : -1);
194
+ i0.ɵɵadvance();
195
+ i0.ɵɵattribute("aria-label", ctx.Heading || "Sign-in options");
196
+ i0.ɵɵadvance();
197
+ i0.ɵɵrepeater(ctx.Providers);
198
+ i0.ɵɵadvance(2);
199
+ i0.ɵɵconditional(!ctx.Providers.length && ctx.FallbackCtaLabel ? 6 : -1);
200
+ i0.ɵɵadvance();
201
+ i0.ɵɵconditional(ctx.ShowPoweredBy ? 7 : -1);
202
+ } }, dependencies: [MJButtonDirective], styles: [".mj-login-picker[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-3, 0.75rem);\n width: 100%;\n max-width: 400px;\n }\n\n \n\n\n .mj-login-picker__heading[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-2xl, 1.5rem);\n font-weight: var(--mj-font-bold, 700);\n color: var(--mj-text-primary);\n text-align: left;\n }\n\n .mj-login-picker__subheading[_ngcontent-%COMP%] {\n margin: 0 0 var(--mj-space-5, 1.25rem);\n font-size: var(--mj-text-base, 1rem);\n color: var(--mj-text-secondary);\n text-align: left;\n }\n\n .mj-login-picker__list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-2, 0.5rem);\n }\n\n \n\n\n .mj-login-picker__row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-3, 0.75rem);\n width: 100%;\n text-align: left;\n }\n\n \n\n\n\n .mj-login-picker__row--default[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n }\n\n \n\n .mj-login-picker__row--fallback[_ngcontent-%COMP%] {\n justify-content: center;\n text-align: center;\n }\n\n .mj-login-picker__chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: var(--mj-radius-sm, 0.25rem);\n background: color-mix(in srgb, currentColor 12%, transparent);\n font-size: var(--mj-text-sm, 0.875rem);\n font-weight: 700;\n }\n\n \n\n .mj-login-picker__label[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n min-width: 0;\n white-space: normal;\n }\n\n .mj-login-picker__pill[_ngcontent-%COMP%] {\n flex: 0 0 auto;\n padding: 0.125rem var(--mj-space-2, 0.5rem);\n border-radius: var(--mj-radius-full, 999px);\n \n\n\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n font-size: var(--mj-text-xs, 0.75rem);\n font-weight: var(--mj-font-bold, 700);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n }\n\n \n\n\n\n .mj-login-picker__chevron[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n flex: 0 0 auto;\n font-size: var(--mj-text-sm, 0.875rem);\n color: var(--mj-text-muted);\n transition: color 120ms ease, transform 120ms ease;\n }\n\n .mj-login-picker__row[_ngcontent-%COMP%]:hover .mj-login-picker__chevron[_ngcontent-%COMP%], \n .mj-login-picker__row[_ngcontent-%COMP%]:focus-visible .mj-login-picker__chevron[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n transform: translateX(2px);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .mj-login-picker__chevron[_ngcontent-%COMP%] {\n transition: none;\n }\n\n .mj-login-picker__row[_ngcontent-%COMP%]:hover .mj-login-picker__chevron[_ngcontent-%COMP%], \n .mj-login-picker__row[_ngcontent-%COMP%]:focus-visible .mj-login-picker__chevron[_ngcontent-%COMP%] {\n transform: none;\n }\n }\n\n .mj-login-picker__attribution[_ngcontent-%COMP%] {\n margin: var(--mj-space-2, 0.5rem) 0 0;\n font-size: var(--mj-text-xs, 0.75rem);\n color: var(--mj-text-muted);\n text-align: center;\n }"] });
203
+ }
204
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJLoginPickerComponent, [{
205
+ type: Component,
206
+ args: [{ selector: 'mj-login-picker', standalone: true, imports: [MJButtonDirective], template: `
207
+ <div class="mj-login-picker">
208
+ @if (Heading) {
209
+ <h3 class="mj-login-picker__heading">{{ Heading }}</h3>
210
+ }
211
+ @if (Subheading) {
212
+ <p class="mj-login-picker__subheading">{{ Subheading }}</p>
213
+ }
214
+
215
+ <div class="mj-login-picker__list" role="group" [attr.aria-label]="Heading || 'Sign-in options'">
216
+ @for (provider of Providers; track provider.name) {
217
+ <button
218
+ mjButton
219
+ [variant]="IsSingleProvider ? 'primary' : 'secondary'"
220
+ size="lg"
221
+ class="mj-login-picker__row"
222
+ [class.mj-login-picker__row--default]="provider.isDefault && !IsSingleProvider"
223
+ type="button"
224
+ [disabled]="Busy"
225
+ [ariaLabel]="LabelFor(provider)"
226
+ (click)="Select(provider)">
227
+ <span class="mj-login-picker__chip" aria-hidden="true">
228
+ @if (IconClassFor(provider); as iconClass) {
229
+ <i [class]="iconClass"></i>
230
+ } @else {
231
+ {{ InitialFor(provider) }}
232
+ }
233
+ </span>
234
+ <span class="mj-login-picker__label">{{ LabelFor(provider) }}</span>
235
+ @if (provider.isDefault && !IsSingleProvider) {
236
+ <span class="mj-login-picker__pill">Default</span>
237
+ }
238
+ <span class="mj-login-picker__chevron" aria-hidden="true">
239
+ <i class="fa-solid fa-arrow-right"></i>
240
+ </span>
241
+ </button>
242
+ }
243
+ </div>
244
+
245
+ <!-- Empty catalog: the deployment is configured through config/env with nothing published,
246
+ so there is no provider to name. Opt-in via FallbackCtaLabel — an app that passes
247
+ nothing renders nothing, which is the prior behaviour. -->
248
+ @if (!Providers.length && FallbackCtaLabel) {
249
+ <button
250
+ mjButton
251
+ variant="primary"
252
+ size="lg"
253
+ class="mj-login-picker__row mj-login-picker__row--fallback"
254
+ type="button"
255
+ [disabled]="Busy"
256
+ (click)="FallbackSelected.emit()">
257
+ {{ FallbackCtaLabel }}
258
+ </button>
259
+ }
260
+
261
+ @if (ShowPoweredBy) {
262
+ <p class="mj-login-picker__attribution">Powered by MemberJunction</p>
263
+ }
264
+ </div>
265
+ `, styles: ["\n .mj-login-picker {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-3, 0.75rem);\n width: 100%;\n max-width: 400px;\n }\n\n /* Left-aligned per the locked Login C direction \u2014 the heading, lede and rows share\n one leading edge; only the attribution centers. */\n .mj-login-picker__heading {\n margin: 0;\n font-size: var(--mj-text-2xl, 1.5rem);\n font-weight: var(--mj-font-bold, 700);\n color: var(--mj-text-primary);\n text-align: left;\n }\n\n .mj-login-picker__subheading {\n margin: 0 0 var(--mj-space-5, 1.25rem);\n font-size: var(--mj-text-base, 1rem);\n color: var(--mj-text-secondary);\n text-align: left;\n }\n\n .mj-login-picker__list {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-2, 0.5rem);\n }\n\n /* Layout only \u2014 every visual affordance of the row (fill, radius, focus ring,\n hit target) belongs to the mjButton directive and is deliberately not restated. */\n .mj-login-picker__row {\n display: flex;\n align-items: center;\n gap: var(--mj-space-3, 0.75rem);\n width: 100%;\n text-align: left;\n }\n\n /* The default provider reads as the recommended path. Border only \u2014 fill, radius, focus\n ring and hit target all still come from the mjButton directive, and this targets the\n picker's own row class rather than .mj-btn, so the directive stays authoritative. */\n .mj-login-picker__row--default {\n border-color: var(--mj-brand-primary);\n }\n\n /* No icon chip or chevron to align against, so this one centres. */\n .mj-login-picker__row--fallback {\n justify-content: center;\n text-align: center;\n }\n\n .mj-login-picker__chip {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: var(--mj-radius-sm, 0.25rem);\n background: color-mix(in srgb, currentColor 12%, transparent);\n font-size: var(--mj-text-sm, 0.875rem);\n font-weight: 700;\n }\n\n /* Long provider names wrap instead of forcing horizontal overflow on narrow screens. */\n .mj-login-picker__label {\n flex: 1 1 auto;\n min-width: 0;\n white-space: normal;\n }\n\n .mj-login-picker__pill {\n flex: 0 0 auto;\n padding: 0.125rem var(--mj-space-2, 0.5rem);\n border-radius: var(--mj-radius-full, 999px);\n /* Brand-tinted rather than currentColor \u2014 the default provider is the one call to\n action on the surface, and Login C gives it the brand accent. */\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n font-size: var(--mj-text-xs, 0.75rem);\n font-weight: var(--mj-font-bold, 700);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n }\n\n /* Trailing affordance from the locked login mockup \u2014 signals that a row navigates\n away rather than toggling in place. Decorative, so it is aria-hidden and the row's\n accessible name still comes from the directive's ariaLabel. */\n .mj-login-picker__chevron {\n display: inline-flex;\n align-items: center;\n flex: 0 0 auto;\n font-size: var(--mj-text-sm, 0.875rem);\n color: var(--mj-text-muted);\n transition: color 120ms ease, transform 120ms ease;\n }\n\n .mj-login-picker__row:hover .mj-login-picker__chevron,\n .mj-login-picker__row:focus-visible .mj-login-picker__chevron {\n color: var(--mj-brand-primary);\n transform: translateX(2px);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .mj-login-picker__chevron {\n transition: none;\n }\n\n .mj-login-picker__row:hover .mj-login-picker__chevron,\n .mj-login-picker__row:focus-visible .mj-login-picker__chevron {\n transform: none;\n }\n }\n\n .mj-login-picker__attribution {\n margin: var(--mj-space-2, 0.5rem) 0 0;\n font-size: var(--mj-text-xs, 0.75rem);\n color: var(--mj-text-muted);\n text-align: center;\n }\n "] }]
266
+ }], null, { Providers: [{
267
+ type: Input
268
+ }], Heading: [{
269
+ type: Input
270
+ }], Subheading: [{
271
+ type: Input
272
+ }], Busy: [{
273
+ type: Input
274
+ }], ShowPoweredBy: [{
275
+ type: Input
276
+ }], FallbackCtaLabel: [{
277
+ type: Input
278
+ }], ProviderSelected: [{
279
+ type: Output
280
+ }], FallbackSelected: [{
281
+ type: Output
282
+ }] }); })();
283
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJLoginPickerComponent, { className: "MJLoginPickerComponent", filePath: "src/lib/login-picker.component.ts", lineNumber: 232 }); })();
284
+ //# sourceMappingURL=login-picker.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-picker.component.js","sourceRoot":"","sources":["../../src/lib/login-picker.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { MJButtonDirective } from '@memberjunction/ng-ui-components';\nimport type { PublicAuthProviderInfo } from '@memberjunction/core';\n\n/**\n * Brand keys the picker knows how to render as a coloured chip. Anything else falls back to a\n * neutral chip with the provider's Font Awesome icon (or its initial).\n */\nconst BRAND_ICON_CLASSES: Readonly<Record<string, string>> = {\n msal: 'fa-brands fa-microsoft',\n microsoft: 'fa-brands fa-microsoft',\n google: 'fa-brands fa-google',\n okta: 'fa-solid fa-circle-half-stroke',\n auth0: 'fa-solid fa-shield-halved',\n cognito: 'fa-brands fa-aws',\n workos: 'fa-solid fa-building-lock',\n 'magic-link': 'fa-solid fa-wand-magic-sparkles'\n};\n\n/**\n * Reusable, app-agnostic multi-IdP login picker.\n *\n * Presentational by design: it takes a provider catalog in and emits the user's choice out. It\n * owns no routing, no branding, and no knowledge of which app embeds it, so Explorer and any\n * other MJ application get the identical accessible picker by dropping in the element and\n * supplying their own surrounding login surface.\n *\n * Accessibility comes from the shared `mjButton` directive (focus ring, hit target, disabled\n * semantics) rather than from styles restated here, so it cannot drift from the rest of the app.\n *\n * @example\n * ```html\n * <mj-login-picker\n * [Providers]=\"Catalog\"\n * [Busy]=\"SigningIn\"\n * (ProviderSelected)=\"OnProviderSelected($event)\">\n * </mj-login-picker>\n * ```\n */\n@Component({\n selector: 'mj-login-picker',\n standalone: true,\n imports: [MJButtonDirective],\n template: `\n <div class=\"mj-login-picker\">\n @if (Heading) {\n <h3 class=\"mj-login-picker__heading\">{{ Heading }}</h3>\n }\n @if (Subheading) {\n <p class=\"mj-login-picker__subheading\">{{ Subheading }}</p>\n }\n\n <div class=\"mj-login-picker__list\" role=\"group\" [attr.aria-label]=\"Heading || 'Sign-in options'\">\n @for (provider of Providers; track provider.name) {\n <button\n mjButton\n [variant]=\"IsSingleProvider ? 'primary' : 'secondary'\"\n size=\"lg\"\n class=\"mj-login-picker__row\"\n [class.mj-login-picker__row--default]=\"provider.isDefault && !IsSingleProvider\"\n type=\"button\"\n [disabled]=\"Busy\"\n [ariaLabel]=\"LabelFor(provider)\"\n (click)=\"Select(provider)\">\n <span class=\"mj-login-picker__chip\" aria-hidden=\"true\">\n @if (IconClassFor(provider); as iconClass) {\n <i [class]=\"iconClass\"></i>\n } @else {\n {{ InitialFor(provider) }}\n }\n </span>\n <span class=\"mj-login-picker__label\">{{ LabelFor(provider) }}</span>\n @if (provider.isDefault && !IsSingleProvider) {\n <span class=\"mj-login-picker__pill\">Default</span>\n }\n <span class=\"mj-login-picker__chevron\" aria-hidden=\"true\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </span>\n </button>\n }\n </div>\n\n <!-- Empty catalog: the deployment is configured through config/env with nothing published,\n so there is no provider to name. Opt-in via FallbackCtaLabel — an app that passes\n nothing renders nothing, which is the prior behaviour. -->\n @if (!Providers.length && FallbackCtaLabel) {\n <button\n mjButton\n variant=\"primary\"\n size=\"lg\"\n class=\"mj-login-picker__row mj-login-picker__row--fallback\"\n type=\"button\"\n [disabled]=\"Busy\"\n (click)=\"FallbackSelected.emit()\">\n {{ FallbackCtaLabel }}\n </button>\n }\n\n @if (ShowPoweredBy) {\n <p class=\"mj-login-picker__attribution\">Powered by MemberJunction</p>\n }\n </div>\n `,\n styles: [\n `\n .mj-login-picker {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-3, 0.75rem);\n width: 100%;\n max-width: 400px;\n }\n\n /* Left-aligned per the locked Login C direction — the heading, lede and rows share\n one leading edge; only the attribution centers. */\n .mj-login-picker__heading {\n margin: 0;\n font-size: var(--mj-text-2xl, 1.5rem);\n font-weight: var(--mj-font-bold, 700);\n color: var(--mj-text-primary);\n text-align: left;\n }\n\n .mj-login-picker__subheading {\n margin: 0 0 var(--mj-space-5, 1.25rem);\n font-size: var(--mj-text-base, 1rem);\n color: var(--mj-text-secondary);\n text-align: left;\n }\n\n .mj-login-picker__list {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-2, 0.5rem);\n }\n\n /* Layout only — every visual affordance of the row (fill, radius, focus ring,\n hit target) belongs to the mjButton directive and is deliberately not restated. */\n .mj-login-picker__row {\n display: flex;\n align-items: center;\n gap: var(--mj-space-3, 0.75rem);\n width: 100%;\n text-align: left;\n }\n\n /* The default provider reads as the recommended path. Border only — fill, radius, focus\n ring and hit target all still come from the mjButton directive, and this targets the\n picker's own row class rather than .mj-btn, so the directive stays authoritative. */\n .mj-login-picker__row--default {\n border-color: var(--mj-brand-primary);\n }\n\n /* No icon chip or chevron to align against, so this one centres. */\n .mj-login-picker__row--fallback {\n justify-content: center;\n text-align: center;\n }\n\n .mj-login-picker__chip {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: var(--mj-radius-sm, 0.25rem);\n background: color-mix(in srgb, currentColor 12%, transparent);\n font-size: var(--mj-text-sm, 0.875rem);\n font-weight: 700;\n }\n\n /* Long provider names wrap instead of forcing horizontal overflow on narrow screens. */\n .mj-login-picker__label {\n flex: 1 1 auto;\n min-width: 0;\n white-space: normal;\n }\n\n .mj-login-picker__pill {\n flex: 0 0 auto;\n padding: 0.125rem var(--mj-space-2, 0.5rem);\n border-radius: var(--mj-radius-full, 999px);\n /* Brand-tinted rather than currentColor — the default provider is the one call to\n action on the surface, and Login C gives it the brand accent. */\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n font-size: var(--mj-text-xs, 0.75rem);\n font-weight: var(--mj-font-bold, 700);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n }\n\n /* Trailing affordance from the locked login mockup — signals that a row navigates\n away rather than toggling in place. Decorative, so it is aria-hidden and the row's\n accessible name still comes from the directive's ariaLabel. */\n .mj-login-picker__chevron {\n display: inline-flex;\n align-items: center;\n flex: 0 0 auto;\n font-size: var(--mj-text-sm, 0.875rem);\n color: var(--mj-text-muted);\n transition: color 120ms ease, transform 120ms ease;\n }\n\n .mj-login-picker__row:hover .mj-login-picker__chevron,\n .mj-login-picker__row:focus-visible .mj-login-picker__chevron {\n color: var(--mj-brand-primary);\n transform: translateX(2px);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .mj-login-picker__chevron {\n transition: none;\n }\n\n .mj-login-picker__row:hover .mj-login-picker__chevron,\n .mj-login-picker__row:focus-visible .mj-login-picker__chevron {\n transform: none;\n }\n }\n\n .mj-login-picker__attribution {\n margin: var(--mj-space-2, 0.5rem) 0 0;\n font-size: var(--mj-text-xs, 0.75rem);\n color: var(--mj-text-muted);\n text-align: center;\n }\n `\n ]\n})\nexport class MJLoginPickerComponent {\n /** Providers to offer, already ordered by the caller. */\n @Input() Providers: PublicAuthProviderInfo[] = [];\n\n /** Optional heading rendered above the list. */\n @Input() Heading: string | null = 'Log in';\n\n /** Optional supporting line rendered under the heading. */\n @Input() Subheading: string | null = null;\n\n /**\n * Disables every row — set while a sign-in is being initiated so a second click cannot\n * start a competing redirect.\n */\n @Input() Busy = false;\n\n /**\n * Whether to render the \"Powered by MemberJunction\" attribution.\n *\n * On by default, and a host-supplied flag rather than a code change, because full\n * white-labelling is a commercial entitlement: a tenant that has paid to remove the\n * attribution must be satisfiable by configuration alone.\n */\n @Input() ShowPoweredBy = true;\n\n /**\n * Label for the call to action shown when the catalog published nothing.\n *\n * Lets one component cover all three states — 2+ providers (a list), exactly one (a single\n * primary CTA naming it), and none at all (this generic CTA, for deployments still configured\n * through `mj.config.cjs` / `AUTH_TYPE`). Null renders nothing, which is the prior behaviour\n * for hosts that handle the empty case themselves.\n */\n @Input() FallbackCtaLabel: string | null = null;\n\n /** Emitted with the chosen provider. The host decides what signing in means. */\n @Output() ProviderSelected = new EventEmitter<PublicAuthProviderInfo>();\n\n /** Emitted when the empty-catalog CTA is clicked. The host starts its configured sign-in. */\n @Output() FallbackSelected = new EventEmitter<void>();\n\n /** A single option is not a choice — it renders as one primary call to action. */\n public get IsSingleProvider(): boolean {\n return this.Providers.length === 1;\n }\n\n /** \"Continue with Okta\" — the conventional modern auth phrasing. */\n public LabelFor(provider: PublicAuthProviderInfo): string {\n return `Continue with ${provider.displayName || provider.name}`;\n }\n\n /**\n * Resolves the icon class for a provider: an explicit `Icon` from metadata wins, otherwise\n * a known brand mapping for the driver, otherwise null (the chip falls back to an initial).\n */\n public IconClassFor(provider: PublicAuthProviderInfo): string | null {\n if (provider.icon) {\n return provider.icon.startsWith('fa-') ? provider.icon : (BRAND_ICON_CLASSES[provider.icon.toLowerCase()] ?? null);\n }\n return BRAND_ICON_CLASSES[provider.driverClass?.toLowerCase()] ?? null;\n }\n\n /** Fallback chip content when no icon resolves. */\n public InitialFor(provider: PublicAuthProviderInfo): string {\n return (provider.displayName || provider.name || '?').charAt(0).toUpperCase();\n }\n\n public Select(provider: PublicAuthProviderInfo): void {\n if (!this.Busy) {\n this.ProviderSelected.emit(provider);\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"mjexplorer-cognito-provider.service.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/mjexplorer-cognito-provider.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAW7D,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EAEjB,kBAAkB,EACnB,MAAM,eAAe,CAAC;;AAEvB;;;GAGG;AACH,UAAU,aAAa;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,kFAAkF;IAClF,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAIa,iBAAkB,SAAQ,UAAU;IA6BV,OAAO,CAAC,aAAa;IA5B1D,MAAM,CAAC,QAAQ,CAAC,aAAa,aAAa;IAC1C,QAAQ,CAAC,IAAI,aAAmC;IAChD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,kBAAkB,CAA6B;IAEvD;;;OAGG;IACH,MAAM,CAAC,sBAAsB,GAAI,aAAa,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;kBAc1D,aAAa;QAGtB;gBAE2C,aAAa,EAAE,aAAa;IAgCnE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;cAsDjB,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;cAMhE,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAYzC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBrC;;;;;OAKG;cACa,sBAAsB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUhE;;;OAGG;cACa,wBAAwB,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAuB7E;;;OAGG;cACa,uBAAuB,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAY3E;;;;;;OAMG;cACa,oBAAoB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IA2CnE;;;;OAIG;IACH,SAAS,CAAC,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB;IA2ElE;;;;;OAKG;cACa,4BAA4B,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUtE;;;;;;OAMG;cACa,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC;YAU9C,iBAAiB;IAM/B;;OAEG;YACW,eAAe;IAW7B;;;;;OAKG;IACH,OAAO,CAAC,8BAA8B;IAsBtC;;OAEG;IACH,OAAO,CAAC,aAAa;IAQrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAWhB,iBAAiB,IAAI,MAAM,EAAE;IAI7B,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO;yCApctD,iBAAiB;6CAAjB,iBAAiB;CAuc7B"}
1
+ {"version":3,"file":"mjexplorer-cognito-provider.service.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/mjexplorer-cognito-provider.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAW7D,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EAEjB,kBAAkB,EACnB,MAAM,eAAe,CAAC;;AAEvB;;;GAGG;AACH,UAAU,aAAa;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,kFAAkF;IAClF,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAIa,iBAAkB,SAAQ,UAAU;IAgCV,OAAO,CAAC,aAAa;IA/B1D,MAAM,CAAC,QAAQ,CAAC,aAAa,aAAa;IAC1C,QAAQ,CAAC,IAAI,aAAmC;IAChD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,kBAAkB,CAA6B;IAEvD;;;OAGG;IACH,MAAM,CAAC,sBAAsB,GAAI,aAAa,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;kBAiB1D,aAAa;QAGtB;gBAE2C,aAAa,EAAE,aAAa;IAgCnE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;cAsDjB,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;cAMhE,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAYzC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBrC;;;;;OAKG;cACa,sBAAsB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUhE;;;OAGG;cACa,wBAAwB,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAuB7E;;;OAGG;cACa,uBAAuB,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAY3E;;;;;;OAMG;cACa,oBAAoB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IA2CnE;;;;OAIG;IACH,SAAS,CAAC,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB;IA2ElE;;;;;OAKG;cACa,4BAA4B,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUtE;;;;;;OAMG;cACa,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC;YAU9C,iBAAiB;IAM/B;;OAEG;YACW,eAAe;IAW7B;;;;;OAKG;IACH,OAAO,CAAC,8BAA8B;IAsBtC;;OAEG;IACH,OAAO,CAAC,aAAa;IAQrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAWhB,iBAAiB,IAAI,MAAM,EAAE;IAI7B,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO;yCAvctD,iBAAiB;6CAAjB,iBAAiB;CA0c7B"}
@@ -46,7 +46,10 @@ let MJCognitoProvider = class MJCognitoProvider extends MJAuthBase {
46
46
  provide: 'cognitoConfig',
47
47
  useValue: {
48
48
  userPoolId: environment['COGNITO_USER_POOL_ID'],
49
- userPoolClientId: environment['COGNITO_CLIENT_ID'] || environment['COGNITO_CLIENTID'],
49
+ // COGNITO_CLIENTID first: it is the key the catalog overlay emits for a metadata-configured
50
+ // row, and it must beat the compiled environment's canonical COGNITO_CLIENT_ID spelling —
51
+ // otherwise a catalog row's ClientID is silently ignored in favour of the compiled value.
52
+ userPoolClientId: environment['COGNITO_CLIENTID'] || environment['COGNITO_CLIENT_ID'],
50
53
  region: environment['COGNITO_REGION'] || environment['AWS_REGION'],
51
54
  domain: environment['COGNITO_DOMAIN'],
52
55
  redirectUri: environment['COGNITO_REDIRECT_URI'] || window.location.origin,
@@ -1 +1 @@
1
- {"version":3,"file":"mjexplorer-cognito-provider.service.js","sourceRoot":"","sources":["../../../src/lib/providers/mjexplorer-cognito-provider.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Inject } from '@angular/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { MJAuthBase } from '../mjexplorer-auth-base.service';\nimport { AngularAuthProviderConfig } from '../IAuthProvider';\nimport { Amplify } from 'aws-amplify';\nimport {\n signInWithRedirect,\n signOut,\n fetchAuthSession,\n getCurrentUser,\n fetchUserAttributes\n} from 'aws-amplify/auth';\nimport { Hub } from 'aws-amplify/utils';\nimport {\n StandardUserInfo,\n StandardAuthToken,\n StandardAuthError,\n AuthErrorType,\n TokenRefreshResult\n} from '../auth-types';\n\n/**\n * Configuration interface for the Cognito provider.\n * Populated from environment config via the `angularProviderFactory`.\n */\ninterface CognitoConfig {\n userPoolId: string;\n userPoolClientId: string;\n region?: string;\n /** Cognito Hosted UI domain, e.g. 'myapp.auth.us-east-1.amazoncognito.com' */\n domain: string;\n /** OAuth redirect URI. Defaults to window.location.origin */\n redirectUri?: string;\n /** OAuth scopes. Defaults to ['openid', 'profile', 'email'] */\n scopes?: string[];\n /** When true, skips redirect callback processing (for MCP OAuth callback path) */\n skipRedirectCallback?: boolean;\n}\n\n/**\n * AWS Cognito authentication provider implementation - v3.0.0\n *\n * Implements the abstract methods from MJAuthBase to hide Cognito-specific details.\n * Uses AWS Amplify v6 (tree-shakeable subpath imports) for authentication.\n *\n * Key abstraction: Cognito stores tokens in Amplify's internal storage, accessed\n * via `fetchAuthSession().tokens?.idToken?.toString()`. Consumers never need to\n * know this detail.\n *\n * ## Cognito Hosted UI Flow\n * This provider uses the Cognito Hosted UI for login via `signInWithRedirect()`.\n * The flow is: redirect to Hosted UI -> user authenticates -> redirect back with\n * authorization code -> Amplify exchanges code for tokens (PKCE).\n */\n@Injectable({\n providedIn: 'root'\n})\n@RegisterClass(MJAuthBase, 'cognito')\nexport class MJCognitoProvider extends MJAuthBase {\n static readonly PROVIDER_TYPE = 'cognito';\n readonly type = MJCognitoProvider.PROVIDER_TYPE;\n private _initialized = false;\n private _hubListenerCancel: (() => void) | null = null;\n\n /**\n * Factory function to provide Angular dependencies required by the Cognito provider.\n * Returns a config injection token following the Okta provider pattern.\n */\n static angularProviderFactory = (environment: Record<string, unknown>) => {\n const isMCPOAuthCallback = window.location.pathname.startsWith('/oauth/callback');\n\n return [\n {\n provide: 'cognitoConfig',\n useValue: {\n userPoolId: environment['COGNITO_USER_POOL_ID'],\n userPoolClientId: environment['COGNITO_CLIENT_ID'] || environment['COGNITO_CLIENTID'],\n region: environment['COGNITO_REGION'] || environment['AWS_REGION'],\n domain: environment['COGNITO_DOMAIN'],\n redirectUri: environment['COGNITO_REDIRECT_URI'] || window.location.origin,\n scopes: environment['COGNITO_SCOPES'] || ['openid', 'profile', 'email', 'aws.cognito.signin.user.admin'],\n skipRedirectCallback: isMCPOAuthCallback,\n } as CognitoConfig\n }\n ];\n };\n\n constructor(@Inject('cognitoConfig') private cognitoConfig: CognitoConfig) {\n const config: AngularAuthProviderConfig = {\n name: MJCognitoProvider.PROVIDER_TYPE,\n type: MJCognitoProvider.PROVIDER_TYPE\n };\n super(config);\n\n // Configure Amplify with the existing Cognito User Pool\n const redirectUri = this.cognitoConfig.redirectUri || window.location.origin;\n Amplify.configure({\n Auth: {\n Cognito: {\n userPoolId: this.cognitoConfig.userPoolId,\n userPoolClientId: this.cognitoConfig.userPoolClientId,\n loginWith: {\n oauth: {\n domain: this.cognitoConfig.domain,\n scopes: this.cognitoConfig.scopes || ['openid', 'profile', 'email', 'aws.cognito.signin.user.admin'],\n redirectSignIn: [redirectUri],\n redirectSignOut: [redirectUri],\n responseType: 'code', // Authorization code + PKCE for refresh tokens\n }\n }\n }\n }\n });\n }\n\n // ============================================================================\n // LIFECYCLE METHODS\n // ============================================================================\n\n async initialize(): Promise<void> {\n if (this._initialized) {\n return;\n }\n\n // CRITICAL: Skip Amplify's redirect handling on the MCP OAuth callback path.\n // The /oauth/callback path is used by MCP OAuth, not Cognito. If we don't skip,\n // Amplify will consume the authorization code and prevent the MCP OAuth flow.\n if (this.cognitoConfig.skipRedirectCallback) {\n this._initialized = true;\n return;\n }\n\n // Set up Hub listener for reactive auth events\n this._hubListenerCancel = Hub.listen('auth', async ({ payload }) => {\n switch (payload.event) {\n case 'signedIn':\n this.updateAuthState(true);\n await this.refreshUserInfo();\n break;\n case 'signedOut':\n this.updateAuthState(false);\n this.updateUserInfo(null);\n break;\n case 'tokenRefresh':\n console.log('[Cognito] Token refreshed successfully');\n break;\n case 'tokenRefresh_failure':\n console.warn('[Cognito] Token refresh failed');\n break;\n case 'signInWithRedirect':\n console.log('[Cognito] OAuth redirect sign-in completed');\n break;\n case 'signInWithRedirect_failure':\n console.error('[Cognito] OAuth redirect sign-in failed');\n break;\n }\n });\n\n // Check for existing session (page refresh or returning from redirect)\n try {\n const user = await getCurrentUser();\n if (user) {\n this.updateAuthState(true);\n await this.refreshUserInfo();\n }\n } catch {\n // Not authenticated — this is expected on fresh visits\n this.updateAuthState(false);\n }\n\n this._initialized = true;\n }\n\n protected async loginInternal(_options?: Record<string, unknown>): Promise<void> {\n await this.ensureInitialized();\n // Redirect to Cognito Hosted UI. This navigates the browser and never returns.\n await signInWithRedirect();\n }\n\n protected async logoutInternal(): Promise<void> {\n this.updateAuthState(false);\n this.updateUserInfo(null);\n\n // Cancel Hub listener before sign-out to avoid race conditions\n this.cancelHubListener();\n\n await signOut();\n // signOut() clears local tokens. With Hosted UI, it also redirects to the\n // Cognito logout endpoint to clear the Hosted UI session cookie.\n }\n\n async handleCallback(): Promise<void> {\n // Amplify v6 handles OAuth code exchange automatically when it detects\n // ?code= and ?state= in the URL during initialization. The Hub listener\n // catches 'signInWithRedirect' events. This method exists for interface\n // compatibility.\n try {\n const user = await getCurrentUser();\n if (user) {\n this.updateAuthState(true);\n await this.refreshUserInfo();\n }\n } catch {\n // Not authenticated after callback\n }\n }\n\n // ============================================================================\n // ABSTRACT METHOD IMPLEMENTATIONS (v3.0.0)\n // ============================================================================\n\n /**\n * Extract ID token from Cognito via Amplify's fetchAuthSession.\n *\n * Cognito stores the JWT in session.tokens.idToken. The .toString()\n * call extracts the raw JWT string. Consumers never need to know this detail.\n */\n protected async extractIdTokenInternal(): Promise<string | null> {\n try {\n const session = await fetchAuthSession();\n return session.tokens?.idToken?.toString() || null;\n } catch (error) {\n console.error('[Cognito] Error extracting ID token:', error);\n return null;\n }\n }\n\n /**\n * Extract complete token info from Cognito session.\n * Maps Amplify's token structure to StandardAuthToken.\n */\n protected async extractTokenInfoInternal(): Promise<StandardAuthToken | null> {\n try {\n const session = await fetchAuthSession();\n const idToken = session.tokens?.idToken;\n if (!idToken) {\n return null;\n }\n\n const payload = idToken.payload;\n const accessToken = session.tokens?.accessToken;\n\n return {\n idToken: idToken.toString(),\n accessToken: accessToken?.toString(),\n expiresAt: payload?.exp ? (payload.exp as number) * 1000 : 0, // Convert to ms\n scopes: this.extractScopes(accessToken)\n };\n } catch (error) {\n console.error('[Cognito] Error extracting token info:', error);\n return null;\n }\n }\n\n /**\n * Extract user info from Cognito user attributes.\n * Maps Cognito's attribute structure to StandardUserInfo.\n */\n protected async extractUserInfoInternal(): Promise<StandardUserInfo | null> {\n try {\n const user = await getCurrentUser();\n const attributes = await fetchUserAttributes();\n\n return this.mapCognitoAttributesToStandard(user, attributes);\n } catch (error) {\n console.error('[Cognito] Error extracting user info:', error);\n return null;\n }\n }\n\n /**\n * Refresh token using Amplify's fetchAuthSession with forceRefresh.\n *\n * Amplify v6 handles the entire refresh token exchange internally:\n * fetchAuthSession({ forceRefresh: true }) uses the stored refresh token\n * to obtain new ID and access tokens from Cognito.\n */\n protected async refreshTokenInternal(): Promise<TokenRefreshResult> {\n try {\n console.log('[Cognito] Attempting to refresh token...');\n\n const session = await fetchAuthSession({ forceRefresh: true });\n const idToken = session.tokens?.idToken;\n\n if (!idToken) {\n return {\n success: false,\n error: {\n type: AuthErrorType.NO_ACTIVE_SESSION,\n message: 'Token refresh succeeded but no ID token returned',\n userMessage: 'Session refresh failed. Please log in again.'\n }\n };\n }\n\n const payload = idToken.payload;\n const accessToken = session.tokens?.accessToken;\n\n console.log('[Cognito] Token refresh successful', {\n expiresAt: payload?.exp ? new Date((payload.exp as number) * 1000).toISOString() : 'N/A'\n });\n\n return {\n success: true,\n token: {\n idToken: idToken.toString(),\n accessToken: accessToken?.toString(),\n expiresAt: payload?.exp ? (payload.exp as number) * 1000 : 0,\n scopes: this.extractScopes(accessToken)\n }\n };\n } catch (error) {\n console.error('[Cognito] Token refresh failed:', error);\n return {\n success: false,\n error: this.classifyErrorInternal(error)\n };\n }\n }\n\n /**\n * Classify Cognito/Amplify-specific errors into semantic types.\n *\n * Maps Amplify v6 error names and messages to AuthErrorType enum.\n */\n protected classifyErrorInternal(error: unknown): StandardAuthError {\n const errorObj = error as Record<string, unknown>;\n const message = (errorObj?.['message'] as string) || 'Unknown error';\n const name = (errorObj?.['name'] as string) || '';\n\n // Not authenticated / no session\n if (name === 'UserUnAuthenticatedException' ||\n message.includes('not authenticated') ||\n message.includes('No current user') ||\n name === 'UserNotFoundException') {\n return {\n type: AuthErrorType.NO_ACTIVE_SESSION,\n message,\n originalError: error,\n userMessage: 'You need to log in to continue.'\n };\n }\n\n // Token expired / invalid refresh token\n if (name === 'NotAuthorizedException' ||\n message.includes('not authorized') ||\n message.includes('Invalid Refresh Token') ||\n message.includes('expired') ||\n message.includes('invalid_grant')) {\n return {\n type: AuthErrorType.TOKEN_EXPIRED,\n message,\n originalError: error,\n userMessage: 'Your session has expired. Please log in again.'\n };\n }\n\n // User cancelled login\n if (message.includes('cancelled') || message.includes('canceled') ||\n message.includes('user denied')) {\n return {\n type: AuthErrorType.USER_CANCELLED,\n message,\n originalError: error,\n userMessage: 'Login was cancelled.'\n };\n }\n\n // Network errors\n if (message.includes('network') || message.includes('fetch') ||\n message.includes('Network') || message.includes('Load failed')) {\n return {\n type: AuthErrorType.NETWORK_ERROR,\n message,\n originalError: error,\n userMessage: 'Network error. Please check your connection and try again.'\n };\n }\n\n // OAuth configuration errors\n if (name === 'OAuthNotConfigureException' ||\n name === 'AuthTokenConfigException' ||\n message.includes('OAuth') || message.includes('configuration')) {\n return {\n type: AuthErrorType.CONFIGURATION_ERROR,\n message,\n originalError: error,\n userMessage: 'Authentication configuration error. Please contact support.'\n };\n }\n\n // Default to unknown\n return {\n type: AuthErrorType.UNKNOWN_ERROR,\n message,\n originalError: error,\n userMessage: 'An unexpected error occurred. Please try again.'\n };\n }\n\n /**\n * Get profile picture URL from Cognito user attributes.\n *\n * Cognito can store a `picture` attribute if configured in the user pool.\n * Returns null if the attribute is not set.\n */\n protected async getProfilePictureUrlInternal(): Promise<string | null> {\n try {\n const attributes = await fetchUserAttributes();\n return attributes.picture || null;\n } catch (error) {\n console.error('[Cognito] Error getting profile picture:', error);\n return null;\n }\n }\n\n /**\n * Handle session expiry by redirecting to Cognito Hosted UI.\n *\n * Cognito uses refresh tokens (responseType: 'code'), so silent refresh\n * usually works. If it fails, we redirect to the Hosted UI for\n * re-authentication. This will navigate the browser and may never return.\n */\n protected async handleSessionExpiryInternal(): Promise<void> {\n console.log('[Cognito] Session expired, redirecting to Hosted UI for re-authentication');\n await signInWithRedirect();\n // This redirects the page and never returns\n }\n\n // ============================================================================\n // HELPER METHODS\n // ============================================================================\n\n private async ensureInitialized(): Promise<void> {\n if (!this._initialized) {\n await this.initialize();\n }\n }\n\n /**\n * Refresh user info from Cognito and update the reactive state.\n */\n private async refreshUserInfo(): Promise<void> {\n try {\n const userInfo = await this.extractUserInfoInternal();\n if (userInfo) {\n this.updateUserInfo(userInfo);\n }\n } catch (error) {\n console.warn('[Cognito] Failed to refresh user info:', error);\n }\n }\n\n /**\n * Map Cognito user attributes to StandardUserInfo.\n *\n * Cognito attributes use snake_case keys (email, given_name, family_name, etc.)\n * and all values are strings (including booleans like email_verified = 'true').\n */\n private mapCognitoAttributesToStandard(\n user: { userId: string; username: string; signInDetails?: { loginId?: string } },\n attributes: Partial<Record<string, string>>\n ): StandardUserInfo {\n const givenName = attributes['given_name'];\n const familyName = attributes['family_name'];\n const fullName = attributes['name'] ||\n (givenName && familyName ? `${givenName} ${familyName}` : givenName || familyName || '');\n\n return {\n id: user.userId || user.username,\n email: attributes['email'] || '',\n name: fullName,\n givenName,\n familyName,\n preferredUsername: attributes['preferred_username'] || user.username,\n pictureUrl: attributes['picture'],\n emailVerified: attributes['email_verified'] === 'true',\n locale: attributes['locale'],\n };\n }\n\n /**\n * Extract OAuth scopes from an access token's payload.\n */\n private extractScopes(accessToken: { payload?: Record<string, unknown> } | undefined): string[] | undefined {\n const scope = accessToken?.payload?.['scope'];\n if (typeof scope === 'string') {\n return scope.split(' ');\n }\n return undefined;\n }\n\n /**\n * Cancel the Hub event listener if active.\n */\n private cancelHubListener(): void {\n if (this._hubListenerCancel) {\n this._hubListenerCancel();\n this._hubListenerCancel = null;\n }\n }\n\n // ============================================================================\n // CONFIGURATION\n // ============================================================================\n\n override getRequiredConfig(): string[] {\n return ['userPoolId', 'userPoolClientId', 'domain'];\n }\n\n override validateConfig(config: Record<string, unknown>): boolean {\n return !!(config['userPoolId'] && config['userPoolClientId'] && config['domain']);\n }\n}\n"]}
1
+ {"version":3,"file":"mjexplorer-cognito-provider.service.js","sourceRoot":"","sources":["../../../src/lib/providers/mjexplorer-cognito-provider.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Inject } from '@angular/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { MJAuthBase } from '../mjexplorer-auth-base.service';\nimport { AngularAuthProviderConfig } from '../IAuthProvider';\nimport { Amplify } from 'aws-amplify';\nimport {\n signInWithRedirect,\n signOut,\n fetchAuthSession,\n getCurrentUser,\n fetchUserAttributes\n} from 'aws-amplify/auth';\nimport { Hub } from 'aws-amplify/utils';\nimport {\n StandardUserInfo,\n StandardAuthToken,\n StandardAuthError,\n AuthErrorType,\n TokenRefreshResult\n} from '../auth-types';\n\n/**\n * Configuration interface for the Cognito provider.\n * Populated from environment config via the `angularProviderFactory`.\n */\ninterface CognitoConfig {\n userPoolId: string;\n userPoolClientId: string;\n region?: string;\n /** Cognito Hosted UI domain, e.g. 'myapp.auth.us-east-1.amazoncognito.com' */\n domain: string;\n /** OAuth redirect URI. Defaults to window.location.origin */\n redirectUri?: string;\n /** OAuth scopes. Defaults to ['openid', 'profile', 'email'] */\n scopes?: string[];\n /** When true, skips redirect callback processing (for MCP OAuth callback path) */\n skipRedirectCallback?: boolean;\n}\n\n/**\n * AWS Cognito authentication provider implementation - v3.0.0\n *\n * Implements the abstract methods from MJAuthBase to hide Cognito-specific details.\n * Uses AWS Amplify v6 (tree-shakeable subpath imports) for authentication.\n *\n * Key abstraction: Cognito stores tokens in Amplify's internal storage, accessed\n * via `fetchAuthSession().tokens?.idToken?.toString()`. Consumers never need to\n * know this detail.\n *\n * ## Cognito Hosted UI Flow\n * This provider uses the Cognito Hosted UI for login via `signInWithRedirect()`.\n * The flow is: redirect to Hosted UI -> user authenticates -> redirect back with\n * authorization code -> Amplify exchanges code for tokens (PKCE).\n */\n@Injectable({\n providedIn: 'root'\n})\n@RegisterClass(MJAuthBase, 'cognito')\nexport class MJCognitoProvider extends MJAuthBase {\n static readonly PROVIDER_TYPE = 'cognito';\n readonly type = MJCognitoProvider.PROVIDER_TYPE;\n private _initialized = false;\n private _hubListenerCancel: (() => void) | null = null;\n\n /**\n * Factory function to provide Angular dependencies required by the Cognito provider.\n * Returns a config injection token following the Okta provider pattern.\n */\n static angularProviderFactory = (environment: Record<string, unknown>) => {\n const isMCPOAuthCallback = window.location.pathname.startsWith('/oauth/callback');\n\n return [\n {\n provide: 'cognitoConfig',\n useValue: {\n userPoolId: environment['COGNITO_USER_POOL_ID'],\n // COGNITO_CLIENTID first: it is the key the catalog overlay emits for a metadata-configured\n // row, and it must beat the compiled environment's canonical COGNITO_CLIENT_ID spelling —\n // otherwise a catalog row's ClientID is silently ignored in favour of the compiled value.\n userPoolClientId: environment['COGNITO_CLIENTID'] || environment['COGNITO_CLIENT_ID'],\n region: environment['COGNITO_REGION'] || environment['AWS_REGION'],\n domain: environment['COGNITO_DOMAIN'],\n redirectUri: environment['COGNITO_REDIRECT_URI'] || window.location.origin,\n scopes: environment['COGNITO_SCOPES'] || ['openid', 'profile', 'email', 'aws.cognito.signin.user.admin'],\n skipRedirectCallback: isMCPOAuthCallback,\n } as CognitoConfig\n }\n ];\n };\n\n constructor(@Inject('cognitoConfig') private cognitoConfig: CognitoConfig) {\n const config: AngularAuthProviderConfig = {\n name: MJCognitoProvider.PROVIDER_TYPE,\n type: MJCognitoProvider.PROVIDER_TYPE\n };\n super(config);\n\n // Configure Amplify with the existing Cognito User Pool\n const redirectUri = this.cognitoConfig.redirectUri || window.location.origin;\n Amplify.configure({\n Auth: {\n Cognito: {\n userPoolId: this.cognitoConfig.userPoolId,\n userPoolClientId: this.cognitoConfig.userPoolClientId,\n loginWith: {\n oauth: {\n domain: this.cognitoConfig.domain,\n scopes: this.cognitoConfig.scopes || ['openid', 'profile', 'email', 'aws.cognito.signin.user.admin'],\n redirectSignIn: [redirectUri],\n redirectSignOut: [redirectUri],\n responseType: 'code', // Authorization code + PKCE for refresh tokens\n }\n }\n }\n }\n });\n }\n\n // ============================================================================\n // LIFECYCLE METHODS\n // ============================================================================\n\n async initialize(): Promise<void> {\n if (this._initialized) {\n return;\n }\n\n // CRITICAL: Skip Amplify's redirect handling on the MCP OAuth callback path.\n // The /oauth/callback path is used by MCP OAuth, not Cognito. If we don't skip,\n // Amplify will consume the authorization code and prevent the MCP OAuth flow.\n if (this.cognitoConfig.skipRedirectCallback) {\n this._initialized = true;\n return;\n }\n\n // Set up Hub listener for reactive auth events\n this._hubListenerCancel = Hub.listen('auth', async ({ payload }) => {\n switch (payload.event) {\n case 'signedIn':\n this.updateAuthState(true);\n await this.refreshUserInfo();\n break;\n case 'signedOut':\n this.updateAuthState(false);\n this.updateUserInfo(null);\n break;\n case 'tokenRefresh':\n console.log('[Cognito] Token refreshed successfully');\n break;\n case 'tokenRefresh_failure':\n console.warn('[Cognito] Token refresh failed');\n break;\n case 'signInWithRedirect':\n console.log('[Cognito] OAuth redirect sign-in completed');\n break;\n case 'signInWithRedirect_failure':\n console.error('[Cognito] OAuth redirect sign-in failed');\n break;\n }\n });\n\n // Check for existing session (page refresh or returning from redirect)\n try {\n const user = await getCurrentUser();\n if (user) {\n this.updateAuthState(true);\n await this.refreshUserInfo();\n }\n } catch {\n // Not authenticated — this is expected on fresh visits\n this.updateAuthState(false);\n }\n\n this._initialized = true;\n }\n\n protected async loginInternal(_options?: Record<string, unknown>): Promise<void> {\n await this.ensureInitialized();\n // Redirect to Cognito Hosted UI. This navigates the browser and never returns.\n await signInWithRedirect();\n }\n\n protected async logoutInternal(): Promise<void> {\n this.updateAuthState(false);\n this.updateUserInfo(null);\n\n // Cancel Hub listener before sign-out to avoid race conditions\n this.cancelHubListener();\n\n await signOut();\n // signOut() clears local tokens. With Hosted UI, it also redirects to the\n // Cognito logout endpoint to clear the Hosted UI session cookie.\n }\n\n async handleCallback(): Promise<void> {\n // Amplify v6 handles OAuth code exchange automatically when it detects\n // ?code= and ?state= in the URL during initialization. The Hub listener\n // catches 'signInWithRedirect' events. This method exists for interface\n // compatibility.\n try {\n const user = await getCurrentUser();\n if (user) {\n this.updateAuthState(true);\n await this.refreshUserInfo();\n }\n } catch {\n // Not authenticated after callback\n }\n }\n\n // ============================================================================\n // ABSTRACT METHOD IMPLEMENTATIONS (v3.0.0)\n // ============================================================================\n\n /**\n * Extract ID token from Cognito via Amplify's fetchAuthSession.\n *\n * Cognito stores the JWT in session.tokens.idToken. The .toString()\n * call extracts the raw JWT string. Consumers never need to know this detail.\n */\n protected async extractIdTokenInternal(): Promise<string | null> {\n try {\n const session = await fetchAuthSession();\n return session.tokens?.idToken?.toString() || null;\n } catch (error) {\n console.error('[Cognito] Error extracting ID token:', error);\n return null;\n }\n }\n\n /**\n * Extract complete token info from Cognito session.\n * Maps Amplify's token structure to StandardAuthToken.\n */\n protected async extractTokenInfoInternal(): Promise<StandardAuthToken | null> {\n try {\n const session = await fetchAuthSession();\n const idToken = session.tokens?.idToken;\n if (!idToken) {\n return null;\n }\n\n const payload = idToken.payload;\n const accessToken = session.tokens?.accessToken;\n\n return {\n idToken: idToken.toString(),\n accessToken: accessToken?.toString(),\n expiresAt: payload?.exp ? (payload.exp as number) * 1000 : 0, // Convert to ms\n scopes: this.extractScopes(accessToken)\n };\n } catch (error) {\n console.error('[Cognito] Error extracting token info:', error);\n return null;\n }\n }\n\n /**\n * Extract user info from Cognito user attributes.\n * Maps Cognito's attribute structure to StandardUserInfo.\n */\n protected async extractUserInfoInternal(): Promise<StandardUserInfo | null> {\n try {\n const user = await getCurrentUser();\n const attributes = await fetchUserAttributes();\n\n return this.mapCognitoAttributesToStandard(user, attributes);\n } catch (error) {\n console.error('[Cognito] Error extracting user info:', error);\n return null;\n }\n }\n\n /**\n * Refresh token using Amplify's fetchAuthSession with forceRefresh.\n *\n * Amplify v6 handles the entire refresh token exchange internally:\n * fetchAuthSession({ forceRefresh: true }) uses the stored refresh token\n * to obtain new ID and access tokens from Cognito.\n */\n protected async refreshTokenInternal(): Promise<TokenRefreshResult> {\n try {\n console.log('[Cognito] Attempting to refresh token...');\n\n const session = await fetchAuthSession({ forceRefresh: true });\n const idToken = session.tokens?.idToken;\n\n if (!idToken) {\n return {\n success: false,\n error: {\n type: AuthErrorType.NO_ACTIVE_SESSION,\n message: 'Token refresh succeeded but no ID token returned',\n userMessage: 'Session refresh failed. Please log in again.'\n }\n };\n }\n\n const payload = idToken.payload;\n const accessToken = session.tokens?.accessToken;\n\n console.log('[Cognito] Token refresh successful', {\n expiresAt: payload?.exp ? new Date((payload.exp as number) * 1000).toISOString() : 'N/A'\n });\n\n return {\n success: true,\n token: {\n idToken: idToken.toString(),\n accessToken: accessToken?.toString(),\n expiresAt: payload?.exp ? (payload.exp as number) * 1000 : 0,\n scopes: this.extractScopes(accessToken)\n }\n };\n } catch (error) {\n console.error('[Cognito] Token refresh failed:', error);\n return {\n success: false,\n error: this.classifyErrorInternal(error)\n };\n }\n }\n\n /**\n * Classify Cognito/Amplify-specific errors into semantic types.\n *\n * Maps Amplify v6 error names and messages to AuthErrorType enum.\n */\n protected classifyErrorInternal(error: unknown): StandardAuthError {\n const errorObj = error as Record<string, unknown>;\n const message = (errorObj?.['message'] as string) || 'Unknown error';\n const name = (errorObj?.['name'] as string) || '';\n\n // Not authenticated / no session\n if (name === 'UserUnAuthenticatedException' ||\n message.includes('not authenticated') ||\n message.includes('No current user') ||\n name === 'UserNotFoundException') {\n return {\n type: AuthErrorType.NO_ACTIVE_SESSION,\n message,\n originalError: error,\n userMessage: 'You need to log in to continue.'\n };\n }\n\n // Token expired / invalid refresh token\n if (name === 'NotAuthorizedException' ||\n message.includes('not authorized') ||\n message.includes('Invalid Refresh Token') ||\n message.includes('expired') ||\n message.includes('invalid_grant')) {\n return {\n type: AuthErrorType.TOKEN_EXPIRED,\n message,\n originalError: error,\n userMessage: 'Your session has expired. Please log in again.'\n };\n }\n\n // User cancelled login\n if (message.includes('cancelled') || message.includes('canceled') ||\n message.includes('user denied')) {\n return {\n type: AuthErrorType.USER_CANCELLED,\n message,\n originalError: error,\n userMessage: 'Login was cancelled.'\n };\n }\n\n // Network errors\n if (message.includes('network') || message.includes('fetch') ||\n message.includes('Network') || message.includes('Load failed')) {\n return {\n type: AuthErrorType.NETWORK_ERROR,\n message,\n originalError: error,\n userMessage: 'Network error. Please check your connection and try again.'\n };\n }\n\n // OAuth configuration errors\n if (name === 'OAuthNotConfigureException' ||\n name === 'AuthTokenConfigException' ||\n message.includes('OAuth') || message.includes('configuration')) {\n return {\n type: AuthErrorType.CONFIGURATION_ERROR,\n message,\n originalError: error,\n userMessage: 'Authentication configuration error. Please contact support.'\n };\n }\n\n // Default to unknown\n return {\n type: AuthErrorType.UNKNOWN_ERROR,\n message,\n originalError: error,\n userMessage: 'An unexpected error occurred. Please try again.'\n };\n }\n\n /**\n * Get profile picture URL from Cognito user attributes.\n *\n * Cognito can store a `picture` attribute if configured in the user pool.\n * Returns null if the attribute is not set.\n */\n protected async getProfilePictureUrlInternal(): Promise<string | null> {\n try {\n const attributes = await fetchUserAttributes();\n return attributes.picture || null;\n } catch (error) {\n console.error('[Cognito] Error getting profile picture:', error);\n return null;\n }\n }\n\n /**\n * Handle session expiry by redirecting to Cognito Hosted UI.\n *\n * Cognito uses refresh tokens (responseType: 'code'), so silent refresh\n * usually works. If it fails, we redirect to the Hosted UI for\n * re-authentication. This will navigate the browser and may never return.\n */\n protected async handleSessionExpiryInternal(): Promise<void> {\n console.log('[Cognito] Session expired, redirecting to Hosted UI for re-authentication');\n await signInWithRedirect();\n // This redirects the page and never returns\n }\n\n // ============================================================================\n // HELPER METHODS\n // ============================================================================\n\n private async ensureInitialized(): Promise<void> {\n if (!this._initialized) {\n await this.initialize();\n }\n }\n\n /**\n * Refresh user info from Cognito and update the reactive state.\n */\n private async refreshUserInfo(): Promise<void> {\n try {\n const userInfo = await this.extractUserInfoInternal();\n if (userInfo) {\n this.updateUserInfo(userInfo);\n }\n } catch (error) {\n console.warn('[Cognito] Failed to refresh user info:', error);\n }\n }\n\n /**\n * Map Cognito user attributes to StandardUserInfo.\n *\n * Cognito attributes use snake_case keys (email, given_name, family_name, etc.)\n * and all values are strings (including booleans like email_verified = 'true').\n */\n private mapCognitoAttributesToStandard(\n user: { userId: string; username: string; signInDetails?: { loginId?: string } },\n attributes: Partial<Record<string, string>>\n ): StandardUserInfo {\n const givenName = attributes['given_name'];\n const familyName = attributes['family_name'];\n const fullName = attributes['name'] ||\n (givenName && familyName ? `${givenName} ${familyName}` : givenName || familyName || '');\n\n return {\n id: user.userId || user.username,\n email: attributes['email'] || '',\n name: fullName,\n givenName,\n familyName,\n preferredUsername: attributes['preferred_username'] || user.username,\n pictureUrl: attributes['picture'],\n emailVerified: attributes['email_verified'] === 'true',\n locale: attributes['locale'],\n };\n }\n\n /**\n * Extract OAuth scopes from an access token's payload.\n */\n private extractScopes(accessToken: { payload?: Record<string, unknown> } | undefined): string[] | undefined {\n const scope = accessToken?.payload?.['scope'];\n if (typeof scope === 'string') {\n return scope.split(' ');\n }\n return undefined;\n }\n\n /**\n * Cancel the Hub event listener if active.\n */\n private cancelHubListener(): void {\n if (this._hubListenerCancel) {\n this._hubListenerCancel();\n this._hubListenerCancel = null;\n }\n }\n\n // ============================================================================\n // CONFIGURATION\n // ============================================================================\n\n override getRequiredConfig(): string[] {\n return ['userPoolId', 'userPoolClientId', 'domain'];\n }\n\n override validateConfig(config: Record<string, unknown>): boolean {\n return !!(config['userPoolId'] && config['userPoolClientId'] && config['domain']);\n }\n}\n"]}
@@ -2,6 +2,7 @@ import { OnDestroy } from '@angular/core';
2
2
  import { MJAuthBase } from '../mjexplorer-auth-base.service';
3
3
  import { MsalBroadcastService, MsalService, MsalGuard } from '@azure/msal-angular';
4
4
  import { PublicClientApplication, InteractionType } from '@azure/msal-browser';
5
+ import { type PublicAuthProviderInfo } from '@memberjunction/core';
5
6
  import { StandardUserInfo, StandardAuthToken, StandardAuthError, TokenRefreshResult } from '../auth-types';
6
7
  import * as i0 from "@angular/core";
7
8
  /**
@@ -43,6 +44,21 @@ export declare class MJMSALProvider extends MJAuthBase implements OnDestroy {
43
44
  authRequest?: undefined;
44
45
  };
45
46
  })[];
47
+ /**
48
+ * Maps a catalog row onto the unprefixed keys `angularProviderFactory` reads (`CLIENT_ID` /
49
+ * `CLIENT_AUTHORITY`), which predate the `<DRIVER>_*` convention the generic overlay emits —
50
+ * without this mapping a metadata-configured row would be silently ignored in favour of the
51
+ * compiled environment.
52
+ *
53
+ * The authority comes from `ClientConfiguration.authority` when the row supplies one; otherwise
54
+ * it is derived from the Issuer by stripping the trailing `/v2.0` — an Entra issuer is
55
+ * `https://login.microsoftonline.com/<tenantId>/v2.0`, and MSAL's authority is that same URL
56
+ * without the version suffix. That derivation only holds for standard Entra tenants: rows for
57
+ * Azure AD B2C or v1 `sts.windows.net` issuers must set `ClientConfiguration.authority`
58
+ * explicitly, because their issuer is not a usable authority (and B2C additionally needs
59
+ * `knownAuthorities`, which this driver does not yet plumb).
60
+ */
61
+ static EnvironmentFromCatalog(info: PublicAuthProviderInfo): Record<string, unknown>;
46
62
  constructor(auth: MsalService, msalBroadcastService: MsalBroadcastService);
47
63
  initialize(): Promise<void>;
48
64
  private _performInitialization;
@@ -1 +1 @@
1
- {"version":3,"file":"mjexplorer-msal-provider.service.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/mjexplorer-msal-provider.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,SAAS,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAE7D,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAA6D,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAE9I,OAAO,EAAuF,uBAAuB,EAAE,eAAe,EAAoB,MAAM,qBAAqB,CAAC;AAGtL,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EAEjB,kBAAkB,EACnB,MAAM,eAAe,CAAC;;AACvB;;;;;;GAMG;AACH,qBAIa,cAAe,SAAQ,UAAW,YAAW,SAAS;IA+C9C,IAAI,EAAE,WAAW;IAAE,OAAO,CAAC,oBAAoB;IA9ClE,MAAM,CAAC,QAAQ,CAAC,aAAa,UAAU;IACvC,QAAQ,CAAC,IAAI,UAAgC;IAE7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAuB;IACpD,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAuC;IACjF,OAAO,CAAC,YAAY,CAA8B;IAElD;;;OAGG;IACH,MAAM,CAAC,sBAAsB,GAAI,aAAa,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;;;;;;;;SAiCnE;gBAEiB,IAAI,EAAE,WAAW,EAAU,oBAAoB,EAAE,oBAAoB;IAYlF,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YASnB,sBAAsB;cAkEpB,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;cAqB/D,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAOzC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrC;;;;;OAKG;cACa,sBAAsB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAkDhE;;;;OAIG;cACa,wBAAwB,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IA4C7E;;;;OAIG;cACa,uBAAuB,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAgB3E;;;;;;;;;;;;;OAaG;cACa,oBAAoB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAwGnE;;;;;OAKG;IACH,SAAS,CAAC,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB;YAiHpD,iBAAiB;IAQ/B;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;IAepB;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAYhC;;;;;;OAMG;cACa,4BAA4B,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAqCtE;;;;;;OAMG;cACa,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBnD,iBAAiB,IAAI,MAAM,EAAE;IAI7B,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO;IASlE,WAAW,IAAI,IAAI;yCA3pBR,cAAc;6CAAd,cAAc;CAiqB1B"}
1
+ {"version":3,"file":"mjexplorer-msal-provider.service.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/mjexplorer-msal-provider.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,SAAS,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAE7D,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAA6D,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAE9I,OAAO,EAAuF,uBAAuB,EAAE,eAAe,EAAoB,MAAM,qBAAqB,CAAC;AACtL,OAAO,EAAY,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE7E,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EAEjB,kBAAkB,EACnB,MAAM,eAAe,CAAC;;AACvB;;;;;;GAMG;AACH,qBAIa,cAAe,SAAQ,UAAW,YAAW,SAAS;IAgF9C,IAAI,EAAE,WAAW;IAAE,OAAO,CAAC,oBAAoB;IA/ElE,MAAM,CAAC,QAAQ,CAAC,aAAa,UAAU;IACvC,QAAQ,CAAC,IAAI,UAAgC;IAE7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAuB;IACpD,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAuC;IACjF,OAAO,CAAC,YAAY,CAA8B;IAElD;;;OAGG;IACH,MAAM,CAAC,sBAAsB,GAAI,aAAa,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;;;;;;;;SAiCnE;IAEF;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,sBAAsB,CAAC,IAAI,EAAE,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBAmBjE,IAAI,EAAE,WAAW,EAAU,oBAAoB,EAAE,oBAAoB;IAYlF,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YASnB,sBAAsB;cAkEpB,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;cAqB/D,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAOzC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrC;;;;;OAKG;cACa,sBAAsB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAkDhE;;;;OAIG;cACa,wBAAwB,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IA4C7E;;;;OAIG;cACa,uBAAuB,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAgB3E;;;;;;;;;;;;;OAaG;cACa,oBAAoB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAwGnE;;;;;OAKG;IACH,SAAS,CAAC,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB;YAiHpD,iBAAiB;IAQ/B;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;IAepB;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAYhC;;;;;;OAMG;cACa,4BAA4B,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAqCtE;;;;;;OAMG;cACa,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBnD,iBAAiB,IAAI,MAAM,EAAE;IAI7B,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO;IASlE,WAAW,IAAI,IAAI;yCA5rBR,cAAc;6CAAd,cAAc;CAksB1B"}
@@ -69,6 +69,34 @@ let MJMSALProvider = class MJMSALProvider extends MJAuthBase {
69
69
  MsalGuard,
70
70
  MsalBroadcastService
71
71
  ];
72
+ /**
73
+ * Maps a catalog row onto the unprefixed keys `angularProviderFactory` reads (`CLIENT_ID` /
74
+ * `CLIENT_AUTHORITY`), which predate the `<DRIVER>_*` convention the generic overlay emits —
75
+ * without this mapping a metadata-configured row would be silently ignored in favour of the
76
+ * compiled environment.
77
+ *
78
+ * The authority comes from `ClientConfiguration.authority` when the row supplies one; otherwise
79
+ * it is derived from the Issuer by stripping the trailing `/v2.0` — an Entra issuer is
80
+ * `https://login.microsoftonline.com/<tenantId>/v2.0`, and MSAL's authority is that same URL
81
+ * without the version suffix. That derivation only holds for standard Entra tenants: rows for
82
+ * Azure AD B2C or v1 `sts.windows.net` issuers must set `ClientConfiguration.authority`
83
+ * explicitly, because their issuer is not a usable authority (and B2C additionally needs
84
+ * `knownAuthorities`, which this driver does not yet plumb).
85
+ */
86
+ static EnvironmentFromCatalog(info) {
87
+ const overlay = {};
88
+ if (info.clientId) {
89
+ overlay['CLIENT_ID'] = info.clientId;
90
+ }
91
+ const configuredAuthority = info.clientConfiguration?.['authority'];
92
+ const authority = typeof configuredAuthority === 'string' && configuredAuthority.length > 0
93
+ ? configuredAuthority
94
+ : info.issuer?.replace(/\/v2\.0\/?$/, '');
95
+ if (authority) {
96
+ overlay['CLIENT_AUTHORITY'] = authority;
97
+ }
98
+ return overlay;
99
+ }
72
100
  constructor(auth, msalBroadcastService) {
73
101
  const config = {
74
102
  name: MJMSALProvider_1.PROVIDER_TYPE,