@chemmangat/msal-next 4.0.1 → 4.1.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.mts CHANGED
@@ -264,6 +264,41 @@ interface MsalAuthConfig {
264
264
  * ```
265
265
  */
266
266
  onInitialized?: (instance: IPublicClientApplication) => void;
267
+ /**
268
+ * Enable automatic token refresh
269
+ *
270
+ * @remarks
271
+ * Automatically refreshes access tokens before they expire to prevent
272
+ * session interruptions. Tokens are refreshed silently in the background.
273
+ *
274
+ * @defaultValue false
275
+ *
276
+ * @example
277
+ * ```tsx
278
+ * <MSALProvider
279
+ * clientId="..."
280
+ * autoRefreshToken={true}
281
+ * refreshBeforeExpiry={300} // Refresh 5 min before expiry
282
+ * >
283
+ * {children}
284
+ * </MSALProvider>
285
+ * ```
286
+ */
287
+ autoRefreshToken?: boolean;
288
+ /**
289
+ * Refresh token this many seconds before expiry
290
+ *
291
+ * @remarks
292
+ * Only used when autoRefreshToken is enabled.
293
+ *
294
+ * @defaultValue 300 (5 minutes)
295
+ *
296
+ * @example
297
+ * ```tsx
298
+ * refreshBeforeExpiry={600} // Refresh 10 minutes before expiry
299
+ * ```
300
+ */
301
+ refreshBeforeExpiry?: number;
267
302
  }
268
303
  /**
269
304
  * Props for MsalAuthProvider component
@@ -283,7 +318,7 @@ interface MsalAuthProviderProps extends MsalAuthConfig {
283
318
  * @returns The MSAL instance or null if not initialized
284
319
  */
285
320
  declare function getMsalInstance(): PublicClientApplication | null;
286
- declare function MsalAuthProvider({ children, loadingComponent, onInitialized, ...config }: MsalAuthProviderProps): react_jsx_runtime.JSX.Element;
321
+ declare function MsalAuthProvider({ children, loadingComponent, onInitialized, autoRefreshToken, refreshBeforeExpiry, ...config }: MsalAuthProviderProps): react_jsx_runtime.JSX.Element;
287
322
 
288
323
  /**
289
324
  * Zero-Config Protected Routes - Type Definitions
@@ -393,12 +428,15 @@ interface MSALProviderProps extends MsalAuthProviderProps {
393
428
  }
394
429
  /**
395
430
  * Pre-configured MSALProvider component for Next.js App Router layouts.
396
- * This component is already marked as 'use client', so you can use it directly
397
- * in your server-side layout.tsx without needing to create a separate client component.
431
+ *
432
+ * @remarks
433
+ * This component is already marked as 'use client' internally, so you can import
434
+ * and use it directly in your server-side layout.tsx without adding 'use client'
435
+ * to your layout file.
398
436
  *
399
437
  * @example
400
438
  * ```tsx
401
- * // app/layout.tsx
439
+ * // app/layout.tsx (Server Component - no 'use client' needed!)
402
440
  * import { MSALProvider } from '@chemmangat/msal-next'
403
441
  *
404
442
  * export default function RootLayout({ children }) {
@@ -416,6 +454,13 @@ interface MSALProviderProps extends MsalAuthProviderProps {
416
454
  * )
417
455
  * }
418
456
  * ```
457
+ *
458
+ * @security
459
+ * - All authentication happens client-side (browser)
460
+ * - Tokens are never sent to your Next.js server
461
+ * - Uses Microsoft's official MSAL library
462
+ * - Supports secure token storage (sessionStorage/localStorage)
463
+ * - No server-side token handling required
419
464
  */
420
465
  declare function MSALProvider({ children, protection, ...props }: MSALProviderProps): react_jsx_runtime.JSX.Element;
421
466
 
@@ -748,24 +793,116 @@ interface UseGraphApiReturn {
748
793
  */
749
794
  declare function useGraphApi(): UseGraphApiReturn;
750
795
 
796
+ /**
797
+ * Complete Microsoft Graph User Profile Types
798
+ * Based on Microsoft Graph /me endpoint
799
+ *
800
+ * @see https://learn.microsoft.com/en-us/graph/api/user-get
801
+ */
802
+ /**
803
+ * Complete user profile from Microsoft Graph /me endpoint
804
+ *
805
+ * @remarks
806
+ * This interface includes all common fields returned by the Microsoft Graph /me endpoint.
807
+ * You can extend this interface with custom fields specific to your organization.
808
+ *
809
+ * @example
810
+ * ```tsx
811
+ * // Basic usage
812
+ * const { profile } = useUserProfile();
813
+ * console.log(profile?.department); // Now type-safe!
814
+ *
815
+ * // With custom fields
816
+ * interface MyUserProfile extends UserProfile {
817
+ * customField: string;
818
+ * }
819
+ *
820
+ * const { profile } = useUserProfile<MyUserProfile>();
821
+ * console.log(profile?.customField);
822
+ * ```
823
+ */
751
824
  interface UserProfile {
825
+ /** Unique identifier for the user */
752
826
  id: string;
827
+ /** User's display name */
753
828
  displayName: string;
829
+ /** User's first name */
754
830
  givenName: string;
831
+ /** User's last name */
755
832
  surname: string;
833
+ /** User principal name (UPN) - typically the email used for login */
756
834
  userPrincipalName: string;
835
+ /** Primary email address */
757
836
  mail: string;
837
+ /** Job title */
758
838
  jobTitle?: string;
839
+ /** Department name */
840
+ department?: string;
841
+ /** Company name */
842
+ companyName?: string;
843
+ /** Office location */
759
844
  officeLocation?: string;
845
+ /** Mobile phone number */
760
846
  mobilePhone?: string;
847
+ /** Business phone numbers */
761
848
  businessPhones?: string[];
849
+ /** Preferred language (e.g., "en-US") */
850
+ preferredLanguage?: string;
851
+ /** Employee ID */
852
+ employeeId?: string;
853
+ /** Employee hire date */
854
+ employeeHireDate?: string;
855
+ /** Employee type (e.g., "Employee", "Contractor") */
856
+ employeeType?: string;
857
+ /** Country/region */
858
+ country?: string;
859
+ /** City */
860
+ city?: string;
861
+ /** State or province */
862
+ state?: string;
863
+ /** Street address */
864
+ streetAddress?: string;
865
+ /** Postal code */
866
+ postalCode?: string;
867
+ /** Usage location (ISO 3166 country code) */
868
+ usageLocation?: string;
869
+ /** Manager's user ID */
870
+ manager?: string;
871
+ /** About me / bio */
872
+ aboutMe?: string;
873
+ /** Birthday */
874
+ birthday?: string;
875
+ /** Interests */
876
+ interests?: string[];
877
+ /** Skills */
878
+ skills?: string[];
879
+ /** Schools attended */
880
+ schools?: string[];
881
+ /** Past projects */
882
+ pastProjects?: string[];
883
+ /** Responsibilities */
884
+ responsibilities?: string[];
885
+ /** My site URL */
886
+ mySite?: string;
887
+ /** Fax number */
888
+ faxNumber?: string;
889
+ /** Account enabled status */
890
+ accountEnabled?: boolean;
891
+ /** Age group (e.g., "Adult", "Minor") */
892
+ ageGroup?: string;
893
+ /** User type (e.g., "Member", "Guest") */
894
+ userType?: string;
895
+ /** Profile photo URL (blob URL created by the library) */
762
896
  photo?: string;
763
897
  }
764
- interface UseUserProfileReturn {
898
+ /**
899
+ * Return type for useUserProfile hook
900
+ */
901
+ interface UseUserProfileReturn<T extends UserProfile = UserProfile> {
765
902
  /**
766
903
  * User profile data
767
904
  */
768
- profile: UserProfile | null;
905
+ profile: T | null;
769
906
  /**
770
907
  * Whether profile is loading
771
908
  */
@@ -783,15 +920,27 @@ interface UseUserProfileReturn {
783
920
  */
784
921
  clearCache: () => void;
785
922
  }
923
+
786
924
  /**
787
925
  * Hook for fetching and caching user profile from MS Graph
788
926
  *
927
+ * @remarks
928
+ * Supports generic type parameter for custom profile fields.
929
+ *
789
930
  * @example
790
931
  * ```tsx
932
+ * // Basic usage
791
933
  * const { profile, loading } = useUserProfile();
934
+ * console.log(profile?.department); // Now available!
935
+ *
936
+ * // With custom fields
937
+ * interface MyProfile extends UserProfile {
938
+ * customField: string;
939
+ * }
940
+ * const { profile } = useUserProfile<MyProfile>();
792
941
  * ```
793
942
  */
794
- declare function useUserProfile(): UseUserProfileReturn;
943
+ declare function useUserProfile<T extends UserProfile = UserProfile>(): UseUserProfileReturn<T>;
795
944
 
796
945
  interface UseRolesReturn {
797
946
  /**
@@ -844,6 +993,80 @@ interface UseRolesReturn {
844
993
  */
845
994
  declare function useRoles(): UseRolesReturn;
846
995
 
996
+ /**
997
+ * Automatic token refresh hook
998
+ * Refreshes tokens before they expire to prevent session interruptions
999
+ */
1000
+ interface UseTokenRefreshOptions {
1001
+ /**
1002
+ * Enable automatic token refresh
1003
+ * @default true
1004
+ */
1005
+ enabled?: boolean;
1006
+ /**
1007
+ * Refresh token this many seconds before expiry
1008
+ * @default 300 (5 minutes)
1009
+ */
1010
+ refreshBeforeExpiry?: number;
1011
+ /**
1012
+ * Scopes to refresh
1013
+ * @default ['User.Read']
1014
+ */
1015
+ scopes?: string[];
1016
+ /**
1017
+ * Callback when token is refreshed
1018
+ */
1019
+ onRefresh?: (expiresIn: number) => void;
1020
+ /**
1021
+ * Callback when refresh fails
1022
+ */
1023
+ onError?: (error: Error) => void;
1024
+ }
1025
+ interface UseTokenRefreshReturn {
1026
+ /**
1027
+ * Seconds until token expires
1028
+ */
1029
+ expiresIn: number | null;
1030
+ /**
1031
+ * Whether token is expiring soon
1032
+ */
1033
+ isExpiringSoon: boolean;
1034
+ /**
1035
+ * Manually trigger token refresh
1036
+ */
1037
+ refresh: () => Promise<void>;
1038
+ /**
1039
+ * Last refresh timestamp
1040
+ */
1041
+ lastRefresh: Date | null;
1042
+ }
1043
+ /**
1044
+ * Hook for automatic token refresh
1045
+ *
1046
+ * @remarks
1047
+ * Automatically refreshes access tokens before they expire to prevent
1048
+ * session interruptions. Runs in the background without user interaction.
1049
+ *
1050
+ * @example
1051
+ * ```tsx
1052
+ * // Basic usage - automatic refresh
1053
+ * useTokenRefresh();
1054
+ *
1055
+ * // With options
1056
+ * const { expiresIn, isExpiringSoon } = useTokenRefresh({
1057
+ * refreshBeforeExpiry: 600, // 10 minutes
1058
+ * scopes: ['User.Read', 'Mail.Read'],
1059
+ * onRefresh: (expiresIn) => console.log(`Token refreshed, expires in ${expiresIn}s`),
1060
+ * });
1061
+ *
1062
+ * // Show warning when expiring soon
1063
+ * if (isExpiringSoon) {
1064
+ * return <div>Your session will expire soon</div>;
1065
+ * }
1066
+ * ```
1067
+ */
1068
+ declare function useTokenRefresh(options?: UseTokenRefreshOptions): UseTokenRefreshReturn;
1069
+
847
1070
  declare function createMsalConfig(config: MsalAuthConfig): Configuration;
848
1071
 
849
1072
  interface WithAuthOptions extends Omit<AuthGuardProps, 'children'> {
@@ -1114,6 +1337,107 @@ declare function isValidScope(scope: string): boolean;
1114
1337
  */
1115
1338
  declare function validateScopes(scopes: string[]): boolean;
1116
1339
 
1340
+ /**
1341
+ * Development-mode configuration validator
1342
+ * Helps developers catch common configuration mistakes early
1343
+ */
1344
+
1345
+ interface ValidationResult {
1346
+ valid: boolean;
1347
+ warnings: ValidationWarning[];
1348
+ errors: ValidationError[];
1349
+ }
1350
+ interface ValidationWarning {
1351
+ field: string;
1352
+ message: string;
1353
+ fix: string;
1354
+ }
1355
+ interface ValidationError {
1356
+ field: string;
1357
+ message: string;
1358
+ fix: string;
1359
+ }
1360
+ /**
1361
+ * Validate MSAL configuration in development mode
1362
+ *
1363
+ * @remarks
1364
+ * This function only runs in development mode and caches results.
1365
+ * It checks for common configuration mistakes and provides helpful warnings.
1366
+ *
1367
+ * @example
1368
+ * ```tsx
1369
+ * const result = validateConfig({
1370
+ * clientId: process.env.NEXT_PUBLIC_AZURE_AD_CLIENT_ID!,
1371
+ * tenantId: process.env.NEXT_PUBLIC_AZURE_AD_TENANT_ID,
1372
+ * });
1373
+ *
1374
+ * if (!result.valid) {
1375
+ * console.warn('Configuration issues detected');
1376
+ * }
1377
+ * ```
1378
+ */
1379
+ declare function validateConfig(config: MsalAuthConfig): ValidationResult;
1380
+ /**
1381
+ * Display validation results in console with colors and emojis
1382
+ */
1383
+ declare function displayValidationResults(result: ValidationResult): void;
1384
+
1385
+ /**
1386
+ * Enhanced MSAL error class with actionable messages
1387
+ */
1388
+ declare class MsalError extends Error {
1389
+ /** Original error code from MSAL */
1390
+ readonly code?: string;
1391
+ /** Actionable fix instructions */
1392
+ readonly fix?: string;
1393
+ /** Documentation link */
1394
+ readonly docs?: string;
1395
+ /** Original error object */
1396
+ readonly originalError?: unknown;
1397
+ constructor(error: unknown);
1398
+ /**
1399
+ * Parse error and extract actionable information
1400
+ */
1401
+ private static parseError;
1402
+ /**
1403
+ * Format error for console logging with colors (development only)
1404
+ */
1405
+ toConsoleString(): string;
1406
+ /**
1407
+ * Check if error is a user cancellation (not a real error)
1408
+ */
1409
+ isUserCancellation(): boolean;
1410
+ /**
1411
+ * Check if error requires user interaction
1412
+ */
1413
+ requiresInteraction(): boolean;
1414
+ }
1415
+ /**
1416
+ * Wrap MSAL errors with enhanced error information
1417
+ *
1418
+ * @example
1419
+ * ```tsx
1420
+ * try {
1421
+ * await loginRedirect();
1422
+ * } catch (error) {
1423
+ * const msalError = wrapMsalError(error);
1424
+ *
1425
+ * if (msalError.isUserCancellation()) {
1426
+ * // User cancelled, ignore
1427
+ * return;
1428
+ * }
1429
+ *
1430
+ * console.error(msalError.toConsoleString());
1431
+ * throw msalError;
1432
+ * }
1433
+ * ```
1434
+ */
1435
+ declare function wrapMsalError(error: unknown): MsalError;
1436
+ /**
1437
+ * Create error for missing environment variable
1438
+ */
1439
+ declare function createMissingEnvVarError(varName: string): MsalError;
1440
+
1117
1441
  interface ProtectedPageProps {
1118
1442
  children: ReactNode;
1119
1443
  config: PageAuthConfig;
@@ -1224,4 +1548,4 @@ interface ServerSession {
1224
1548
  accessToken?: string;
1225
1549
  }
1226
1550
 
1227
- export { AuthGuard, type AuthGuardProps, type AuthMiddlewareConfig, type AuthProtectionConfig, AuthStatus, type AuthStatusProps, type CustomTokenClaims, type DebugLoggerConfig, ErrorBoundary, type ErrorBoundaryProps, type GraphApiOptions, MSALProvider, MicrosoftSignInButton, type MicrosoftSignInButtonProps, type MsalAuthConfig, MsalAuthProvider, type MsalAuthProviderProps, type PageAuthConfig, ProtectedPage, type RetryConfig, type ServerSession, SignOutButton, type SignOutButtonProps, type UseGraphApiReturn, type UseMsalAuthReturn, type UseRolesReturn, type UseUserProfileReturn, UserAvatar, type UserAvatarProps, type UserProfile, type ValidatedAccountData, type WithAuthOptions, createAuthMiddleware, createMsalConfig, createRetryWrapper, createScopedLogger, getDebugLogger, getMsalInstance, isValidAccountData, isValidRedirectUri, isValidScope, retryWithBackoff, safeJsonParse, sanitizeError, useGraphApi, useMsalAuth, useRoles, useUserProfile, validateScopes, withAuth, withPageAuth };
1551
+ export { AuthGuard, type AuthGuardProps, type AuthMiddlewareConfig, type AuthProtectionConfig, AuthStatus, type AuthStatusProps, type CustomTokenClaims, type DebugLoggerConfig, ErrorBoundary, type ErrorBoundaryProps, type GraphApiOptions, MSALProvider, MicrosoftSignInButton, type MicrosoftSignInButtonProps, type MsalAuthConfig, MsalAuthProvider, type MsalAuthProviderProps, MsalError, type PageAuthConfig, ProtectedPage, type RetryConfig, type ServerSession, SignOutButton, type SignOutButtonProps, type UseGraphApiReturn, type UseMsalAuthReturn, type UseRolesReturn, type UseTokenRefreshOptions, type UseTokenRefreshReturn, type UseUserProfileReturn, UserAvatar, type UserAvatarProps, type UserProfile, type ValidatedAccountData, type ValidationError, type ValidationResult, type ValidationWarning, type WithAuthOptions, createAuthMiddleware, createMissingEnvVarError, createMsalConfig, createRetryWrapper, createScopedLogger, displayValidationResults, getDebugLogger, getMsalInstance, isValidAccountData, isValidRedirectUri, isValidScope, retryWithBackoff, safeJsonParse, sanitizeError, useGraphApi, useMsalAuth, useRoles, useTokenRefresh, useUserProfile, validateConfig, validateScopes, withAuth, withPageAuth, wrapMsalError };