ngx-auth
Version:
Angular 20+ Authentication module
1 lines • 10.8 kB
Source Map (JSON)
{"version":3,"file":"ngx-auth.mjs","sources":["../../src/auth.service.ts","../../src/auth.interceptor.ts","../../src/protected.guard.ts","../../src/public.guard.ts","../../src/providers.ts","../../src/ngx-auth.ts"],"sourcesContent":["import { type HttpErrorResponse, type HttpRequest } from '@angular/common/http';\nimport { InjectionToken } from '@angular/core';\nimport { type Observable } from 'rxjs';\n\n/**\n * Essential service for authentication\n */\nexport abstract class NgxAuthService {\n /**\n * Get access token\n * Should return access token in Observable from e.g.\n * localStorage\n */\n abstract getAccessToken(): Promise<string | null> | Observable<string | null>;\n\n /**\n * Add token to headers, dependent on server\n * set-up, by default adds a bearer token.\n * Called by interceptor.\n * To change behavior, override this method.\n */\n abstract getHeaders?(token: string): Record<string, string | string[]>;\n\n /**\n * Check, if user already authorized.\n * Should return Observable with true or false values\n */\n abstract isAuthenticated(): Promise<boolean> | Observable<boolean>;\n\n /**\n * Function, checks response of failed request to determine,\n * whether token be refreshed or not.\n *\n * Essentially checks status\n */\n abstract refreshShouldHappen(response: HttpErrorResponse, request?: HttpRequest<any>): boolean;\n\n /**\n * Function, that should perform refresh token\n * Should be successfully completed so interceptor\n * can execute pending requests or retry original one\n */\n abstract refreshToken(): Promise<any> | Observable<any>;\n\n /**\n * Saves last interrupted url inside of the service for further reusage,\n * e.g. restoring interrupted page after logging in\n */\n abstract setInterruptedUrl?(url: string): void;\n\n /**\n * Checks if request must be skipped by interceptor.\n * Useful for requests such as request token which doesn't require token in headers\n */\n abstract skipRequest(request: HttpRequest<any>): boolean;\n}\n\nexport const AUTH_SERVICE = new InjectionToken<NgxAuthService>('ngx-auth--service');\n","import { HttpClient, type HttpErrorResponse, type HttpHandlerFn, type HttpInterceptorFn, type HttpRequest } from '@angular/common/http';\nimport { inject, signal } from '@angular/core';\nimport { catchError, first, from, map, Subject, switchMap, throwError } from 'rxjs';\n\nimport { AUTH_SERVICE, type NgxAuthService } from './auth.service';\n\nexport const NgxRefreshInProgress = signal(false);\nconst delay$ = new Subject<boolean>();\n\nexport const ngxAuthInterceptor: HttpInterceptorFn = (req: HttpRequest<unknown>, next: HttpHandlerFn) => {\n const authService = inject(AUTH_SERVICE);\n const http = inject(HttpClient);\n\n if (authService.skipRequest(req)) {\n return next(req);\n }\n\n const request$ = NgxRefreshInProgress()\n ? delayRequest(authService, req)\n : addToken(authService, req);\n\n return request$.pipe(\n switchMap(req => next(req)),\n catchError(res => responseError(authService, http, req, res)),\n );\n};\n\n/**\n * Add access token to headers or the request\n */\nfunction addToken(authService: NgxAuthService, req: HttpRequest<any>) {\n return from(authService.getAccessToken())\n .pipe(\n first(),\n map(token => {\n if (token) {\n return req.clone({\n setHeaders: authService.getHeaders?.(token) ?? { Authorization: `Bearer ${token}` },\n });\n }\n\n return req;\n }),\n );\n}\n\n/**\n * Delay request, by subscribing on refresh event, once it finished, process it\n * otherwise throw error\n */\nfunction delayRequest(authService: NgxAuthService, req: HttpRequest<any>) {\n return delay$.pipe(\n first(),\n switchMap(canDelay => canDelay\n ? addToken(authService, req)\n : throwError(() => req),\n ),\n );\n}\n\n/**\n * Failed request interceptor, check if it has to be processed with refresh\n */\nfunction responseError(\n authService: NgxAuthService,\n http: HttpClient,\n req: HttpRequest<any>,\n res: HttpErrorResponse,\n) {\n const refreshShouldHappen = authService.refreshShouldHappen(res, req);\n\n if (refreshShouldHappen && !NgxRefreshInProgress()) {\n NgxRefreshInProgress.set(true);\n\n from(authService.refreshToken())\n .subscribe({\n error: () => {\n NgxRefreshInProgress.set(false);\n delay$.next(false);\n },\n next: () => {\n NgxRefreshInProgress.set(false);\n delay$.next(true);\n },\n });\n }\n\n if (refreshShouldHappen && NgxRefreshInProgress()) {\n return delay$.pipe(\n first(),\n switchMap(canRetry => canRetry\n ? http.request(req)\n : throwError(() => res || req),\n ),\n );\n }\n\n return throwError(() => res);\n}\n","import { inject, InjectionToken } from '@angular/core';\nimport { type ActivatedRouteSnapshot, type CanActivateFn, Router, type RouterStateSnapshot } from '@angular/router';\nimport { from, tap } from 'rxjs';\n\nimport { AUTH_SERVICE } from './auth.service';\n\nexport const PUBLIC_REDIRECT_URI = new InjectionToken<string>('ngx-auth--public-redirect-uri');\n\n/**\n * Guard, checks access token availability and allows or disallows access to page,\n * and redirects out\n */\nexport const ngxProtectedGuard: CanActivateFn = (_: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {\n const authService = inject(AUTH_SERVICE);\n const publicUri = inject(PUBLIC_REDIRECT_URI);\n const router = inject(Router);\n\n return from(authService.isAuthenticated()).pipe(\n tap(async isAllowed => {\n if (isAllowed) {\n return;\n }\n\n authService.setInterruptedUrl?.(state.url);\n await router.navigateByUrl(publicUri);\n }),\n );\n};\n","import { inject, InjectionToken } from '@angular/core';\nimport { type CanActivateFn, Router } from '@angular/router';\nimport { from, map, tap } from 'rxjs';\n\nimport { AUTH_SERVICE } from './auth.service';\n\nexport const PROTECTED_REDIRECT_URI = new InjectionToken<string>('ngx-auth--protected-redirect-uri');\n\n/**\n * Guard, checks access token availability and allows or disallows access to page,\n * and redirects out\n */\nexport const ngxPublicGuard: CanActivateFn = () => {\n const authService = inject(AUTH_SERVICE);\n const protectedUri = inject(PROTECTED_REDIRECT_URI);\n const router = inject(Router);\n\n return from(authService.isAuthenticated()).pipe(\n map(isAuthenticated => !isAuthenticated),\n tap(async isAllowed => {\n if (isAllowed) {\n return;\n }\n\n await router.navigateByUrl(protectedUri);\n }),\n );\n};\n","import { makeEnvironmentProviders, type Type } from '@angular/core';\n\nimport { AUTH_SERVICE, type NgxAuthService } from './auth.service';\nimport { PUBLIC_REDIRECT_URI } from './protected.guard';\nimport { PROTECTED_REDIRECT_URI } from './public.guard';\n\nexport function provideNgxAuthProviders(options: {\n authService: Type<NgxAuthService>;\n protectedRedirectUri: string;\n publicRedirectUri: string;\n}) {\n return makeEnvironmentProviders([\n {\n provide: AUTH_SERVICE,\n useExisting: options.authService,\n },\n {\n provide: PROTECTED_REDIRECT_URI,\n useValue: options.protectedRedirectUri,\n },\n {\n provide: PUBLIC_REDIRECT_URI,\n useValue: options.publicRedirectUri,\n },\n ]);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}