@phila/sso-vue 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -216,6 +216,7 @@ export declare function useBrokerAuth(): {
216
216
  idp_sub?: string | undefined;
217
217
  } | null>;
218
218
  token: Ref<string | null, string | null>;
219
+ setupPasskeyToken: Ref<string | null, string | null>;
219
220
  error: Ref<Error | null, Error | null>;
220
221
  authReady: Ref<boolean, boolean>;
221
222
  userName: ComputedRef<string | null>;
@@ -250,10 +251,11 @@ idp?: string | undefined;
250
251
  idp_sub?: string | undefined;
251
252
  } | null>;
252
253
  token: Ref<string | null, string | null>;
254
+ setupPasskeyToken: Ref<string | null, string | null>;
253
255
  error: Ref<Error | null, Error | null>;
254
256
  authReady: Ref<boolean, boolean>;
255
257
  syncState: (state: BrokerClientState) => void;
256
- }, "user" | "isAuthenticated" | "isLoading" | "token" | "error" | "authReady">, Pick<{
258
+ }, "user" | "isAuthenticated" | "isLoading" | "token" | "error" | "authReady" | "setupPasskeyToken">, Pick<{
257
259
  isAuthenticated: Ref<boolean, boolean>;
258
260
  isLoading: Ref<boolean, boolean>;
259
261
  user: Ref< {
@@ -274,6 +276,7 @@ idp?: string | undefined;
274
276
  idp_sub?: string | undefined;
275
277
  } | null>;
276
278
  token: Ref<string | null, string | null>;
279
+ setupPasskeyToken: Ref<string | null, string | null>;
277
280
  error: Ref<Error | null, Error | null>;
278
281
  authReady: Ref<boolean, boolean>;
279
282
  syncState: (state: BrokerClientState) => void;
@@ -298,6 +301,7 @@ idp?: string | undefined;
298
301
  idp_sub?: string | undefined;
299
302
  } | null>;
300
303
  token: Ref<string | null, string | null>;
304
+ setupPasskeyToken: Ref<string | null, string | null>;
301
305
  error: Ref<Error | null, Error | null>;
302
306
  authReady: Ref<boolean, boolean>;
303
307
  syncState: (state: BrokerClientState) => void;
