npm package: @phila/sso-vue
Description: Vue 3 adapter for @phila/sso-core
Author: City of Philadelphia
Latest version: 0.0.9

# @phila/sso-vue

Vue 3 adapter for `@phila/sso-core`. Provides a Vue plugin, Pinia store, and composables for Azure AD B2C authentication.

## Installation

```bash
pnpm add @phila/sso-vue @phila/sso-core @azure/msal-browser pinia
```

## Quick Start (Vite + B2C)

The `createB2CPlugin` factory reads `VITE_SSO_*` environment variables automatically:

```env
VITE_SSO_CLIENT_ID=your-client-id
VITE_SSO_TENANT=YourTenant
VITE_SSO_AUTHORITY_DOMAIN=YourTenant.b2clogin.com
VITE_SSO_REDIRECT_URI=http://localhost:3000
```

```ts
// main.ts
import { createApp } from "vue";
import { createPinia } from "pinia";
import { createB2CPlugin } from "@phila/sso-vue";
import App from "./App.vue";

const app = createApp(App);
app.use(createPinia());
app.use(createB2CPlugin());
app.mount("#app");
```

```vue
<!-- App.vue -->
<script setup lang="ts">
import { useAuth } from "@phila/sso-vue";

const { isAuthenticated, userName, authReady, signIn, signOut } = useAuth();
</script>

<template>
  <div v-if="!authReady">Loading...</div>
  <div v-else-if="isAuthenticated">
    <p>Welcome, {{ userName }}</p>
    <button @click="signOut()">Sign out</button>
  </div>
  <div v-else>
    <button @click="signIn()">Sign in</button>
  </div>
</template>
```

## Advanced Setup

For full control over the provider configuration:

```ts
import { createSSOPlugin } from "@phila/sso-vue";
import { B2CProvider } from "@phila/sso-core";

app.use(
  createSSOPlugin({
    clientConfig: {
      provider: new B2CProvider({
        clientId: "your-client-id",
        b2cEnvironment: "YourTenant",
        authorityDomain: "YourTenant.b2clogin.com",
        redirectUri: "http://localhost:3000",
        apiScopes: ["https://YourTenant.onmicrosoft.com/api/read"],
        policies: {
          signUpSignIn: "B2C_1A_SIGNUP_SIGNIN",
          signInOnly: "B2C_1A_AD_SIGNIN_ONLY",
          resetPassword: "B2C_1A_PASSWORDRESET",
        },
      }),
      debug: true,
    },
  }),
);
```

### Plugin Options

```ts
interface SSOPluginOptions {
  clientConfig: SSOClientConfig;
  autoInitialize?: boolean; // default: true
}
```

## Composables

### `useAuth()`

Primary composable for authentication. Must be called after the plugin is installed.

**Reactive state:**

| Property          | Type                          | Description                    |
| ----------------- | ----------------------------- | ------------------------------ |
| `isAuthenticated` | `Ref<boolean>`                | User is signed in              |
| `isLoading`       | `Ref<boolean>`                | Auth operation in progress     |
| `user`            | `Ref<AccountInfo \| null>`    | MSAL account info              |
| `token`           | `Ref<string \| null>`         | Current access token           |
| `error`           | `Ref<Error \| null>`          | Last auth error                |
| `activePolicy`    | `Ref<string \| null>`         | Active B2C policy              |
| `authReady`       | `Ref<boolean>`                | Initialization complete        |
| `userName`        | `ComputedRef<string \| null>` | Display name from token claims |

**Actions:**

| Method                         | Returns                   | Description                      |
| ------------------------------ | ------------------------- | -------------------------------- |
| `signIn(options?)`             | `Promise<void>`           | Start sign-in flow               |
| `signInCityEmployee(options?)` | `Promise<void>`           | Sign in with sign-in-only policy |
| `signOut(options?)`            | `Promise<void>`           | Sign out                         |
| `forgotPassword()`             | `Promise<void>`           | Start password reset             |
| `acquireToken(options?)`       | `Promise<string \| null>` | Get access token                 |

**Utilities:**

| Method          | Returns   | Description                                             |
| --------------- | --------- | ------------------------------------------------------- |
| `hasRole(role)` | `boolean` | Check user role from `roles` or `extension_Roles` claim |

### `useSSOClient()`

Returns the raw `SSOClient` instance for advanced use cases (direct event subscription, etc.).

```ts
const client = useSSOClient();
client.events.on("auth:tokenAcquired", token => {
  /* ... */
});
```

### `useSSOStore()`

Direct access to the Pinia store. Useful when you need store-level reactivity outside of components.

```ts
import { useSSOStore } from "@phila/sso-vue";

const store = useSSOStore();
watch(
  () => store.isAuthenticated,
  val => {
    /* ... */
  },
);
```

## `createB2CPlugin` Options

```ts
interface B2CPluginOptions {
  signInPolicy?: string; // default: "B2C_1A_AD_SIGNIN_ONLY"
  resetPasswordPolicy?: string; // default: "B2C_1A_PASSWORDRESET"
  debug?: boolean; // default: import.meta.env.DEV
}
```

## License

MIT