@chemmangat/msal-next 4.2.0 → 4.2.1

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 (2) hide show
  1. package/README.md +137 -14
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -6,7 +6,7 @@ Production-grade MSAL authentication library for Next.js App Router with minimal
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
  [![Security](https://img.shields.io/badge/Security-A+-green.svg)](./SECURITY.md)
8
8
 
9
- > **📦 Current Version: 4.1.1** - Production-ready with automatic token refresh and enhanced security
9
+ > **📦 Current Version: 4.2.1** - Production-ready with automatic token refresh and enhanced security
10
10
 
11
11
  ---
12
12
 
@@ -466,6 +466,7 @@ Pre-styled sign-in button with Microsoft branding.
466
466
  variant="dark" // or "light"
467
467
  size="medium" // "small", "medium", "large"
468
468
  onSuccess={() => console.log('Signed in!')}
469
+ onError={(error) => console.error(error)}
469
470
  />
470
471
  ```
471
472
 
@@ -477,6 +478,7 @@ Pre-styled sign-out button.
477
478
  variant="light"
478
479
  size="medium"
479
480
  onSuccess={() => console.log('Signed out!')}
481
+ onError={(error) => console.error(error)}
480
482
  />
481
483
  ```
482
484
 
@@ -510,13 +512,16 @@ Main authentication hook.
510
512
 
511
513
  ```tsx
512
514
  const {
513
- account, // Current user account
514
- accounts, // All cached accounts
515
- isAuthenticated, // Boolean: is user signed in?
516
- inProgress, // Boolean: is auth in progress?
517
- loginRedirect, // Function: sign in
518
- logoutRedirect, // Function: sign out
519
- acquireToken, // Function: get access token
515
+ account, // Current user account
516
+ accounts, // All cached accounts
517
+ isAuthenticated, // Boolean: is user signed in?
518
+ inProgress, // Boolean: is auth in progress?
519
+ loginRedirect, // Function: sign in (redirect flow)
520
+ logoutRedirect, // Function: sign out (redirect flow)
521
+ acquireToken, // Function: get access token (silent with redirect fallback)
522
+ acquireTokenSilent, // Function: get access token (silent only, no fallback)
523
+ acquireTokenRedirect, // Function: get access token via redirect
524
+ clearSession, // Function: clear MSAL session without Microsoft logout
520
525
  } = useMsalAuth();
521
526
  ```
522
527
 
@@ -553,18 +558,30 @@ const message = await graph.post('/me/messages', {
553
558
  subject: 'Hello',
554
559
  body: { content: 'World' }
555
560
  });
561
+
562
+ // PUT, PATCH, DELETE
563
+ await graph.put('/me/photo/$value', photoBlob);
564
+ await graph.patch('/me', { displayName: 'New Name' });
565
+ await graph.delete('/me/messages/{id}');
566
+
567
+ // Custom request with options
568
+ const data = await graph.request('/me', { version: 'beta', scopes: ['User.Read'] });
556
569
  ```
557
570
 
558
571
  #### useRoles()
559
- Access user's Azure AD roles.
572
+ Access user's Azure AD roles and groups.
560
573
 
561
574
  ```tsx
562
575
  const {
563
576
  roles, // Array of role names
564
577
  groups, // Array of group IDs
578
+ loading, // Boolean: is loading?
579
+ error, // Error object if failed
565
580
  hasRole, // Function: check single role
566
- hasAnyRole, // Function: check multiple roles
567
- hasAllRoles, // Function: check all roles
581
+ hasGroup, // Function: check single group by ID
582
+ hasAnyRole, // Function: check if user has any of the given roles
583
+ hasAllRoles, // Function: check if user has all of the given roles
584
+ refetch, // Function: refetch roles and groups
568
585
  } = useRoles();
569
586
 
570
587
  if (hasRole('Admin')) {
@@ -572,9 +589,109 @@ if (hasRole('Admin')) {
572
589
  }
573
590
  ```
574
591
 
592
+ #### useTokenRefresh()
593
+ Monitor and control token refresh state.
594
+
595
+ ```tsx
596
+ const {
597
+ expiresIn, // Seconds until token expires (null if unknown)
598
+ isExpiringSoon, // Boolean: token expiring within threshold
599
+ refresh, // Function: manually trigger token refresh
600
+ lastRefresh, // Date: when token was last refreshed
601
+ } = useTokenRefresh({
602
+ refreshBeforeExpiry: 300, // seconds before expiry to refresh
603
+ scopes: ['User.Read'],
604
+ onRefresh: (expiresIn) => console.log(`Refreshed, expires in ${expiresIn}s`),
605
+ onError: (error) => console.error(error),
606
+ });
607
+ ```
608
+
609
+ #### useMultiAccount()
610
+ Manage multiple signed-in Microsoft accounts.
611
+
612
+ ```tsx
613
+ const {
614
+ accounts, // All signed-in accounts
615
+ activeAccount, // Currently active account
616
+ hasMultipleAccounts, // Boolean: more than one account signed in
617
+ accountCount, // Number of signed-in accounts
618
+ inProgress, // Boolean: interaction in progress
619
+ switchAccount, // Function: switch active account
620
+ addAccount, // Function: sign in with another account
621
+ removeAccount, // Function: remove account from cache
622
+ signOutAccount, // Function: sign out a specific account
623
+ signOutAll, // Function: sign out all accounts
624
+ getAccountByUsername, // Function: find account by username
625
+ getAccountById, // Function: find account by homeAccountId
626
+ isActiveAccount, // Function: check if account is active
627
+ } = useMultiAccount();
628
+ ```
629
+
575
630
  ---
576
631
 
577
- ## 🎓 Advanced Usage
632
+ ### Additional Components
633
+
634
+ #### AccountSwitcher
635
+ Pre-built UI for switching between multiple signed-in accounts.
636
+
637
+ ```tsx
638
+ <AccountSwitcher
639
+ showAvatars={true}
640
+ maxAccounts={5}
641
+ variant="default" // "default", "compact", "minimal"
642
+ showAddButton={true}
643
+ showRemoveButton={true}
644
+ onSwitch={(account) => console.log('Switched to', account.name)}
645
+ onAdd={() => console.log('Adding account')}
646
+ onRemove={(account) => console.log('Removed', account.name)}
647
+ />
648
+ ```
649
+
650
+ #### AccountList
651
+ Display all signed-in accounts in a list.
652
+
653
+ ```tsx
654
+ <AccountList
655
+ showAvatars={true}
656
+ showDetails={true}
657
+ showActiveIndicator={true}
658
+ clickToSwitch={true}
659
+ orientation="vertical" // or "horizontal"
660
+ onAccountClick={(account) => console.log('Clicked', account.name)}
661
+ />
662
+ ```
663
+
664
+ ---
665
+
666
+ ### Higher-Order Components
667
+
668
+ #### withAuth
669
+ Protect a component by wrapping it with `AuthGuard`.
670
+
671
+ ```tsx
672
+ const ProtectedPage = withAuth(MyPage);
673
+
674
+ // With options
675
+ const ProtectedPage = withAuth(MyPage, {
676
+ loadingComponent: <Spinner />,
677
+ fallbackComponent: <div>Please sign in</div>,
678
+ scopes: ['User.Read'],
679
+ });
680
+ ```
681
+
682
+ #### withPageAuth
683
+ Add page-level auth protection with role support.
684
+
685
+ ```tsx
686
+ const ProtectedDashboard = withPageAuth(Dashboard, {
687
+ required: true,
688
+ roles: ['Admin', 'Editor'],
689
+ redirectTo: '/login',
690
+ });
691
+ export default ProtectedDashboard;
692
+ ```
693
+
694
+ ---
578
695
 
579
696
  ### Automatic Token Refresh (NEW in v4.1.0)
580
697
 
@@ -598,12 +715,13 @@ Prevent unexpected logouts by automatically refreshing tokens before they expire
598
715
  import { useTokenRefresh } from '@chemmangat/msal-next';
599
716
 
600
717
  export default function SessionWarning() {
601
- const { expiresIn, isExpiringSoon } = useTokenRefresh();
718
+ const { expiresIn, isExpiringSoon, refresh, lastRefresh } = useTokenRefresh();
602
719
 
603
720
  if (isExpiringSoon) {
604
721
  return (
605
722
  <div className="warning">
606
- ⚠️ Your session will expire in {Math.floor(expiresIn / 60)} minutes
723
+ ⚠️ Your session will expire in {Math.floor((expiresIn ?? 0) / 60)} minutes
724
+ <button onClick={refresh}>Refresh now</button>
607
725
  </div>
608
726
  );
609
727
  }
@@ -752,9 +870,14 @@ export default function ProfilePage() {
752
870
  | `tenantId` | `string` | No | - | Azure AD Directory (tenant) ID (for single-tenant) |
753
871
  | `authorityType` | `'common' \| 'organizations' \| 'consumers' \| 'tenant'` | No | `'common'` | Authority type |
754
872
  | `redirectUri` | `string` | No | `window.location.origin` | Redirect URI after authentication |
873
+ | `postLogoutRedirectUri` | `string` | No | `redirectUri` | Redirect URI after logout |
755
874
  | `scopes` | `string[]` | No | `['User.Read']` | Default scopes |
756
875
  | `cacheLocation` | `'sessionStorage' \| 'localStorage' \| 'memoryStorage'` | No | `'sessionStorage'` | Token cache location |
757
876
  | `enableLogging` | `boolean` | No | `false` | Enable debug logging |
877
+ | `autoRefreshToken` | `boolean` | No | `false` | Automatically refresh tokens before expiry |
878
+ | `refreshBeforeExpiry` | `number` | No | `300` | Seconds before expiry to refresh token |
879
+ | `allowedRedirectUris` | `string[]` | No | - | Whitelist of allowed redirect URIs |
880
+ | `protection` | `AuthProtectionConfig` | No | - | Zero-config protected routes configuration |
758
881
 
759
882
  ### Authority Types
760
883
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chemmangat/msal-next",
3
- "version": "4.2.0",
3
+ "version": "4.2.1",
4
4
  "description": "Production-ready Microsoft/Azure AD authentication for Next.js App Router. Zero-config setup, TypeScript-first, multi-account support, auto token refresh. The easiest way to add Microsoft login to your Next.js app.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",