package/dist/index.js CHANGED
@@ -130,6 +130,7 @@ const useBrokerStore = pinia.defineStore("broker-sso", () => {
130
130
  const isLoading = vue.ref(false);
131
131
  const user = vue.ref(null);
132
132
  const token = vue.ref(null);
133
+ const setupPasskeyToken = vue.ref(null);
133
134
  const error = vue.ref(null);
134
135
  const authReady = vue.ref(false);
135
136
  function syncState(state) {
@@ -137,10 +138,11 @@ const useBrokerStore = pinia.defineStore("broker-sso", () => {
137
138
  isLoading.value = state.isLoading;
138
139
  user.value = state.user;
139
140
  token.value = state.token;
141
+ setupPasskeyToken.value = state.setupPasskeyToken;
140
142
  error.value = state.error;
141
143
  authReady.value = state.authReady;
142
144
  }
143
- return { isAuthenticated, isLoading, user, token, error, authReady, syncState };
145
+ return { isAuthenticated, isLoading, user, token, setupPasskeyToken, error, authReady, syncState };
144
146
  });
145
147
  function createBrokerPlugin(options) {
146
148
  return {
@@ -173,7 +175,7 @@ function useBrokerClient() {
173
175
  function useBrokerAuth() {
174
176
  const store = useBrokerStore();
175
177
  const client = useBrokerClient();
176
- const { isAuthenticated, isLoading, user, token, error, authReady } = pinia.storeToRefs(store);
178
+ const { isAuthenticated, isLoading, user, token, setupPasskeyToken, error, authReady } = pinia.storeToRefs(store);
177
179
  const userName = vue.computed(() => {
178
180
  if (!user.value) return null;
179
181
  const joined = [user.value.given_name, user.value.family_name].filter(Boolean).join(" ");
@@ -200,6 +202,7 @@ function useBrokerAuth() {
200
202
  isLoading,
201
203
  user,
202
204
  token,
205
+ setupPasskeyToken,
203
206
  error,
204
207
  authReady,
205
208
  userName,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/plugin.ts","../src/composables/useSSOClient.ts","../src/composables/useAuth.ts","../src/createB2CPlugin.ts","../src/broker-plugin.ts","../src/composables/useBrokerAuth.ts"],"sourcesContent":["import { ref } from \"vue\";\nimport { defineStore } from \"pinia\";\nimport { SSOClient } from \"@phila/sso-core\";\nimport type { App } from \"vue\";\nimport type { SSOClientConfig, SSOClientState, AuthResponse } from \"@phila/sso-core\";\n\nexport const SSO_CLIENT_KEY = Symbol(\"sso-client\");\n\nexport interface SSOPluginOptions {\n clientConfig: SSOClientConfig;\n autoInitialize?: boolean;\n}\n\nexport const useSSOStore = defineStore(\"sso\", () => {\n const isAuthenticated = ref(false);\n const isLoading = ref(false);\n const user = ref<SSOClientState[\"user\"]>(null);\n const token = ref<string | null>(null);\n const error = ref<Error | null>(null);\n const activePolicy = ref<string | null>(null);\n const authReady = ref(false);\n\n function syncState(state: SSOClientState) {\n isAuthenticated.value = state.isAuthenticated;\n isLoading.value = state.isLoading;\n user.value = state.user;\n token.value = state.token;\n error.value = state.error;\n activePolicy.value = state.activePolicy;\n authReady.value = state.authReady;\n }\n\n return { isAuthenticated, isLoading, user, token, error, activePolicy, authReady, syncState };\n});\n\nexport function createSSOPlugin(options: SSOPluginOptions) {\n return {\n install(app: App) {\n const client = new SSOClient(options.clientConfig);\n\n // Provide the client for useSSOClient()\n app.provide(SSO_CLIENT_KEY, client);\n\n // Subscribe to state changes and sync to Pinia store\n client.events.on(\"auth:stateChanged\", (state: SSOClientState) => {\n const store = useSSOStore();\n store.syncState(state);\n });\n\n // Auto-initialize unless explicitly disabled\n if (options.autoInitialize !== false) {\n client.initialize().then((response: AuthResponse | null) => {\n if (response && options.clientConfig.debug) {\n console.log(\"[sso-vue] Auto-initialized with response:\", response);\n }\n });\n }\n },\n };\n}\n","import { inject } from \"vue\";\nimport { SSOClient } from \"@phila/sso-core\";\nimport { SSO_CLIENT_KEY } from \"../plugin\";\n\n/**\n * Access the raw SSOClient instance.\n * Must be called within a component that is a descendant of createSSOPlugin.\n */\nexport function useSSOClient(): SSOClient {\n const client = inject<SSOClient>(SSO_CLIENT_KEY);\n if (!client) {\n throw new Error(\"SSOClient not found. Did you install createSSOPlugin?\");\n }\n return client;\n}\n","import { computed } from \"vue\";\nimport { storeToRefs } from \"pinia\";\nimport { useSSOStore } from \"../plugin\";\nimport { useSSOClient } from \"./useSSOClient\";\nimport type { SignInOptions, SignOutOptions, TokenOptions } from \"@phila/sso-core\";\n\n/**\n * Primary composable for SSO authentication in Vue 3 apps.\n * API shape is intentionally similar to service-cat's existing useAuth()\n * to minimize migration friction.\n */\nexport function useAuth() {\n const store = useSSOStore();\n const client = useSSOClient();\n const { isAuthenticated, isLoading, user, token, error, activePolicy, authReady } = storeToRefs(store);\n\n // Computed helpers\n const userName = computed(() => {\n const claims = user.value?.idTokenClaims as Record<string, unknown> | undefined;\n if (!claims) return null;\n const given = (claims.given_name ?? claims.name ?? \"\") as string;\n const family = (claims.family_name ?? \"\") as string;\n return family ? `${given} ${family}`.trim() : given;\n });\n\n // Actions\n async function signIn(options?: SignInOptions): Promise<void> {\n await client.signIn(options);\n }\n\n async function signInCityEmployee(options?: SignInOptions): Promise<void> {\n await client.signInCityEmployee(options);\n }\n\n async function signOut(options?: SignOutOptions): Promise<void> {\n await client.signOut(options);\n }\n\n async function forgotPassword(): Promise<void> {\n await client.forgotPassword();\n }\n\n async function acquireToken(options?: TokenOptions): Promise<string | null> {\n return client.acquireToken(options);\n }\n\n // Utilities\n function hasRole(role: string): boolean {\n const claims = user.value?.idTokenClaims as Record<string, unknown> | undefined;\n if (!claims) return false;\n\n const roles = (claims.roles ?? claims.extension_Roles ?? []) as string[];\n return Array.isArray(roles) && roles.includes(role);\n }\n\n return {\n // State (readonly refs)\n isAuthenticated,\n isLoading,\n user,\n token,\n error,\n activePolicy,\n authReady,\n userName,\n\n // Actions\n signIn,\n signInCityEmployee,\n signOut,\n forgotPassword,\n acquireToken,\n\n // Utilities\n hasRole,\n };\n}\n","// ABOUTME: Convenience factory for vanilla Vue/Vite apps using Azure AD B2C\n// ABOUTME: Reads VITE_SSO_* env vars by convention so apps need zero B2CProvider boilerplate\nimport { B2CProvider } from \"@phila/sso-core\";\nimport { createSSOPlugin } from \"./plugin\";\n\nexport interface B2CPluginOptions {\n signInPolicy?: string;\n resetPasswordPolicy?: string;\n debug?: boolean;\n}\n\n/**\n * Creates a ready-to-use Vue plugin for Azure AD B2C authentication.\n * Reads connection details from VITE_SSO_* environment variables:\n * VITE_SSO_CLIENT_ID, VITE_SSO_TENANT, VITE_SSO_AUTHORITY_DOMAIN, VITE_SSO_REDIRECT_URI\n */\nexport function createB2CPlugin(options: B2CPluginOptions = {}) {\n const {\n signInPolicy = \"B2C_1A_AD_SIGNIN_ONLY\",\n resetPasswordPolicy = \"B2C_1A_PASSWORDRESET\",\n debug = import.meta.env.DEV,\n } = options;\n\n return createSSOPlugin({\n clientConfig: {\n provider: new B2CProvider({\n clientId: import.meta.env.VITE_SSO_CLIENT_ID,\n b2cEnvironment: import.meta.env.VITE_SSO_TENANT,\n authorityDomain: import.meta.env.VITE_SSO_AUTHORITY_DOMAIN,\n redirectUri: import.meta.env.VITE_SSO_REDIRECT_URI,\n policies: {\n signUpSignIn: signInPolicy,\n signInOnly: signInPolicy,\n resetPassword: resetPasswordPolicy,\n },\n }),\n debug,\n },\n });\n}\n","// ABOUTME: Vue 3 plugin for the phila-identity broker — replaces createSSOPlugin() / useSSOStore().\n// ABOUTME: Uses BrokerClient instead of SSOClient, so there's no MSAL dependency.\n// ABOUTME:\n// ABOUTME: Store shape differences from the B2C plugin:\n// ABOUTME: - user is BrokerUser (not MSAL AccountInfo) — direct named properties, no idTokenClaims map\n// ABOUTME: - activePolicy is gone — the broker is policy-agnostic from the client's perspective\n// ABOUTME:\n// ABOUTME: Everything else (provide/inject, Pinia store, event wiring) is identical.\n\nimport { ref } from \"vue\";\nimport { defineStore } from \"pinia\";\nimport { BrokerClient } from \"@phila/sso-core\";\nimport type { App } from \"vue\";\nimport type { BrokerClientConfig, BrokerClientState } from \"@phila/sso-core\";\n\nexport const BROKER_CLIENT_KEY = Symbol(\"broker-client\");\n\n// ── Plugin options ─────────────────────────────────────────────────────────────\n\nexport interface BrokerPluginOptions {\n clientConfig: BrokerClientConfig;\n /**\n * Set false to skip the automatic initialize() call during install.\n * Useful when you want to call initialize() yourself at a specific lifecycle point.\n */\n autoInitialize?: boolean;\n}\n\n// ── Pinia store ────────────────────────────────────────────────────────────────\n\n/**\n * Same interface as useSSOStore() but with BrokerUser and no activePolicy.\n * Components can use this directly or go through useAuth() (which wraps it).\n */\nexport const useBrokerStore = defineStore(\"broker-sso\", () => {\n const isAuthenticated = ref(false);\n const isLoading = ref(false);\n const user = ref<BrokerClientState[\"user\"]>(null);\n const token = ref<string | null>(null);\n const error = ref<Error | null>(null);\n const authReady = ref(false);\n\n function syncState(state: BrokerClientState) {\n isAuthenticated.value = state.isAuthenticated;\n isLoading.value = state.isLoading;\n user.value = state.user;\n token.value = state.token;\n error.value = state.error;\n authReady.value = state.authReady;\n }\n\n return { isAuthenticated, isLoading, user, token, error, authReady, syncState };\n});\n\n// ── Plugin factory ─────────────────────────────────────────────────────────────\n\nexport function createBrokerPlugin(options: BrokerPluginOptions) {\n return {\n install(app: App) {\n const client = new BrokerClient(options.clientConfig);\n\n app.provide(BROKER_CLIENT_KEY, client);\n\n client.events.on(\"auth:stateChanged\", (state: BrokerClientState) => {\n const store = useBrokerStore();\n store.syncState(state);\n });\n\n if (options.autoInitialize !== false) {\n client.initialize().then(user => {\n if (user && options.clientConfig.debug) {\n console.log(\"[broker-plugin] Initialized, user:\", user.sub);\n }\n });\n }\n },\n };\n}\n","// ABOUTME: useAuth() equivalent for broker-authenticated Vue 3 apps.\n// ABOUTME: API surface matches useAuth() from useAuth.ts so migration is find-and-replace.\n// ABOUTME:\n// ABOUTME: What's simpler compared to the B2C useAuth():\n// ABOUTME: - userName reads direct BrokerUser properties (no idTokenClaims map)\n// ABOUTME: - no forgotPassword() — handled entirely on the B2C side behind the broker\n// ABOUTME: - no signInCityEmployee() / policy-based sign-in — one signIn() covers all flows\n// ABOUTME: - hasRole() reads roles claim directly (not extension_Roles fallback)\n\nimport { computed, inject } from \"vue\";\nimport { storeToRefs } from \"pinia\";\nimport { useBrokerStore, BROKER_CLIENT_KEY } from \"../broker-plugin\";\nimport type { BrokerClient, BrokerSignInOptions, BrokerSignOutOptions, BrokerTokenOptions } from \"@phila/sso-core\";\n\nfunction useBrokerClient(): BrokerClient {\n const client = inject<BrokerClient>(BROKER_CLIENT_KEY);\n if (!client) {\n throw new Error(\n \"[useBrokerAuth] BrokerClient not found. \" +\n \"Did you install createBrokerPlugin() before calling useBrokerAuth()?\",\n );\n }\n return client;\n}\n\n/**\n * Primary composable for broker-authenticated Vue 3 apps.\n * Drop-in replacement for useAuth() — same returned shape, simpler internals.\n *\n * @example\n * const { isAuthenticated, user, signIn, signOut } = useBrokerAuth();\n */\nexport function useBrokerAuth() {\n const store = useBrokerStore();\n const client = useBrokerClient();\n const { isAuthenticated, isLoading, user, token, error, authReady } = storeToRefs(store);\n\n // ── Computed helpers ─────────────────────────────────────────────────────\n\n const userName = computed(() => {\n if (!user.value) return null;\n // BrokerUser has direct properties — no idTokenClaims indirection.\n const joined = [user.value.given_name, user.value.family_name].filter(Boolean).join(\" \");\n return user.value.name || joined || null;\n });\n\n // ── Actions ──────────────────────────────────────────────────────────────\n\n async function signIn(options?: BrokerSignInOptions): Promise<void> {\n await client.signIn(options);\n }\n\n async function signOut(options?: BrokerSignOutOptions): Promise<void> {\n await client.signOut(options);\n }\n\n async function acquireToken(options?: BrokerTokenOptions): Promise<string | null> {\n return client.acquireToken(options);\n }\n\n // ── Utilities ────────────────────────────────────────────────────────────\n\n /**\n * Check if the authenticated user has a given role.\n * The broker includes roles in the access token `scope` field by convention;\n * adjust the claim name here if your broker config uses a custom roles claim.\n */\n function hasRole(role: string): boolean {\n if (!user.value) return false;\n // Roles aren't yet standardized in the broker's token — placeholder for\n // when the broker adds a `roles` claim to the JWT payload.\n const claims = user.value as unknown as Record<string, unknown>;\n const roles = (claims.roles ?? []) as string[];\n return Array.isArray(roles) && roles.includes(role);\n }\n\n return {\n // State (readonly refs)\n isAuthenticated,\n isLoading,\n user,\n token,\n error,\n authReady,\n userName,\n\n // Actions\n signIn,\n signOut,\n acquireToken,\n\n // Utilities\n hasRole,\n };\n}\n"],"names":["defineStore","ref","SSOClient","inject","storeToRefs","computed","B2CProvider","BrokerClient"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/plugin.ts","../src/composables/useSSOClient.ts","../src/composables/useAuth.ts","../src/createB2CPlugin.ts","../src/broker-plugin.ts","../src/composables/useBrokerAuth.ts"],"sourcesContent":["import { ref } from \"vue\";\nimport { defineStore } from \"pinia\";\nimport { SSOClient } from \"@phila/sso-core\";\nimport type { App } from \"vue\";\nimport type { SSOClientConfig, SSOClientState, AuthResponse } from \"@phila/sso-core\";\n\nexport const SSO_CLIENT_KEY = Symbol(\"sso-client\");\n\nexport interface SSOPluginOptions {\n clientConfig: SSOClientConfig;\n autoInitialize?: boolean;\n}\n\nexport const useSSOStore = defineStore(\"sso\", () => {\n const isAuthenticated = ref(false);\n const isLoading = ref(false);\n const user = ref<SSOClientState[\"user\"]>(null);\n const token = ref<string | null>(null);\n const error = ref<Error | null>(null);\n const activePolicy = ref<string | null>(null);\n const authReady = ref(false);\n\n function syncState(state: SSOClientState) {\n isAuthenticated.value = state.isAuthenticated;\n isLoading.value = state.isLoading;\n user.value = state.user;\n token.value = state.token;\n error.value = state.error;\n activePolicy.value = state.activePolicy;\n authReady.value = state.authReady;\n }\n\n return { isAuthenticated, isLoading, user, token, error, activePolicy, authReady, syncState };\n});\n\nexport function createSSOPlugin(options: SSOPluginOptions) {\n return {\n install(app: App) {\n const client = new SSOClient(options.clientConfig);\n\n // Provide the client for useSSOClient()\n app.provide(SSO_CLIENT_KEY, client);\n\n // Subscribe to state changes and sync to Pinia store\n client.events.on(\"auth:stateChanged\", (state: SSOClientState) => {\n const store = useSSOStore();\n store.syncState(state);\n });\n\n // Auto-initialize unless explicitly disabled\n if (options.autoInitialize !== false) {\n client.initialize().then((response: AuthResponse | null) => {\n if (response && options.clientConfig.debug) {\n console.log(\"[sso-vue] Auto-initialized with response:\", response);\n }\n });\n }\n },\n };\n}\n","import { inject } from \"vue\";\nimport { SSOClient } from \"@phila/sso-core\";\nimport { SSO_CLIENT_KEY } from \"../plugin\";\n\n/**\n * Access the raw SSOClient instance.\n * Must be called within a component that is a descendant of createSSOPlugin.\n */\nexport function useSSOClient(): SSOClient {\n const client = inject<SSOClient>(SSO_CLIENT_KEY);\n if (!client) {\n throw new Error(\"SSOClient not found. Did you install createSSOPlugin?\");\n }\n return client;\n}\n","import { computed } from \"vue\";\nimport { storeToRefs } from \"pinia\";\nimport { useSSOStore } from \"../plugin\";\nimport { useSSOClient } from \"./useSSOClient\";\nimport type { SignInOptions, SignOutOptions, TokenOptions } from \"@phila/sso-core\";\n\n/**\n * Primary composable for SSO authentication in Vue 3 apps.\n * API shape is intentionally similar to service-cat's existing useAuth()\n * to minimize migration friction.\n */\nexport function useAuth() {\n const store = useSSOStore();\n const client = useSSOClient();\n const { isAuthenticated, isLoading, user, token, error, activePolicy, authReady } = storeToRefs(store);\n\n // Computed helpers\n const userName = computed(() => {\n const claims = user.value?.idTokenClaims as Record<string, unknown> | undefined;\n if (!claims) return null;\n const given = (claims.given_name ?? claims.name ?? \"\") as string;\n const family = (claims.family_name ?? \"\") as string;\n return family ? `${given} ${family}`.trim() : given;\n });\n\n // Actions\n async function signIn(options?: SignInOptions): Promise<void> {\n await client.signIn(options);\n }\n\n async function signInCityEmployee(options?: SignInOptions): Promise<void> {\n await client.signInCityEmployee(options);\n }\n\n async function signOut(options?: SignOutOptions): Promise<void> {\n await client.signOut(options);\n }\n\n async function forgotPassword(): Promise<void> {\n await client.forgotPassword();\n }\n\n async function acquireToken(options?: TokenOptions): Promise<string | null> {\n return client.acquireToken(options);\n }\n\n // Utilities\n function hasRole(role: string): boolean {\n const claims = user.value?.idTokenClaims as Record<string, unknown> | undefined;\n if (!claims) return false;\n\n const roles = (claims.roles ?? claims.extension_Roles ?? []) as string[];\n return Array.isArray(roles) && roles.includes(role);\n }\n\n return {\n // State (readonly refs)\n isAuthenticated,\n isLoading,\n user,\n token,\n error,\n activePolicy,\n authReady,\n userName,\n\n // Actions\n signIn,\n signInCityEmployee,\n signOut,\n forgotPassword,\n acquireToken,\n\n // Utilities\n hasRole,\n };\n}\n","// ABOUTME: Convenience factory for vanilla Vue/Vite apps using Azure AD B2C\n// ABOUTME: Reads VITE_SSO_* env vars by convention so apps need zero B2CProvider boilerplate\nimport { B2CProvider } from \"@phila/sso-core\";\nimport { createSSOPlugin } from \"./plugin\";\n\nexport interface B2CPluginOptions {\n signInPolicy?: string;\n resetPasswordPolicy?: string;\n debug?: boolean;\n}\n\n/**\n * Creates a ready-to-use Vue plugin for Azure AD B2C authentication.\n * Reads connection details from VITE_SSO_* environment variables:\n * VITE_SSO_CLIENT_ID, VITE_SSO_TENANT, VITE_SSO_AUTHORITY_DOMAIN, VITE_SSO_REDIRECT_URI\n */\nexport function createB2CPlugin(options: B2CPluginOptions = {}) {\n const {\n signInPolicy = \"B2C_1A_AD_SIGNIN_ONLY\",\n resetPasswordPolicy = \"B2C_1A_PASSWORDRESET\",\n debug = import.meta.env.DEV,\n } = options;\n\n return createSSOPlugin({\n clientConfig: {\n provider: new B2CProvider({\n clientId: import.meta.env.VITE_SSO_CLIENT_ID,\n b2cEnvironment: import.meta.env.VITE_SSO_TENANT,\n authorityDomain: import.meta.env.VITE_SSO_AUTHORITY_DOMAIN,\n redirectUri: import.meta.env.VITE_SSO_REDIRECT_URI,\n policies: {\n signUpSignIn: signInPolicy,\n signInOnly: signInPolicy,\n resetPassword: resetPasswordPolicy,\n },\n }),\n debug,\n },\n });\n}\n","// ABOUTME: Vue 3 plugin for the phila-identity broker — replaces createSSOPlugin() / useSSOStore().\n// ABOUTME: Uses BrokerClient instead of SSOClient, so there's no MSAL dependency.\n// ABOUTME:\n// ABOUTME: Store shape differences from the B2C plugin:\n// ABOUTME: - user is BrokerUser (not MSAL AccountInfo) — direct named properties, no idTokenClaims map\n// ABOUTME: - activePolicy is gone — the broker is policy-agnostic from the client's perspective\n// ABOUTME:\n// ABOUTME: Everything else (provide/inject, Pinia store, event wiring) is identical.\n\nimport { ref } from \"vue\";\nimport { defineStore } from \"pinia\";\nimport { BrokerClient } from \"@phila/sso-core\";\nimport type { App } from \"vue\";\nimport type { BrokerClientConfig, BrokerClientState } from \"@phila/sso-core\";\n\nexport const BROKER_CLIENT_KEY = Symbol(\"broker-client\");\n\n// ── Plugin options ─────────────────────────────────────────────────────────────\n\nexport interface BrokerPluginOptions {\n clientConfig: BrokerClientConfig;\n /**\n * Set false to skip the automatic initialize() call during install.\n * Useful when you want to call initialize() yourself at a specific lifecycle point.\n */\n autoInitialize?: boolean;\n}\n\n// ── Pinia store ────────────────────────────────────────────────────────────────\n\n/**\n * Same interface as useSSOStore() but with BrokerUser and no activePolicy.\n * Components can use this directly or go through useAuth() (which wraps it).\n */\nexport const useBrokerStore = defineStore(\"broker-sso\", () => {\n const isAuthenticated = ref(false);\n const isLoading = ref(false);\n const user = ref<BrokerClientState[\"user\"]>(null);\n const token = ref<string | null>(null);\n const setupPasskeyToken = ref<string | null>(null);\n const error = ref<Error | null>(null);\n const authReady = ref(false);\n\n function syncState(state: BrokerClientState) {\n isAuthenticated.value = state.isAuthenticated;\n isLoading.value = state.isLoading;\n user.value = state.user;\n token.value = state.token;\n setupPasskeyToken.value = state.setupPasskeyToken;\n error.value = state.error;\n authReady.value = state.authReady;\n }\n\n return { isAuthenticated, isLoading, user, token, setupPasskeyToken, error, authReady, syncState };\n});\n\n// ── Plugin factory ─────────────────────────────────────────────────────────────\n\nexport function createBrokerPlugin(options: BrokerPluginOptions) {\n return {\n install(app: App) {\n const client = new BrokerClient(options.clientConfig);\n\n app.provide(BROKER_CLIENT_KEY, client);\n\n client.events.on(\"auth:stateChanged\", (state: BrokerClientState) => {\n const store = useBrokerStore();\n store.syncState(state);\n });\n\n if (options.autoInitialize !== false) {\n client.initialize().then(user => {\n if (user && options.clientConfig.debug) {\n console.log(\"[broker-plugin] Initialized, user:\", user.sub);\n }\n });\n }\n },\n };\n}\n","// ABOUTME: useAuth() equivalent for broker-authenticated Vue 3 apps.\n// ABOUTME: API surface matches useAuth() from useAuth.ts so migration is find-and-replace.\n// ABOUTME:\n// ABOUTME: What's simpler compared to the B2C useAuth():\n// ABOUTME: - userName reads direct BrokerUser properties (no idTokenClaims map)\n// ABOUTME: - no forgotPassword() — handled entirely on the B2C side behind the broker\n// ABOUTME: - no signInCityEmployee() / policy-based sign-in — one signIn() covers all flows\n// ABOUTME: - hasRole() reads roles claim directly (not extension_Roles fallback)\n\nimport { computed, inject } from \"vue\";\nimport { storeToRefs } from \"pinia\";\nimport { useBrokerStore, BROKER_CLIENT_KEY } from \"../broker-plugin\";\nimport type { BrokerClient, BrokerSignInOptions, BrokerSignOutOptions, BrokerTokenOptions } from \"@phila/sso-core\";\n\nfunction useBrokerClient(): BrokerClient {\n const client = inject<BrokerClient>(BROKER_CLIENT_KEY);\n if (!client) {\n throw new Error(\n \"[useBrokerAuth] BrokerClient not found. \" +\n \"Did you install createBrokerPlugin() before calling useBrokerAuth()?\",\n );\n }\n return client;\n}\n\n/**\n * Primary composable for broker-authenticated Vue 3 apps.\n * Drop-in replacement for useAuth() — same returned shape, simpler internals.\n *\n * @example\n * const { isAuthenticated, user, signIn, signOut } = useBrokerAuth();\n */\nexport function useBrokerAuth() {\n const store = useBrokerStore();\n const client = useBrokerClient();\n const { isAuthenticated, isLoading, user, token, setupPasskeyToken, error, authReady } = storeToRefs(store);\n\n // ── Computed helpers ─────────────────────────────────────────────────────\n\n const userName = computed(() => {\n if (!user.value) return null;\n // BrokerUser has direct properties — no idTokenClaims indirection.\n const joined = [user.value.given_name, user.value.family_name].filter(Boolean).join(\" \");\n return user.value.name || joined || null;\n });\n\n // ── Actions ──────────────────────────────────────────────────────────────\n\n async function signIn(options?: BrokerSignInOptions): Promise<void> {\n await client.signIn(options);\n }\n\n async function signOut(options?: BrokerSignOutOptions): Promise<void> {\n await client.signOut(options);\n }\n\n async function acquireToken(options?: BrokerTokenOptions): Promise<string | null> {\n return client.acquireToken(options);\n }\n\n // ── Utilities ────────────────────────────────────────────────────────────\n\n /**\n * Check if the authenticated user has a given role.\n * The broker includes roles in the access token `scope` field by convention;\n * adjust the claim name here if your broker config uses a custom roles claim.\n */\n function hasRole(role: string): boolean {\n if (!user.value) return false;\n // Roles aren't yet standardized in the broker's token — placeholder for\n // when the broker adds a `roles` claim to the JWT payload.\n const claims = user.value as unknown as Record<string, unknown>;\n const roles = (claims.roles ?? []) as string[];\n return Array.isArray(roles) && roles.includes(role);\n }\n\n return {\n // State (readonly refs)\n isAuthenticated,\n isLoading,\n user,\n token,\n setupPasskeyToken,\n error,\n authReady,\n userName,\n\n // Actions\n signIn,\n signOut,\n acquireToken,\n\n // Utilities\n hasRole,\n };\n}\n"],"names":["defineStore","ref","SSOClient","inject","storeToRefs","computed","B2CProvider","BrokerClient"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -128,6 +128,7 @@ const useBrokerStore = defineStore("broker-sso", () => {
128
128
  const isLoading = ref(false);
129
129
  const user = ref(null);
130
130
  const token = ref(null);
131
+ const setupPasskeyToken = ref(null);
131
132
  const error = ref(null);
132
133
  const authReady = ref(false);
133
134
  function syncState(state) {
@@ -135,10 +136,11 @@ const useBrokerStore = defineStore("broker-sso", () => {
135
136
  isLoading.value = state.isLoading;
136
137
  user.value = state.user;
137
138
  token.value = state.token;
139
+ setupPasskeyToken.value = state.setupPasskeyToken;
138
140
  error.value = state.error;
139
141
  authReady.value = state.authReady;
140
142
  }
141
- return { isAuthenticated, isLoading, user, token, error, authReady, syncState };
143
+ return { isAuthenticated, isLoading, user, token, setupPasskeyToken, error, authReady, syncState };
142
144
  });
143
145
  function createBrokerPlugin(options) {
144
146
  return {
@@ -171,7 +173,7 @@ function useBrokerClient() {
171
173
  function useBrokerAuth() {
172
174
  const store = useBrokerStore();
173
175
  const client = useBrokerClient();
174
- const { isAuthenticated, isLoading, user, token, error, authReady } = storeToRefs(store);
176
+ const { isAuthenticated, isLoading, user, token, setupPasskeyToken, error, authReady } = storeToRefs(store);
175
177
  const userName = computed(() => {
176
178
  if (!user.value) return null;
177
179
  const joined = [user.value.given_name, user.value.family_name].filter(Boolean).join(" ");
@@ -198,6 +200,7 @@ function useBrokerAuth() {
198
200
  isLoading,
199
201
  user,
200
202
  token,
203
+ setupPasskeyToken,
201
204
  error,
202
205
  authReady,
203
206
  userName,
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/plugin.ts","../src/composables/useSSOClient.ts","../src/composables/useAuth.ts","../src/createB2CPlugin.ts","../src/broker-plugin.ts","../src/composables/useBrokerAuth.ts"],"sourcesContent":["import { ref } from \"vue\";\nimport { defineStore } from \"pinia\";\nimport { SSOClient } from \"@phila/sso-core\";\nimport type { App } from \"vue\";\nimport type { SSOClientConfig, SSOClientState, AuthResponse } from \"@phila/sso-core\";\n\nexport const SSO_CLIENT_KEY = Symbol(\"sso-client\");\n\nexport interface SSOPluginOptions {\n clientConfig: SSOClientConfig;\n autoInitialize?: boolean;\n}\n\nexport const useSSOStore = defineStore(\"sso\", () => {\n const isAuthenticated = ref(false);\n const isLoading = ref(false);\n const user = ref<SSOClientState[\"user\"]>(null);\n const token = ref<string | null>(null);\n const error = ref<Error | null>(null);\n const activePolicy = ref<string | null>(null);\n const authReady = ref(false);\n\n function syncState(state: SSOClientState) {\n isAuthenticated.value = state.isAuthenticated;\n isLoading.value = state.isLoading;\n user.value = state.user;\n token.value = state.token;\n error.value = state.error;\n activePolicy.value = state.activePolicy;\n authReady.value = state.authReady;\n }\n\n return { isAuthenticated, isLoading, user, token, error, activePolicy, authReady, syncState };\n});\n\nexport function createSSOPlugin(options: SSOPluginOptions) {\n return {\n install(app: App) {\n const client = new SSOClient(options.clientConfig);\n\n // Provide the client for useSSOClient()\n app.provide(SSO_CLIENT_KEY, client);\n\n // Subscribe to state changes and sync to Pinia store\n client.events.on(\"auth:stateChanged\", (state: SSOClientState) => {\n const store = useSSOStore();\n store.syncState(state);\n });\n\n // Auto-initialize unless explicitly disabled\n if (options.autoInitialize !== false) {\n client.initialize().then((response: AuthResponse | null) => {\n if (response && options.clientConfig.debug) {\n console.log(\"[sso-vue] Auto-initialized with response:\", response);\n }\n });\n }\n },\n };\n}\n","import { inject } from \"vue\";\nimport { SSOClient } from \"@phila/sso-core\";\nimport { SSO_CLIENT_KEY } from \"../plugin\";\n\n/**\n * Access the raw SSOClient instance.\n * Must be called within a component that is a descendant of createSSOPlugin.\n */\nexport function useSSOClient(): SSOClient {\n const client = inject<SSOClient>(SSO_CLIENT_KEY);\n if (!client) {\n throw new Error(\"SSOClient not found. Did you install createSSOPlugin?\");\n }\n return client;\n}\n","import { computed } from \"vue\";\nimport { storeToRefs } from \"pinia\";\nimport { useSSOStore } from \"../plugin\";\nimport { useSSOClient } from \"./useSSOClient\";\nimport type { SignInOptions, SignOutOptions, TokenOptions } from \"@phila/sso-core\";\n\n/**\n * Primary composable for SSO authentication in Vue 3 apps.\n * API shape is intentionally similar to service-cat's existing useAuth()\n * to minimize migration friction.\n */\nexport function useAuth() {\n const store = useSSOStore();\n const client = useSSOClient();\n const { isAuthenticated, isLoading, user, token, error, activePolicy, authReady } = storeToRefs(store);\n\n // Computed helpers\n const userName = computed(() => {\n const claims = user.value?.idTokenClaims as Record<string, unknown> | undefined;\n if (!claims) return null;\n const given = (claims.given_name ?? claims.name ?? \"\") as string;\n const family = (claims.family_name ?? \"\") as string;\n return family ? `${given} ${family}`.trim() : given;\n });\n\n // Actions\n async function signIn(options?: SignInOptions): Promise<void> {\n await client.signIn(options);\n }\n\n async function signInCityEmployee(options?: SignInOptions): Promise<void> {\n await client.signInCityEmployee(options);\n }\n\n async function signOut(options?: SignOutOptions): Promise<void> {\n await client.signOut(options);\n }\n\n async function forgotPassword(): Promise<void> {\n await client.forgotPassword();\n }\n\n async function acquireToken(options?: TokenOptions): Promise<string | null> {\n return client.acquireToken(options);\n }\n\n // Utilities\n function hasRole(role: string): boolean {\n const claims = user.value?.idTokenClaims as Record<string, unknown> | undefined;\n if (!claims) return false;\n\n const roles = (claims.roles ?? claims.extension_Roles ?? []) as string[];\n return Array.isArray(roles) && roles.includes(role);\n }\n\n return {\n // State (readonly refs)\n isAuthenticated,\n isLoading,\n user,\n token,\n error,\n activePolicy,\n authReady,\n userName,\n\n // Actions\n signIn,\n signInCityEmployee,\n signOut,\n forgotPassword,\n acquireToken,\n\n // Utilities\n hasRole,\n };\n}\n","// ABOUTME: Convenience factory for vanilla Vue/Vite apps using Azure AD B2C\n// ABOUTME: Reads VITE_SSO_* env vars by convention so apps need zero B2CProvider boilerplate\nimport { B2CProvider } from \"@phila/sso-core\";\nimport { createSSOPlugin } from \"./plugin\";\n\nexport interface B2CPluginOptions {\n signInPolicy?: string;\n resetPasswordPolicy?: string;\n debug?: boolean;\n}\n\n/**\n * Creates a ready-to-use Vue plugin for Azure AD B2C authentication.\n * Reads connection details from VITE_SSO_* environment variables:\n * VITE_SSO_CLIENT_ID, VITE_SSO_TENANT, VITE_SSO_AUTHORITY_DOMAIN, VITE_SSO_REDIRECT_URI\n */\nexport function createB2CPlugin(options: B2CPluginOptions = {}) {\n const {\n signInPolicy = \"B2C_1A_AD_SIGNIN_ONLY\",\n resetPasswordPolicy = \"B2C_1A_PASSWORDRESET\",\n debug = import.meta.env.DEV,\n } = options;\n\n return createSSOPlugin({\n clientConfig: {\n provider: new B2CProvider({\n clientId: import.meta.env.VITE_SSO_CLIENT_ID,\n b2cEnvironment: import.meta.env.VITE_SSO_TENANT,\n authorityDomain: import.meta.env.VITE_SSO_AUTHORITY_DOMAIN,\n redirectUri: import.meta.env.VITE_SSO_REDIRECT_URI,\n policies: {\n signUpSignIn: signInPolicy,\n signInOnly: signInPolicy,\n resetPassword: resetPasswordPolicy,\n },\n }),\n debug,\n },\n });\n}\n","// ABOUTME: Vue 3 plugin for the phila-identity broker — replaces createSSOPlugin() / useSSOStore().\n// ABOUTME: Uses BrokerClient instead of SSOClient, so there's no MSAL dependency.\n// ABOUTME:\n// ABOUTME: Store shape differences from the B2C plugin:\n// ABOUTME: - user is BrokerUser (not MSAL AccountInfo) — direct named properties, no idTokenClaims map\n// ABOUTME: - activePolicy is gone — the broker is policy-agnostic from the client's perspective\n// ABOUTME:\n// ABOUTME: Everything else (provide/inject, Pinia store, event wiring) is identical.\n\nimport { ref } from \"vue\";\nimport { defineStore } from \"pinia\";\nimport { BrokerClient } from \"@phila/sso-core\";\nimport type { App } from \"vue\";\nimport type { BrokerClientConfig, BrokerClientState } from \"@phila/sso-core\";\n\nexport const BROKER_CLIENT_KEY = Symbol(\"broker-client\");\n\n// ── Plugin options ─────────────────────────────────────────────────────────────\n\nexport interface BrokerPluginOptions {\n clientConfig: BrokerClientConfig;\n /**\n * Set false to skip the automatic initialize() call during install.\n * Useful when you want to call initialize() yourself at a specific lifecycle point.\n */\n autoInitialize?: boolean;\n}\n\n// ── Pinia store ────────────────────────────────────────────────────────────────\n\n/**\n * Same interface as useSSOStore() but with BrokerUser and no activePolicy.\n * Components can use this directly or go through useAuth() (which wraps it).\n */\nexport const useBrokerStore = defineStore(\"broker-sso\", () => {\n const isAuthenticated = ref(false);\n const isLoading = ref(false);\n const user = ref<BrokerClientState[\"user\"]>(null);\n const token = ref<string | null>(null);\n const error = ref<Error | null>(null);\n const authReady = ref(false);\n\n function syncState(state: BrokerClientState) {\n isAuthenticated.value = state.isAuthenticated;\n isLoading.value = state.isLoading;\n user.value = state.user;\n token.value = state.token;\n error.value = state.error;\n authReady.value = state.authReady;\n }\n\n return { isAuthenticated, isLoading, user, token, error, authReady, syncState };\n});\n\n// ── Plugin factory ─────────────────────────────────────────────────────────────\n\nexport function createBrokerPlugin(options: BrokerPluginOptions) {\n return {\n install(app: App) {\n const client = new BrokerClient(options.clientConfig);\n\n app.provide(BROKER_CLIENT_KEY, client);\n\n client.events.on(\"auth:stateChanged\", (state: BrokerClientState) => {\n const store = useBrokerStore();\n store.syncState(state);\n });\n\n if (options.autoInitialize !== false) {\n client.initialize().then(user => {\n if (user && options.clientConfig.debug) {\n console.log(\"[broker-plugin] Initialized, user:\", user.sub);\n }\n });\n }\n },\n };\n}\n","// ABOUTME: useAuth() equivalent for broker-authenticated Vue 3 apps.\n// ABOUTME: API surface matches useAuth() from useAuth.ts so migration is find-and-replace.\n// ABOUTME:\n// ABOUTME: What's simpler compared to the B2C useAuth():\n// ABOUTME: - userName reads direct BrokerUser properties (no idTokenClaims map)\n// ABOUTME: - no forgotPassword() — handled entirely on the B2C side behind the broker\n// ABOUTME: - no signInCityEmployee() / policy-based sign-in — one signIn() covers all flows\n// ABOUTME: - hasRole() reads roles claim directly (not extension_Roles fallback)\n\nimport { computed, inject } from \"vue\";\nimport { storeToRefs } from \"pinia\";\nimport { useBrokerStore, BROKER_CLIENT_KEY } from \"../broker-plugin\";\nimport type { BrokerClient, BrokerSignInOptions, BrokerSignOutOptions, BrokerTokenOptions } from \"@phila/sso-core\";\n\nfunction useBrokerClient(): BrokerClient {\n const client = inject<BrokerClient>(BROKER_CLIENT_KEY);\n if (!client) {\n throw new Error(\n \"[useBrokerAuth] BrokerClient not found. \" +\n \"Did you install createBrokerPlugin() before calling useBrokerAuth()?\",\n );\n }\n return client;\n}\n\n/**\n * Primary composable for broker-authenticated Vue 3 apps.\n * Drop-in replacement for useAuth() — same returned shape, simpler internals.\n *\n * @example\n * const { isAuthenticated, user, signIn, signOut } = useBrokerAuth();\n */\nexport function useBrokerAuth() {\n const store = useBrokerStore();\n const client = useBrokerClient();\n const { isAuthenticated, isLoading, user, token, error, authReady } = storeToRefs(store);\n\n // ── Computed helpers ─────────────────────────────────────────────────────\n\n const userName = computed(() => {\n if (!user.value) return null;\n // BrokerUser has direct properties — no idTokenClaims indirection.\n const joined = [user.value.given_name, user.value.family_name].filter(Boolean).join(\" \");\n return user.value.name || joined || null;\n });\n\n // ── Actions ──────────────────────────────────────────────────────────────\n\n async function signIn(options?: BrokerSignInOptions): Promise<void> {\n await client.signIn(options);\n }\n\n async function signOut(options?: BrokerSignOutOptions): Promise<void> {\n await client.signOut(options);\n }\n\n async function acquireToken(options?: BrokerTokenOptions): Promise<string | null> {\n return client.acquireToken(options);\n }\n\n // ── Utilities ────────────────────────────────────────────────────────────\n\n /**\n * Check if the authenticated user has a given role.\n * The broker includes roles in the access token `scope` field by convention;\n * adjust the claim name here if your broker config uses a custom roles claim.\n */\n function hasRole(role: string): boolean {\n if (!user.value) return false;\n // Roles aren't yet standardized in the broker's token — placeholder for\n // when the broker adds a `roles` claim to the JWT payload.\n const claims = user.value as unknown as Record<string, unknown>;\n const roles = (claims.roles ?? []) as string[];\n return Array.isArray(roles) && roles.includes(role);\n }\n\n return {\n // State (readonly refs)\n isAuthenticated,\n isLoading,\n user,\n token,\n error,\n authReady,\n userName,\n\n // Actions\n signIn,\n signOut,\n acquireToken,\n\n // Utilities\n hasRole,\n };\n}\n"],"names":[],"mappings":";;;AAMO,MAAM,wCAAwB,YAAY;AAO1C,MAAM,cAAc,YAAY,OAAO,MAAM;AAClD,QAAM,kBAAkB,IAAI,KAAK;AACjC,QAAM,YAAY,IAAI,KAAK;AAC3B,QAAM,OAAO,IAA4B,IAAI;AAC7C,QAAM,QAAQ,IAAmB,IAAI;AACrC,QAAM,QAAQ,IAAkB,IAAI;AACpC,QAAM,eAAe,IAAmB,IAAI;AAC5C,QAAM,YAAY,IAAI,KAAK;AAE3B,WAAS,UAAU,OAAuB;AACxC,oBAAgB,QAAQ,MAAM;AAC9B,cAAU,QAAQ,MAAM;AACxB,SAAK,QAAQ,MAAM;AACnB,UAAM,QAAQ,MAAM;AACpB,UAAM,QAAQ,MAAM;AACpB,iBAAa,QAAQ,MAAM;AAC3B,cAAU,QAAQ,MAAM;AAAA,EAC1B;AAEA,SAAO,EAAE,iBAAiB,WAAW,MAAM,OAAO,OAAO,cAAc,WAAW,UAAA;AACpF,CAAC;AAEM,SAAS,gBAAgB,SAA2B;AACzD,SAAO;AAAA,IACL,QAAQ,KAAU;AAChB,YAAM,SAAS,IAAI,UAAU,QAAQ,YAAY;AAGjD,UAAI,QAAQ,gBAAgB,MAAM;AAGlC,aAAO,OAAO,GAAG,qBAAqB,CAAC,UAA0B;AAC/D,cAAM,QAAQ,YAAA;AACd,cAAM,UAAU,KAAK;AAAA,MACvB,CAAC;AAGD,UAAI,QAAQ,mBAAmB,OAAO;AACpC,eAAO,WAAA,EAAa,KAAK,CAAC,aAAkC;AAC1D,cAAI,YAAY,QAAQ,aAAa,OAAO;AAC1C,oBAAQ,IAAI,6CAA6C,QAAQ;AAAA,UACnE;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EAAA;AAEJ;ACnDO,SAAS,eAA0B;AACxC,QAAM,SAAS,OAAkB,cAAc;AAC/C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACA,SAAO;AACT;ACHO,SAAS,UAAU;AACxB,QAAM,QAAQ,YAAA;AACd,QAAM,SAAS,aAAA;AACf,QAAM,EAAE,iBAAiB,WAAW,MAAM,OAAO,OAAO,cAAc,UAAA,IAAc,YAAY,KAAK;AAGrG,QAAM,WAAW,SAAS,MAAM;AAC9B,UAAM,SAAS,KAAK,OAAO;AAC3B,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,QAAS,OAAO,cAAc,OAAO,QAAQ;AACnD,UAAM,SAAU,OAAO,eAAe;AACtC,WAAO,SAAS,GAAG,KAAK,IAAI,MAAM,GAAG,SAAS;AAAA,EAChD,CAAC;AAGD,iBAAe,OAAO,SAAwC;AAC5D,UAAM,OAAO,OAAO,OAAO;AAAA,EAC7B;AAEA,iBAAe,mBAAmB,SAAwC;AACxE,UAAM,OAAO,mBAAmB,OAAO;AAAA,EACzC;AAEA,iBAAe,QAAQ,SAAyC;AAC9D,UAAM,OAAO,QAAQ,OAAO;AAAA,EAC9B;AAEA,iBAAe,iBAAgC;AAC7C,UAAM,OAAO,eAAA;AAAA,EACf;AAEA,iBAAe,aAAa,SAAgD;AAC1E,WAAO,OAAO,aAAa,OAAO;AAAA,EACpC;AAGA,WAAS,QAAQ,MAAuB;AACtC,UAAM,SAAS,KAAK,OAAO;AAC3B,QAAI,CAAC,OAAQ,QAAO;AAEpB,UAAM,QAAS,OAAO,SAAS,OAAO,mBAAmB,CAAA;AACzD,WAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,IAAI;AAAA,EACpD;AAEA,SAAO;AAAA;AAAA,IAEL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAGA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAGA;AAAA,EAAA;AAEJ;AC5DO,SAAS,gBAAgB,UAA4B,IAAI;AAC9D,QAAM;AAAA,IACJ,eAAe;AAAA,IACf,sBAAsB;AAAA,IACtB,QAAQ;AAAA,EAAA,IACN;AAEJ,SAAO,gBAAgB;AAAA,IACrB,cAAc;AAAA,MACZ,UAAU,IAAI,YAAY;AAAA,QACxB,UAAU;AAAA,QACV,gBAAgB;AAAA,QAChB,iBAAiB;AAAA,QACjB,aAAa;AAAA,QACb,UAAU;AAAA,UACR,cAAc;AAAA,UACd,YAAY;AAAA,UACZ,eAAe;AAAA,QAAA;AAAA,MACjB,CACD;AAAA,MACD;AAAA,IAAA;AAAA,EACF,CACD;AACH;ACxBO,MAAM,2CAA2B,eAAe;AAmBhD,MAAM,iBAAiB,YAAY,cAAc,MAAM;AAC5D,QAAM,kBAAkB,IAAI,KAAK;AACjC,QAAM,YAAY,IAAI,KAAK;AAC3B,QAAM,OAAO,IAA+B,IAAI;AAChD,QAAM,QAAQ,IAAmB,IAAI;AACrC,QAAM,QAAQ,IAAkB,IAAI;AACpC,QAAM,YAAY,IAAI,KAAK;AAE3B,WAAS,UAAU,OAA0B;AAC3C,oBAAgB,QAAQ,MAAM;AAC9B,cAAU,QAAQ,MAAM;AACxB,SAAK,QAAQ,MAAM;AACnB,UAAM,QAAQ,MAAM;AACpB,UAAM,QAAQ,MAAM;AACpB,cAAU,QAAQ,MAAM;AAAA,EAC1B;AAEA,SAAO,EAAE,iBAAiB,WAAW,MAAM,OAAO,OAAO,WAAW,UAAA;AACtE,CAAC;AAIM,SAAS,mBAAmB,SAA8B;AAC/D,SAAO;AAAA,IACL,QAAQ,KAAU;AAChB,YAAM,SAAS,IAAI,aAAa,QAAQ,YAAY;AAEpD,UAAI,QAAQ,mBAAmB,MAAM;AAErC,aAAO,OAAO,GAAG,qBAAqB,CAAC,UAA6B;AAClE,cAAM,QAAQ,eAAA;AACd,cAAM,UAAU,KAAK;AAAA,MACvB,CAAC;AAED,UAAI,QAAQ,mBAAmB,OAAO;AACpC,eAAO,WAAA,EAAa,KAAK,CAAA,SAAQ;AAC/B,cAAI,QAAQ,QAAQ,aAAa,OAAO;AACtC,oBAAQ,IAAI,sCAAsC,KAAK,GAAG;AAAA,UAC5D;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EAAA;AAEJ;AC/DA,SAAS,kBAAgC;AACvC,QAAM,SAAS,OAAqB,iBAAiB;AACrD,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAGJ;AACA,SAAO;AACT;AASO,SAAS,gBAAgB;AAC9B,QAAM,QAAQ,eAAA;AACd,QAAM,SAAS,gBAAA;AACf,QAAM,EAAE,iBAAiB,WAAW,MAAM,OAAO,OAAO,UAAA,IAAc,YAAY,KAAK;AAIvF,QAAM,WAAW,SAAS,MAAM;AAC9B,QAAI,CAAC,KAAK,MAAO,QAAO;AAExB,UAAM,SAAS,CAAC,KAAK,MAAM,YAAY,KAAK,MAAM,WAAW,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AACvF,WAAO,KAAK,MAAM,QAAQ,UAAU;AAAA,EACtC,CAAC;AAID,iBAAe,OAAO,SAA8C;AAClE,UAAM,OAAO,OAAO,OAAO;AAAA,EAC7B;AAEA,iBAAe,QAAQ,SAA+C;AACpE,UAAM,OAAO,QAAQ,OAAO;AAAA,EAC9B;AAEA,iBAAe,aAAa,SAAsD;AAChF,WAAO,OAAO,aAAa,OAAO;AAAA,EACpC;AASA,WAAS,QAAQ,MAAuB;AACtC,QAAI,CAAC,KAAK,MAAO,QAAO;AAGxB,UAAM,SAAS,KAAK;AACpB,UAAM,QAAS,OAAO,SAAS,CAAA;AAC/B,WAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,IAAI;AAAA,EACpD;AAEA,SAAO;AAAA;AAAA,IAEL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAGA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAGA;AAAA,EAAA;AAEJ;"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/plugin.ts","../src/composables/useSSOClient.ts","../src/composables/useAuth.ts","../src/createB2CPlugin.ts","../src/broker-plugin.ts","../src/composables/useBrokerAuth.ts"],"sourcesContent":["import { ref } from \"vue\";\nimport { defineStore } from \"pinia\";\nimport { SSOClient } from \"@phila/sso-core\";\nimport type { App } from \"vue\";\nimport type { SSOClientConfig, SSOClientState, AuthResponse } from \"@phila/sso-core\";\n\nexport const SSO_CLIENT_KEY = Symbol(\"sso-client\");\n\nexport interface SSOPluginOptions {\n clientConfig: SSOClientConfig;\n autoInitialize?: boolean;\n}\n\nexport const useSSOStore = defineStore(\"sso\", () => {\n const isAuthenticated = ref(false);\n const isLoading = ref(false);\n const user = ref<SSOClientState[\"user\"]>(null);\n const token = ref<string | null>(null);\n const error = ref<Error | null>(null);\n const activePolicy = ref<string | null>(null);\n const authReady = ref(false);\n\n function syncState(state: SSOClientState) {\n isAuthenticated.value = state.isAuthenticated;\n isLoading.value = state.isLoading;\n user.value = state.user;\n token.value = state.token;\n error.value = state.error;\n activePolicy.value = state.activePolicy;\n authReady.value = state.authReady;\n }\n\n return { isAuthenticated, isLoading, user, token, error, activePolicy, authReady, syncState };\n});\n\nexport function createSSOPlugin(options: SSOPluginOptions) {\n return {\n install(app: App) {\n const client = new SSOClient(options.clientConfig);\n\n // Provide the client for useSSOClient()\n app.provide(SSO_CLIENT_KEY, client);\n\n // Subscribe to state changes and sync to Pinia store\n client.events.on(\"auth:stateChanged\", (state: SSOClientState) => {\n const store = useSSOStore();\n store.syncState(state);\n });\n\n // Auto-initialize unless explicitly disabled\n if (options.autoInitialize !== false) {\n client.initialize().then((response: AuthResponse | null) => {\n if (response && options.clientConfig.debug) {\n console.log(\"[sso-vue] Auto-initialized with response:\", response);\n }\n });\n }\n },\n };\n}\n","import { inject } from \"vue\";\nimport { SSOClient } from \"@phila/sso-core\";\nimport { SSO_CLIENT_KEY } from \"../plugin\";\n\n/**\n * Access the raw SSOClient instance.\n * Must be called within a component that is a descendant of createSSOPlugin.\n */\nexport function useSSOClient(): SSOClient {\n const client = inject<SSOClient>(SSO_CLIENT_KEY);\n if (!client) {\n throw new Error(\"SSOClient not found. Did you install createSSOPlugin?\");\n }\n return client;\n}\n","import { computed } from \"vue\";\nimport { storeToRefs } from \"pinia\";\nimport { useSSOStore } from \"../plugin\";\nimport { useSSOClient } from \"./useSSOClient\";\nimport type { SignInOptions, SignOutOptions, TokenOptions } from \"@phila/sso-core\";\n\n/**\n * Primary composable for SSO authentication in Vue 3 apps.\n * API shape is intentionally similar to service-cat's existing useAuth()\n * to minimize migration friction.\n */\nexport function useAuth() {\n const store = useSSOStore();\n const client = useSSOClient();\n const { isAuthenticated, isLoading, user, token, error, activePolicy, authReady } = storeToRefs(store);\n\n // Computed helpers\n const userName = computed(() => {\n const claims = user.value?.idTokenClaims as Record<string, unknown> | undefined;\n if (!claims) return null;\n const given = (claims.given_name ?? claims.name ?? \"\") as string;\n const family = (claims.family_name ?? \"\") as string;\n return family ? `${given} ${family}`.trim() : given;\n });\n\n // Actions\n async function signIn(options?: SignInOptions): Promise<void> {\n await client.signIn(options);\n }\n\n async function signInCityEmployee(options?: SignInOptions): Promise<void> {\n await client.signInCityEmployee(options);\n }\n\n async function signOut(options?: SignOutOptions): Promise<void> {\n await client.signOut(options);\n }\n\n async function forgotPassword(): Promise<void> {\n await client.forgotPassword();\n }\n\n async function acquireToken(options?: TokenOptions): Promise<string | null> {\n return client.acquireToken(options);\n }\n\n // Utilities\n function hasRole(role: string): boolean {\n const claims = user.value?.idTokenClaims as Record<string, unknown> | undefined;\n if (!claims) return false;\n\n const roles = (claims.roles ?? claims.extension_Roles ?? []) as string[];\n return Array.isArray(roles) && roles.includes(role);\n }\n\n return {\n // State (readonly refs)\n isAuthenticated,\n isLoading,\n user,\n token,\n error,\n activePolicy,\n authReady,\n userName,\n\n // Actions\n signIn,\n signInCityEmployee,\n signOut,\n forgotPassword,\n acquireToken,\n\n // Utilities\n hasRole,\n };\n}\n","// ABOUTME: Convenience factory for vanilla Vue/Vite apps using Azure AD B2C\n// ABOUTME: Reads VITE_SSO_* env vars by convention so apps need zero B2CProvider boilerplate\nimport { B2CProvider } from \"@phila/sso-core\";\nimport { createSSOPlugin } from \"./plugin\";\n\nexport interface B2CPluginOptions {\n signInPolicy?: string;\n resetPasswordPolicy?: string;\n debug?: boolean;\n}\n\n/**\n * Creates a ready-to-use Vue plugin for Azure AD B2C authentication.\n * Reads connection details from VITE_SSO_* environment variables:\n * VITE_SSO_CLIENT_ID, VITE_SSO_TENANT, VITE_SSO_AUTHORITY_DOMAIN, VITE_SSO_REDIRECT_URI\n */\nexport function createB2CPlugin(options: B2CPluginOptions = {}) {\n const {\n signInPolicy = \"B2C_1A_AD_SIGNIN_ONLY\",\n resetPasswordPolicy = \"B2C_1A_PASSWORDRESET\",\n debug = import.meta.env.DEV,\n } = options;\n\n return createSSOPlugin({\n clientConfig: {\n provider: new B2CProvider({\n clientId: import.meta.env.VITE_SSO_CLIENT_ID,\n b2cEnvironment: import.meta.env.VITE_SSO_TENANT,\n authorityDomain: import.meta.env.VITE_SSO_AUTHORITY_DOMAIN,\n redirectUri: import.meta.env.VITE_SSO_REDIRECT_URI,\n policies: {\n signUpSignIn: signInPolicy,\n signInOnly: signInPolicy,\n resetPassword: resetPasswordPolicy,\n },\n }),\n debug,\n },\n });\n}\n","// ABOUTME: Vue 3 plugin for the phila-identity broker — replaces createSSOPlugin() / useSSOStore().\n// ABOUTME: Uses BrokerClient instead of SSOClient, so there's no MSAL dependency.\n// ABOUTME:\n// ABOUTME: Store shape differences from the B2C plugin:\n// ABOUTME: - user is BrokerUser (not MSAL AccountInfo) — direct named properties, no idTokenClaims map\n// ABOUTME: - activePolicy is gone — the broker is policy-agnostic from the client's perspective\n// ABOUTME:\n// ABOUTME: Everything else (provide/inject, Pinia store, event wiring) is identical.\n\nimport { ref } from \"vue\";\nimport { defineStore } from \"pinia\";\nimport { BrokerClient } from \"@phila/sso-core\";\nimport type { App } from \"vue\";\nimport type { BrokerClientConfig, BrokerClientState } from \"@phila/sso-core\";\n\nexport const BROKER_CLIENT_KEY = Symbol(\"broker-client\");\n\n// ── Plugin options ─────────────────────────────────────────────────────────────\n\nexport interface BrokerPluginOptions {\n clientConfig: BrokerClientConfig;\n /**\n * Set false to skip the automatic initialize() call during install.\n * Useful when you want to call initialize() yourself at a specific lifecycle point.\n */\n autoInitialize?: boolean;\n}\n\n// ── Pinia store ────────────────────────────────────────────────────────────────\n\n/**\n * Same interface as useSSOStore() but with BrokerUser and no activePolicy.\n * Components can use this directly or go through useAuth() (which wraps it).\n */\nexport const useBrokerStore = defineStore(\"broker-sso\", () => {\n const isAuthenticated = ref(false);\n const isLoading = ref(false);\n const user = ref<BrokerClientState[\"user\"]>(null);\n const token = ref<string | null>(null);\n const setupPasskeyToken = ref<string | null>(null);\n const error = ref<Error | null>(null);\n const authReady = ref(false);\n\n function syncState(state: BrokerClientState) {\n isAuthenticated.value = state.isAuthenticated;\n isLoading.value = state.isLoading;\n user.value = state.user;\n token.value = state.token;\n setupPasskeyToken.value = state.setupPasskeyToken;\n error.value = state.error;\n authReady.value = state.authReady;\n }\n\n return { isAuthenticated, isLoading, user, token, setupPasskeyToken, error, authReady, syncState };\n});\n\n// ── Plugin factory ─────────────────────────────────────────────────────────────\n\nexport function createBrokerPlugin(options: BrokerPluginOptions) {\n return {\n install(app: App) {\n const client = new BrokerClient(options.clientConfig);\n\n app.provide(BROKER_CLIENT_KEY, client);\n\n client.events.on(\"auth:stateChanged\", (state: BrokerClientState) => {\n const store = useBrokerStore();\n store.syncState(state);\n });\n\n if (options.autoInitialize !== false) {\n client.initialize().then(user => {\n if (user && options.clientConfig.debug) {\n console.log(\"[broker-plugin] Initialized, user:\", user.sub);\n }\n });\n }\n },\n };\n}\n","// ABOUTME: useAuth() equivalent for broker-authenticated Vue 3 apps.\n// ABOUTME: API surface matches useAuth() from useAuth.ts so migration is find-and-replace.\n// ABOUTME:\n// ABOUTME: What's simpler compared to the B2C useAuth():\n// ABOUTME: - userName reads direct BrokerUser properties (no idTokenClaims map)\n// ABOUTME: - no forgotPassword() — handled entirely on the B2C side behind the broker\n// ABOUTME: - no signInCityEmployee() / policy-based sign-in — one signIn() covers all flows\n// ABOUTME: - hasRole() reads roles claim directly (not extension_Roles fallback)\n\nimport { computed, inject } from \"vue\";\nimport { storeToRefs } from \"pinia\";\nimport { useBrokerStore, BROKER_CLIENT_KEY } from \"../broker-plugin\";\nimport type { BrokerClient, BrokerSignInOptions, BrokerSignOutOptions, BrokerTokenOptions } from \"@phila/sso-core\";\n\nfunction useBrokerClient(): BrokerClient {\n const client = inject<BrokerClient>(BROKER_CLIENT_KEY);\n if (!client) {\n throw new Error(\n \"[useBrokerAuth] BrokerClient not found. \" +\n \"Did you install createBrokerPlugin() before calling useBrokerAuth()?\",\n );\n }\n return client;\n}\n\n/**\n * Primary composable for broker-authenticated Vue 3 apps.\n * Drop-in replacement for useAuth() — same returned shape, simpler internals.\n *\n * @example\n * const { isAuthenticated, user, signIn, signOut } = useBrokerAuth();\n */\nexport function useBrokerAuth() {\n const store = useBrokerStore();\n const client = useBrokerClient();\n const { isAuthenticated, isLoading, user, token, setupPasskeyToken, error, authReady } = storeToRefs(store);\n\n // ── Computed helpers ─────────────────────────────────────────────────────\n\n const userName = computed(() => {\n if (!user.value) return null;\n // BrokerUser has direct properties — no idTokenClaims indirection.\n const joined = [user.value.given_name, user.value.family_name].filter(Boolean).join(\" \");\n return user.value.name || joined || null;\n });\n\n // ── Actions ──────────────────────────────────────────────────────────────\n\n async function signIn(options?: BrokerSignInOptions): Promise<void> {\n await client.signIn(options);\n }\n\n async function signOut(options?: BrokerSignOutOptions): Promise<void> {\n await client.signOut(options);\n }\n\n async function acquireToken(options?: BrokerTokenOptions): Promise<string | null> {\n return client.acquireToken(options);\n }\n\n // ── Utilities ────────────────────────────────────────────────────────────\n\n /**\n * Check if the authenticated user has a given role.\n * The broker includes roles in the access token `scope` field by convention;\n * adjust the claim name here if your broker config uses a custom roles claim.\n */\n function hasRole(role: string): boolean {\n if (!user.value) return false;\n // Roles aren't yet standardized in the broker's token — placeholder for\n // when the broker adds a `roles` claim to the JWT payload.\n const claims = user.value as unknown as Record<string, unknown>;\n const roles = (claims.roles ?? []) as string[];\n return Array.isArray(roles) && roles.includes(role);\n }\n\n return {\n // State (readonly refs)\n isAuthenticated,\n isLoading,\n user,\n token,\n setupPasskeyToken,\n error,\n authReady,\n userName,\n\n // Actions\n signIn,\n signOut,\n acquireToken,\n\n // Utilities\n hasRole,\n };\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phila/sso-vue",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "description": "Vue 3 adapter for @phila/sso-core",
6
6
  "main": "./dist/index.js",
@@ -26,7 +26,7 @@
26
26
  "author": "City of Philadelphia",
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
- "@phila/sso-core": "0.1.0"
29
+ "@phila/sso-core": "0.2.0"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "vue": "^3.0.0",