UNPKG

keycloak-angular

Version:

Easy Keycloak integration for Angular applications.

1,189 lines (1,167 loc) 61.9 kB
import { HttpRequest, HttpHeaders, HttpInterceptor, HttpHandler, HttpEvent, HttpHandlerFn } from '@angular/common/http'; import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, CanActivateFn, CanActivateChildFn } from '@angular/router'; import * as rxjs from 'rxjs'; import { Subject, Observable } from 'rxjs'; import * as Keycloak$1 from 'keycloak-js'; import Keycloak__default, { KeycloakError, KeycloakConfig, KeycloakInitOptions } from 'keycloak-js'; import * as i0 from '@angular/core'; import { InjectionToken, OnDestroy, Signal, Provider, EnvironmentProviders } from '@angular/core'; import * as i1 from '@angular/common'; /** * @license * Copyright Mauricio Gemelli Vigolo and contributors. * * Use of this source code is governed by a MIT-style license that can be * found in the LICENSE file at https://github.com/mauriciovigolo/keycloak-angular/blob/main/LICENSE.md */ /** * Keycloak event types, as described at the keycloak-js documentation: * https://www.keycloak.org/docs/latest/securing_apps/index.html#callback-events * * @deprecated Keycloak Event based on the KeycloakService is deprecated and * will be removed in future versions. * Use the new `KEYCLOAK_EVENT_SIGNAL` injection token to listen for the keycloak * events. * More info: https://github.com/mauriciovigolo/keycloak-angular/blob/main/docs/migration-guides/v19.md */ declare enum KeycloakEventTypeLegacy { /** * Called if there was an error during authentication. */ OnAuthError = 0, /** * Called if the user is logged out * (will only be called if the session status iframe is enabled, or in Cordova mode). */ OnAuthLogout = 1, /** * Called if there was an error while trying to refresh the token. */ OnAuthRefreshError = 2, /** * Called when the token is refreshed. */ OnAuthRefreshSuccess = 3, /** * Called when a user is successfully authenticated. */ OnAuthSuccess = 4, /** * Called when the adapter is initialized. */ OnReady = 5, /** * Called when the access token is expired. If a refresh token is available the token * can be refreshed with updateToken, or in cases where it is not (that is, with implicit flow) * you can redirect to login screen to obtain a new access token. */ OnTokenExpired = 6, /** * Called when a AIA has been requested by the application. */ OnActionUpdate = 7 } /** * Structure of an event triggered by Keycloak, contains it's type * and arguments (if any). * * @deprecated Keycloak Event based on the KeycloakService is deprecated and * will be removed in future versions. * Use the new `KEYCLOAK_EVENT_SIGNAL` injection token to listen for the keycloak * events. * More info: https://github.com/mauriciovigolo/keycloak-angular/blob/main/docs/migration-guides/v19.md */ interface KeycloakEventLegacy { /** * Event type as described at {@link KeycloakEventTypeLegacy}. */ type: KeycloakEventTypeLegacy; /** * Arguments from the keycloak-js event function. */ args?: unknown; } /** * @license * Copyright Mauricio Gemelli Vigolo and contributors. * * Use of this source code is governed by a MIT-style license that can be * found in the LICENSE file at https://github.com/mauriciovigolo/keycloak-angular/blob/main/LICENSE.md */ /** * HTTP Methods * * @deprecated KeycloakBearerInterceptor is deprecated and will be removed in future versions. * Use the new functional interceptor `includeBearerTokenInterceptor`. * More info: https://github.com/mauriciovigolo/keycloak-angular/blob/main/docs/migration-guides/v19.md */ type HttpMethodsLegacy = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; /** * ExcludedUrl type may be used to specify the url and the HTTP method that * should not be intercepted by the KeycloakBearerInterceptor. * * Example: * const excludedUrl: ExcludedUrl[] = [ * { * url: 'reports/public' * httpMethods: ['GET'] * } * ] * * In the example above for URL reports/public and HTTP Method GET the * bearer will not be automatically added. * * If the url is informed but httpMethod is undefined, then the bearer * will not be added for all HTTP Methods. * * @deprecated KeycloakBearerInterceptor is deprecated and will be removed in future versions. * Use the new functional interceptor `includeBearerTokenInterceptor`. * More info: https://github.com/mauriciovigolo/keycloak-angular/blob/main/docs/migration-guides/v19.md */ interface ExcludedUrl { url: string; httpMethods?: HttpMethodsLegacy[]; } /** * Similar to ExcludedUrl, contains the HTTP methods and a regex to * include the url patterns. * This interface is used internally by the KeycloakService. * * @deprecated KeycloakBearerInterceptor is deprecated and will be removed in future versions. * Use the new functional interceptor `includeBearerTokenInterceptor`. * More info: https://github.com/mauriciovigolo/keycloak-angular/blob/main/docs/migration-guides/v19.md */ interface ExcludedUrlRegex { urlPattern: RegExp; httpMethods?: HttpMethodsLegacy[]; } /** * keycloak-angular initialization options. * * @deprecated KeycloakService is deprecated and will be removed in future versions. * Use the new `provideKeycloak` method to load Keycloak in an Angular application. * More info: https://github.com/mauriciovigolo/keycloak-angular/blob/main/docs/migration-guides/v19.md */ interface KeycloakOptions { /** * Configs to init the keycloak-js library. If undefined, will look for a keycloak.json file * at root of the project. * If not undefined, can be a string meaning the url to the keycloak.json file or an object * of {@link Keycloak.KeycloakConfig}. Use this configuration if you want to specify the keycloak server, * realm, clientId. This is usefull if you have different configurations for production, stage * and development environments. Hint: Make use of Angular environment configuration. */ config?: string | Keycloak.KeycloakConfig; /** * Options to initialize the Keycloak adapter, matches the options as provided by Keycloak itself. */ initOptions?: Keycloak.KeycloakInitOptions; /** * By default all requests made by Angular HttpClient will be intercepted in order to * add the bearer in the Authorization Http Header. However, if this is a not desired * feature, the enableBearerInterceptor must be false. * * Briefly, if enableBearerInterceptor === false, the bearer will not be added * to the authorization header. * * The default value is true. */ enableBearerInterceptor?: boolean; /** * Forces the execution of loadUserProfile after the keycloak initialization considering that the * user logged in. * This option is recommended if is desirable to have the user details at the beginning, * so after the login, the loadUserProfile function will be called and its value cached. * * The default value is true. */ loadUserProfileAtStartUp?: boolean; /** * @deprecated * String Array to exclude the urls that should not have the Authorization Header automatically * added. This library makes use of Angular Http Interceptor, to automatically add the Bearer * token to the request. */ bearerExcludedUrls?: (string | ExcludedUrl)[]; /** * This value will be used as the Authorization Http Header name. The default value is * **Authorization**. If the backend expects requests to have a token in a different header, you * should change this value, i.e: **JWT-Authorization**. This will result in a Http Header * Authorization as "JWT-Authorization: bearer <token>". */ authorizationHeaderName?: string; /** * This value will be included in the Authorization Http Header param. The default value is * **Bearer**, which will result in a Http Header Authorization as "Authorization: Bearer <token>". * * If any other value is needed by the backend in the authorization header, you should change this * value. * * Warning: this value must be in compliance with the keycloak server instance and the adapter. */ bearerPrefix?: string; /** * This value will be used to determine whether or not the token needs to be updated. If the token * will expire is fewer seconds than the updateMinValidity value, then it will be updated. * * The default value is 20. */ updateMinValidity?: number; /** * A function that will tell the KeycloakBearerInterceptor whether to add the token to the request * or to leave the request as it is. If the returned value is `true`, the request will have the token * present on it. If it is `false`, the token will be left off the request. * * The default is a function that always returns `true`. */ shouldAddToken?: (request: HttpRequest<unknown>) => boolean; /** * A function that will tell the KeycloakBearerInterceptor if the token should be considered for * updating as a part of the request being made. If the returned value is `true`, the request will * check the token's expiry time and if it is less than the number of seconds configured by * updateMinValidity then it will be updated before the request is made. If the returned value is * false, the token will not be updated. * * The default is a function that always returns `true`. */ shouldUpdateToken?: (request: HttpRequest<unknown>) => boolean; } /** * Service to expose existent methods from the Keycloak JS adapter, adding new * functionalities to improve the use of keycloak in Angular v > 4.3 applications. * * This class should be injected in the application bootstrap, so the same instance will be used * along the web application. * * @deprecated This service is deprecated and will be removed in future versions. * Use the new `provideKeycloak` function to load Keycloak in an Angular application. * More info: https://github.com/mauriciovigolo/keycloak-angular/blob/main/docs/migration-guides/v19.md */ declare class KeycloakService { /** * Keycloak-js instance. */ private _instance; /** * User profile as KeycloakProfile interface. */ private _userProfile; /** * Flag to indicate if the bearer will not be added to the authorization header. */ private _enableBearerInterceptor; /** * When the implicit flow is choosen there must exist a silentRefresh, as there is * no refresh token. */ private _silentRefresh; /** * Indicates that the user profile should be loaded at the keycloak initialization, * just after the login. */ private _loadUserProfileAtStartUp; /** * The bearer prefix that will be appended to the Authorization Header. */ private _bearerPrefix; /** * Value that will be used as the Authorization Http Header name. */ private _authorizationHeaderName; /** * @deprecated * The excluded urls patterns that must skip the KeycloakBearerInterceptor. */ private _excludedUrls; /** * Observer for the keycloak events */ private _keycloakEvents$; /** * The amount of required time remaining before expiry of the token before the token will be refreshed. */ private _updateMinValidity; /** * Returns true if the request should have the token added to the headers by the KeycloakBearerInterceptor. */ shouldAddToken: (request: HttpRequest<unknown>) => boolean; /** * Returns true if the request being made should potentially update the token. */ shouldUpdateToken: (request: HttpRequest<unknown>) => boolean; /** * Binds the keycloak-js events to the keycloakEvents Subject * which is a good way to monitor for changes, if needed. * * The keycloakEvents returns the keycloak-js event type and any * argument if the source function provides any. */ private bindsKeycloakEvents; /** * Loads all bearerExcludedUrl content in a uniform type: ExcludedUrl, * so it becomes easier to handle. * * @param bearerExcludedUrls array of strings or ExcludedUrl that includes * the url and HttpMethod. */ private loadExcludedUrls; /** * Handles the class values initialization. * * @param options */ private initServiceValues; /** * Keycloak initialization. It should be called to initialize the adapter. * Options is an object with 2 main parameters: config and initOptions. The first one * will be used to create the Keycloak instance. The second one are options to initialize the * keycloak instance. * * @param options * Config: may be a string representing the keycloak URI or an object with the * following content: * - url: Keycloak json URL * - realm: realm name * - clientId: client id * * initOptions: * Options to initialize the Keycloak adapter, matches the options as provided by Keycloak itself. * * enableBearerInterceptor: * Flag to indicate if the bearer will added to the authorization header. * * loadUserProfileInStartUp: * Indicates that the user profile should be loaded at the keycloak initialization, * just after the login. * * bearerExcludedUrls: * String Array to exclude the urls that should not have the Authorization Header automatically * added. * * authorizationHeaderName: * This value will be used as the Authorization Http Header name. * * bearerPrefix: * This value will be included in the Authorization Http Header param. * * tokenUpdateExcludedHeaders: * Array of Http Header key/value maps that should not trigger the token to be updated. * * updateMinValidity: * This value determines if the token will be refreshed based on its expiration time. * * @returns * A Promise with a boolean indicating if the initialization was successful. */ init(options?: KeycloakOptions): Promise<boolean>; /** * Redirects to login form on (options is an optional object with redirectUri and/or * prompt fields). * * @param options * Object, where: * - redirectUri: Specifies the uri to redirect to after login. * - prompt:By default the login screen is displayed if the user is not logged-in to Keycloak. * To only authenticate to the application if the user is already logged-in and not display the * login page if the user is not logged-in, set this option to none. To always require * re-authentication and ignore SSO, set this option to login . * - maxAge: Used just if user is already authenticated. Specifies maximum time since the * authentication of user happened. If user is already authenticated for longer time than * maxAge, the SSO is ignored and he will need to re-authenticate again. * - loginHint: Used to pre-fill the username/email field on the login form. * - action: If value is 'register' then user is redirected to registration page, otherwise to * login page. * - locale: Specifies the desired locale for the UI. * @returns * A void Promise if the login is successful and after the user profile loading. */ login(options?: Keycloak.KeycloakLoginOptions): Promise<void>; /** * Redirects to logout. * * @param redirectUri * Specifies the uri to redirect to after logout. * @returns * A void Promise if the logout was successful, cleaning also the userProfile. */ logout(redirectUri?: string): Promise<void>; /** * Redirects to registration form. Shortcut for login with option * action = 'register'. Options are same as for the login method but 'action' is set to * 'register'. * * @param options * login options * @returns * A void Promise if the register flow was successful. */ register(options?: Keycloak.KeycloakLoginOptions): Promise<void>; /** * Check if the user has access to the specified role. It will look for roles in * realm and the given resource, but will not check if the user is logged in for better performance. * * @param role * role name * @param resource * resource name. If not specified, `clientId` is used * @returns * A boolean meaning if the user has the specified Role. */ isUserInRole(role: string, resource?: string): boolean; /** * Return the roles of the logged user. The realmRoles parameter, with default value * true, will return the resource roles and realm roles associated with the logged user. If set to false * it will only return the resource roles. The resource parameter, if specified, will return only resource roles * associated with the given resource. * * @param realmRoles * Set to false to exclude realm roles (only client roles) * @param resource * resource name If not specified, returns roles from all resources * @returns * Array of Roles associated with the logged user. */ getUserRoles(realmRoles?: boolean, resource?: string): string[]; /** * Check if user is logged in. * * @returns * A boolean that indicates if the user is logged in. */ isLoggedIn(): boolean; /** * Returns true if the token has less than minValidity seconds left before * it expires. * * @param minValidity * Seconds left. (minValidity) is optional. Default value is 0. * @returns * Boolean indicating if the token is expired. */ isTokenExpired(minValidity?: number): boolean; /** * If the token expires within _updateMinValidity seconds the token is refreshed. If the * session status iframe is enabled, the session status is also checked. * Returns a promise telling if the token was refreshed or not. If the session is not active * anymore, the promise is rejected. * * @param minValidity * Seconds left. (minValidity is optional, if not specified updateMinValidity - default 20 is used) * @returns * Promise with a boolean indicating if the token was succesfully updated. */ updateToken(minValidity?: number): Promise<boolean>; /** * Loads the user profile. * Returns promise to set functions to be invoked if the profile was loaded * successfully, or if the profile could not be loaded. * * @param forceReload * If true will force the loadUserProfile even if its already loaded. * @returns * A promise with the KeycloakProfile data loaded. */ loadUserProfile(forceReload?: boolean): Promise<Keycloak$1.KeycloakProfile>; /** * Returns the authenticated token. */ getToken(): Promise<string>; /** * Returns the logged username. * * @returns * The logged username. */ getUsername(): string; /** * Clear authentication state, including tokens. This can be useful if application * has detected the session was expired, for example if updating token fails. * Invoking this results in onAuthLogout callback listener being invoked. */ clearToken(): void; /** * Adds a valid token in header. The key & value format is: * Authorization Bearer <token>. * If the headers param is undefined it will create the Angular headers object. * * @param headers * Updated header with Authorization and Keycloak token. * @returns * An observable with with the HTTP Authorization header and the current token. */ addTokenToHeader(headers?: HttpHeaders): rxjs.Observable<HttpHeaders>; /** * Returns the original Keycloak instance, if you need any customization that * this Angular service does not support yet. Use with caution. * * @returns * The KeycloakInstance from keycloak-js. */ getKeycloakInstance(): Keycloak.KeycloakInstance; /** * @deprecated * Returns the excluded URLs that should not be considered by * the http interceptor which automatically adds the authorization header in the Http Request. * * @returns * The excluded urls that must not be intercepted by the KeycloakBearerInterceptor. */ get excludedUrls(): ExcludedUrlRegex[]; /** * Flag to indicate if the bearer will be added to the authorization header. * * @returns * Returns if the bearer interceptor was set to be disabled. */ get enableBearerInterceptor(): boolean; /** * Keycloak subject to monitor the events triggered by keycloak-js. * The following events as available (as described at keycloak docs - * https://www.keycloak.org/docs/latest/securing_apps/index.html#callback-events): * - OnAuthError * - OnAuthLogout * - OnAuthRefreshError * - OnAuthRefreshSuccess * - OnAuthSuccess * - OnReady * - OnTokenExpire * In each occurrence of any of these, this subject will return the event type, * described at {@link KeycloakEventTypeLegacy} enum and the function args from the keycloak-js * if provided any. * * @returns * A subject with the {@link KeycloakEventLegacy} which describes the event type and attaches the * function args. */ get keycloakEvents$(): Subject<KeycloakEventLegacy>; static ɵfac: i0.ɵɵFactoryDeclaration<KeycloakService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<KeycloakService>; } /** * @license * Copyright Mauricio Gemelli Vigolo and contributors. * * Use of this source code is governed by a MIT-style license that can be * found in the LICENSE file at https://github.com/mauriciovigolo/keycloak-angular/blob/main/LICENSE.md */ /** * A simple guard implementation out of the box. This class should be inherited and * implemented by the application. The only method that should be implemented is #isAccessAllowed. * The reason for this is that the authorization flow is usually not unique, so in this way you will * have more freedom to customize your authorization flow. * * @deprecated Class based guards are deprecated in Keycloak Angular and will be removed in future versions. * Use the new `createAuthGuard` function to create a Guard for your application. * More info: https://github.com/mauriciovigolo/keycloak-angular/blob/main/docs/migration-guides/v19.md */ declare abstract class KeycloakAuthGuard implements CanActivate { protected router: Router; protected keycloakAngular: KeycloakService; /** * Indicates if the user is authenticated or not. */ protected authenticated: boolean; /** * Roles of the logged user. It contains the clientId and realm user roles. */ protected roles: string[]; constructor(router: Router, keycloakAngular: KeycloakService); /** * CanActivate checks if the user is logged in and get the full list of roles (REALM + CLIENT) * of the logged user. This values are set to authenticated and roles params. * * @param route * @param state */ canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean | UrlTree>; /** * Create your own customized authorization flow in this method. From here you already known * if the user is authenticated (this.authenticated) and the user roles (this.roles). * * Return a UrlTree if the user should be redirected to another route. * * @param route * @param state */ abstract isAccessAllowed(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean | UrlTree>; } /** * This interceptor includes the bearer by default in all HttpClient requests. * * If you need to exclude some URLs from adding the bearer, please, take a look * at the {@link KeycloakOptions} bearerExcludedUrls property. * * @deprecated KeycloakBearerInterceptor is deprecated and will be removed in future versions. * Use the new functional interceptor such as `includeBearerTokenInterceptor`. * More info: https://github.com/mauriciovigolo/keycloak-angular/blob/main/docs/migration-guides/v19.md */ declare class KeycloakBearerInterceptor implements HttpInterceptor { private keycloak; /** * Calls to update the keycloak token if the request should update the token. * * @param req http request from @angular http module. * @returns * A promise boolean for the token update or noop result. */ private conditionallyUpdateToken; /** * @deprecated * Checks if the url is excluded from having the Bearer Authorization * header added. * * @param req http request from @angular http module. * @param excludedUrlRegex contains the url pattern and the http methods, * excluded from adding the bearer at the Http Request. */ private isUrlExcluded; /** * Intercept implementation that checks if the request url matches the excludedUrls. * If not, adds the Authorization header to the request if the user is logged in. * * @param req * @param next */ intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>>; /** * Adds the token of the current user to the Authorization header * * @param req * @param next */ private handleRequestWithTokenHeader; static ɵfac: i0.ɵɵFactoryDeclaration<KeycloakBearerInterceptor, never>; static ɵprov: i0.ɵɵInjectableDeclaration<KeycloakBearerInterceptor>; } /** * @deprecated NgModules are deprecated in Keycloak Angular and will be removed in future versions. * Use the new `provideKeycloak` function to load Keycloak in an Angular application. * More info: https://github.com/mauriciovigolo/keycloak-angular/blob/main/docs/migration-guides/v19.md */ declare class CoreModule { static ɵfac: i0.ɵɵFactoryDeclaration<CoreModule, never>; static ɵmod: i0.ɵɵNgModuleDeclaration<CoreModule, never, [typeof i1.CommonModule], never>; static ɵinj: i0.ɵɵInjectorDeclaration<CoreModule>; } /** * @deprecated NgModules are deprecated in Keycloak Angular and will be removed in future versions. * Use the new `provideKeycloak` function to load Keycloak in an Angular application. * More info: https://github.com/mauriciovigolo/keycloak-angular/blob/main/docs/migration-guides/v19.md */ declare class KeycloakAngularModule { static ɵfac: i0.ɵɵFactoryDeclaration<KeycloakAngularModule, never>; static ɵmod: i0.ɵɵNgModuleDeclaration<KeycloakAngularModule, never, [typeof CoreModule], never>; static ɵinj: i0.ɵɵInjectorDeclaration<KeycloakAngularModule>; } /** * Structural directive to conditionally display elements based on Keycloak user roles. * * This directive checks if the authenticated user has at least one of the specified roles. * Roles can be validated against a specific **resource (client ID)** or the **realm**. * * ### Features: * - Supports role checking in both **resources (client-level roles)** and the **realm**. * - Accepts an array of roles to match. * - Optional configuration to check realm-level roles. * * ### Inputs: * - `kaHasRoles` (Required): Array of roles to validate. * - `resource` (Optional): The client ID or resource name to validate resource-level roles. * - `checkRealm` (Optional): A boolean flag to enable realm role validation (default is `false`). * * ### Requirements: * - A Keycloak instance must be injected via Angular's dependency injection. * - The user must be authenticated in Keycloak. * * @example * #### Example 1: Check for Global Realm Roles * Show the content only if the user has the `admin` or `editor` role in the realm. * ```html * <div *kaHasRoles="['admin', 'editor']; checkRealm:true"> * <p>This content is visible only to users with 'admin' or 'editor' realm roles.</p> * </div> * ``` * * @example * #### Example 2: Check for Resource Roles * Show the content only if the user has the `read` or `write` role for a specific resource (`my-client`). * ```html * <div *kaHasRoles="['read', 'write']; resource:'my-client'"> * <p>This content is visible only to users with 'read' or 'write' roles for 'my-client'.</p> * </div> * ``` * * @example * #### Example 3: Check for Both Resource and Realm Roles * Show the content if the user has the roles in either the realm or a resource. * ```html * <div *kaHasRoles="['admin', 'write']; resource:'my-client' checkRealm:true"> * <p>This content is visible to users with 'admin' in the realm or 'write' in 'my-client'.</p> * </div> * ``` * * @example * #### Example 4: Fallback Content When Roles Do Not Match * Use an `<ng-template>` to display fallback content if the user lacks the required roles. * ```html * <div *kaHasRoles="['admin']; resource:'my-client'"> * <p>Welcome, Admin!</p> * </div> * <ng-template #noAccess> * <p>Access Denied</p> * </ng-template> * ``` */ declare class HasRolesDirective { private templateRef; private viewContainer; private keycloak; /** * List of roles to validate against the resource or realm. */ roles: string[]; /** * The resource (client ID) to validate roles against. */ resource?: string; /** * Flag to enable realm-level role validation. */ checkRealm: boolean; constructor(); private render; /** * Checks if the user has at least one of the specified roles in the resource or realm. * @returns True if the user has access, false otherwise. */ private checkUserRoles; static ɵfac: i0.ɵɵFactoryDeclaration<HasRolesDirective, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<HasRolesDirective, "[kaHasRoles]", never, { "roles": { "alias": "kaHasRoles"; "required": false; }; "resource": { "alias": "kaHasRolesResource"; "required": false; }; "checkRealm": { "alias": "kaHasRolesCheckRealm"; "required": false; }; }, {}, never, never, true, never>; } /** * @license * Copyright Mauricio Gemelli Vigolo All Rights Reserved. * * Use of this source code is governed by a MIT-style license that can be * found in the LICENSE file at https://github.com/mauriciovigolo/keycloak-angular/blob/main/LICENSE.md */ /** * Represents a feature from keycloak-angular that can be configured during the library initialization. * * This type defines the structure of a feature that includes a `configure` method, * which is responsible for setting up or initializing the feature's behavior or properties * related to Keycloak. * * ### Usage: * The `KeycloakFeature` type is typically used for defining modular, reusable Keycloak * features that can be dynamically configured and integrated into an application. * * @property {() => void} configure - A method that initializes or configures the feature. * This method is invoked to perform any setup or customization required for the feature. * * ### Example: * ```typescript * const withLoggingFeature: KeycloakFeature = { * configure: () => { * console.log('Configuring Keycloak logging feature'); * }, * }; * * const withAnalyticsFeature: KeycloakFeature = { * configure: () => { * console.log('Configuring Keycloak analytics feature'); * }, * }; * * // Configure and initialize features * withLoggingFeature.configure(); * withAnalyticsFeature.configure(); * ``` */ type KeycloakFeature = { configure: () => void; }; /** * @license * Copyright Mauricio Gemelli Vigolo All Rights Reserved. * * Use of this source code is governed by a MIT-style license that can be * found in the LICENSE file at https://github.com/mauriciovigolo/keycloak-angular/blob/main/LICENSE.md */ /** * Options for configuring the auto-refresh token feature. * * This type defines the configuration parameters for enabling auto-refresh * of Keycloak tokens and handling session inactivity scenarios. */ type WithRefreshTokenOptions = { /** * The session timeout duration in milliseconds. This specifies the time * of inactivity after which the session is considered expired. * * Default value: `300000` milliseconds (5 minutes). */ sessionTimeout?: number; /** * Action to take when the session timeout due to inactivity occurs. * * - `'login'`: Execute the `keycloak.login` method. * - `'logout'`: Logs the user out by calling the `keycloak.logout` method. * - `'none'`: Takes no action on session timeout. * * Default value: `'logout'`. */ onInactivityTimeout?: 'login' | 'logout' | 'none'; }; /** * Enables automatic token refresh and session inactivity handling for a * Keycloak-enabled Angular application. * * This function initializes a service that tracks user interactions, such as * mouse movements, touches, key presses, clicks, and scrolls. If user activity * is detected, it periodically calls `Keycloak.updateToken` to ensure the bearer * token remains valid and does not expire. * * If the session remains inactive beyond the defined `sessionTimeout`, the * specified action (`logout`, `login`, or `none`) will be executed. By default, * the service will call `keycloak.logout` upon inactivity timeout. * * Event tracking uses RxJS observables with a debounce of 300 milliseconds to * monitor user interactions. When the Keycloak `OnTokenExpired` event occurs, * the service checks the user's last activity timestamp. If the user has been * active within the session timeout period, it refreshes the token using `updateToken`. * * * @param options - Configuration options for the auto-refresh token feature. * - `sessionTimeout` (optional): The duration in milliseconds after which * the session is considered inactive. Defaults to `300000` (5 minutes). * - `onInactivityTimeout` (optional): The action to take when session inactivity * exceeds the specified timeout. Defaults to `'logout'`. * - `'login'`: Execute `keycloak.login` function. * - `'logout'`: Logs the user out by calling `keycloak.logout`. * - `'none'`: No action is taken. * * @returns A `KeycloakFeature` instance that configures and enables the * auto-refresh token functionality. */ declare function withAutoRefreshToken(options?: WithRefreshTokenOptions): KeycloakFeature; /** * @license * Copyright Mauricio Gemelli Vigolo All Rights Reserved. * * Use of this source code is governed by a MIT-style license that can be * found in the LICENSE file at https://github.com/mauriciovigolo/keycloak-angular/blob/main/LICENSE.md */ /** * Type representing the roles granted to a user, including both realm and resource-level roles. */ type Roles = { /** * Roles assigned at the realm level. */ realmRoles: string[]; /** * Roles assigned at the resource level, organized by resource name. */ resourceRoles: { [resource: string]: string[]; }; }; /** * Data structure passed to the custom authorization guard to determine access. */ type AuthGuardData = { /** * Indicates whether the user is currently authenticated. */ authenticated: boolean; /** * A collection of roles granted to the user, including both realm and resource roles. */ grantedRoles: Roles; /** * The Keycloak instance managing the user's session and access. */ keycloak: Keycloak__default; }; /** * Creates a custom authorization guard for Angular routes, enabling fine-grained access control. * * This guard invokes the provided `isAccessAllowed` function to determine if access is permitted * based on the current route, router state, and user's authentication and roles data. * * @template T - The type of the guard function (`CanActivateFn` or `CanActivateChildFn`). * @param isAccessAllowed - A callback function that evaluates access conditions. The function receives: * - `route`: The current `ActivatedRouteSnapshot` for the route being accessed. * - `state`: The current `RouterStateSnapshot` representing the router's state. * - `authData`: An `AuthGuardData` object containing the user's authentication status, roles, and Keycloak instance. * @returns A guard function of type `T` that can be used as a route `canActivate` or `canActivateChild` guard. * * @example * ```ts * import { createAuthGuard } from './auth-guard'; * import { Routes } from '@angular/router'; * * const isUserAllowed = async (route, state, authData) => { * const { authenticated, grantedRoles } = authData; * return authenticated && grantedRoles.realmRoles.includes('admin'); * }; * * const routes: Routes = [ * { * path: 'admin', * canActivate: [createAuthGuard(isUserAllowed)], * component: AdminComponent, * }, * ]; * ``` */ declare const createAuthGuard: <T extends CanActivateFn | CanActivateChildFn>(isAccessAllowed: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot, authData: AuthGuardData) => Promise<boolean | UrlTree>) => T; /** * @license * Copyright Mauricio Gemelli Vigolo All Rights Reserved. * * Use of this source code is governed by a MIT-style license that can be * found in the LICENSE file at https://github.com/mauriciovigolo/keycloak-angular/blob/main/LICENSE.md */ /** * Represents the HTTP methods supported by the interceptor for authorization purposes. */ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; /** * Common attributes for the Auth Bearer interceptor that can be reused in other interceptor implementations. */ type BearerTokenCondition = { /** * Prefix to be used in the Authorization header. Default is "Bearer". * This will result in a header formatted as: `Authorization: Bearer <token>`. * * Adjust this value if your backend expects a different prefix in the Authorization header. */ bearerPrefix?: string; /** * Name of the HTTP header used for authorization. Default is "Authorization". * Customize this value if your backend expects a different header, e.g., "JWT-Authorization". */ authorizationHeaderName?: string; /** * Function to determine whether the token should be updated before a request. Default is a function returning true. * If the function returns `true`, the token's validity will be checked and updated if needed. * If it returns `false`, the token update process will be skipped for that request. * * @param request - The current `HttpRequest` object being intercepted. * @returns A boolean indicating whether to update the token. */ shouldUpdateToken?: (request: HttpRequest<unknown>) => boolean; }; /** * Generic factory function to create an interceptor condition with default values. * * This utility allows you to define custom interceptor conditions while ensuring that * default values are applied to any missing fields. By using generics, you can enforce * strong typing when creating the fields for the interceptor condition, enhancing type safety. * * @template T - A type that extends `AuthBearerCondition`. * @param value - An object of type `T` (extending `AuthBearerCondition`) to be enhanced with default values. * @returns A new object of type `T` with default values assigned to any undefined properties. */ declare const createInterceptorCondition: <T extends BearerTokenCondition>(value: T) => T; /** * Conditionally updates the Keycloak token based on the provided request and conditions. * * @param req - The `HttpRequest` object being processed. * @param keycloak - The Keycloak instance managing authentication. * @param condition - An `AuthBearerCondition` object with the `shouldUpdateToken` function. * @returns A `Promise<boolean>` indicating whether the token was successfully updated. */ declare const conditionallyUpdateToken: (req: HttpRequest<unknown>, keycloak: Keycloak__default, { shouldUpdateToken }: BearerTokenCondition) => Promise<boolean>; /** * Adds the Authorization header to an HTTP request and forwards it to the next handler. * * @param req - The original `HttpRequest` object. * @param next - The `HttpHandlerFn` function for forwarding the HTTP request. * @param keycloak - The Keycloak instance providing the authentication token. * @param condition - An `AuthBearerCondition` object specifying header configuration. * @returns An `Observable<HttpEvent<unknown>>` representing the HTTP response. */ declare const addAuthorizationHeader: (req: HttpRequest<unknown>, next: HttpHandlerFn, keycloak: Keycloak__default, condition: BearerTokenCondition) => Observable<HttpEvent<unknown>>; /** * @license * Copyright Mauricio Gemelli Vigolo All Rights Reserved. * * Use of this source code is governed by a MIT-style license that can be * found in the LICENSE file at https://github.com/mauriciovigolo/keycloak-angular/blob/main/LICENSE.md */ /** * Defines a custom condition for determining whether a Bearer token should be included * in the `Authorization` header of an outgoing HTTP request. * * This type extends the `BearerTokenCondition` type and adds a dynamic function * (`shouldAddToken`) that evaluates whether the token should be added based on the * request, handler, and Keycloak state. */ type CustomBearerTokenCondition = Partial<BearerTokenCondition> & { /** * A function that dynamically determines whether the Bearer token should be included * in the `Authorization` header for a given request. * * This function is asynchronous and receives the following arguments: * - `req`: The `HttpRequest` object representing the current outgoing HTTP request. * - `next`: The `HttpHandlerFn` for forwarding the request to the next handler in the chain. * - `keycloak`: The `Keycloak` instance representing the authentication context. */ shouldAddToken: (req: HttpRequest<unknown>, next: HttpHandlerFn, keycloak: Keycloak__default) => Promise<boolean>; }; /** * Injection token for configuring the `customBearerTokenInterceptor`. * * This injection token holds an array of `CustomBearerTokenCondition` objects, which define * the conditions under which a Bearer token should be included in the `Authorization` header * of outgoing HTTP requests. Each condition provides a `shouldAddToken` function that dynamically * determines whether the token should be added based on the request, handler, and Keycloak state. */ declare const CUSTOM_BEARER_TOKEN_INTERCEPTOR_CONFIG: InjectionToken<CustomBearerTokenCondition[]>; /** * Custom HTTP Interceptor for dynamically adding a Bearer token to requests based on conditions. * * This interceptor uses a flexible approach where the decision to include a Bearer token in the * `Authorization` HTTP header is determined by a user-provided function (`shouldAddToken`). * This enables a dynamic and granular control over when tokens are added to HTTP requests. * * ### Key Features: * 1. **Dynamic Token Inclusion**: Uses a condition function (`shouldAddToken`) to decide dynamically * whether to add the token based on the request, Keycloak state, and other factors. * 2. **Token Management**: Optionally refreshes the Keycloak token before adding it to the request. * 3. **Controlled Authorization**: Adds the Bearer token only when the condition function allows * and the user is authenticated in Keycloak. * * ### Configuration: * The interceptor relies on `CUSTOM_BEARER_TOKEN_INTERCEPTOR_CONFIG`, an injection token that contains * an array of `CustomBearerTokenCondition` objects. Each condition specifies a `shouldAddToken` function * that determines whether to add the Bearer token for a given request. * * ### Workflow: * 1. Reads the conditions from the `CUSTOM_BEARER_TOKEN_INTERCEPTOR_CONFIG` injection token. * 2. Iterates through the conditions and evaluates the `shouldAddToken` function for the request. * 3. If a condition matches: * - Optionally refreshes the Keycloak token if needed. * - Adds the Bearer token to the request's `Authorization` header if the user is authenticated. * 4. If no conditions match, the request proceeds unchanged. * * ### Parameters: * @param req - The `HttpRequest` object representing the outgoing HTTP request. * @param next - The `HttpHandlerFn` for passing the request to the next handler in the chain. * * @returns An `Observable<HttpEvent<unknown>>` representing the HTTP response. * * ### Usage Example: * ```typescript * // Define a custom condition to include the token * const customCondition: CustomBearerTokenCondition = { * shouldAddToken: async (req, next, keycloak) => { * // Add token only for requests to the /api endpoint * return req.url.startsWith('/api') && keycloak.authenticated; * }, * }; * * // Configure the interceptor with the custom condition * export const appConfig: ApplicationConfig = { * providers: [ * provideHttpClient(withInterceptors([customBearerTokenInterceptor])), * { * provide: CUSTOM_BEARER_TOKEN_INTERCEPTOR_CONFIG, * useValue: [customCondition], * }, * ], * }; * ``` */ declare const customBearerTokenInterceptor: (req: HttpRequest<unknown>, next: HttpHandlerFn) => Observable<HttpEvent<unknown>>; /** * @license * Copyright Mauricio Gemelli Vigolo All Rights Reserved. * * Use of this source code is governed by a MIT-style license that can be * found in the LICENSE file at https://github.com/mauriciovigolo/keycloak-angular/blob/main/LICENSE.md */ /** * Defines the conditions for including the Bearer token in the Authorization HTTP header. */ type IncludeBearerTokenCondition = Partial<BearerTokenCondition> & { /** * A URL pattern (as a `RegExp`) used to determine whether the Bearer token should be added * to the Authorization HTTP header for a given request. The Bearer token is only added if * this pattern matches the request's URL. * * This EXPLICIT configuration is for security purposes, ensuring that internal tokens are not * shared with unintended services. */ urlPattern: RegExp; /** * An optional array of HTTP methods (`HttpMethod[]`) to further refine the conditions under * which the Bearer token is added. If not provided, the default behavior is to add the token * for all HTTP methods matching the `urlPattern`. */ httpMethods?: HttpMethod[]; }; /** * Injection token for configuring the `includeBearerTokenInterceptor`, allowing the specification * of conditions under which the Bearer token should be included in HTTP request headers. * * This configuration supports multiple conditions, enabling customization for different URLs. * It also provides options to tailor the Bearer prefix and the Authorization header name as needed. */ declare const INCLUDE_BEARER_TOKEN_INTERCEPTOR_CONFIG: InjectionToken<IncludeBearerTokenCondition[]>; /** * HTTP Interceptor to include a Bearer token in the Authorization header for specific HTTP requests. * * This interceptor ensures that a Bearer token is added to outgoing HTTP requests based on explicitly * defined conditions. By default, the interceptor does not include the Bearer token unless the request * matches the provided configuration (`IncludeBearerTokenCondition`). This approach enhances security * by preventing sensitive tokens from being unintentionally sent to unauthorized services. * * ### Features: * 1. **Explicit URL Matching**: The interceptor uses regular expressions to match URLs where the Bearer token should be included. * 2. **HTTP Method Filtering**: Optional filtering by HTTP methods (e.g., `GET`, `POST`, `PUT`) to refine the conditions for adding the token. * 3. **Token Management**: Ensures the Keycloak token is valid by optionally refreshing it before attaching it to the request. * 4. **Controlled Authorization**: Sends the token only for requests where the user is authenticated, and the conditions match. * * ### Workflow: * - Reads conditions from `INCLUDE_BEARER_TOKEN_INTERCEPTOR_CONFIG`, which specifies when the Bearer token should be included. * - If a request matches the conditions: * 1. The Keycloak token is refreshed if needed. * 2. The Bearer token is added to the Authorization header. * 3. The modified request is passed to the next handler. * - If no conditions match, the request proceeds unchanged. * * ### Security: * By explicitly defining URL patterns and optional HTTP methods, this interceptor prevents the leakage of tokens * to unintended endpoints, such as third-party APIs or external services. This is especially critical for applications * that interact with both internal and external services. * * @param req - The `HttpRequest` object representing the outgoing HTTP request. * @param next - The `HttpHandlerFn` for passing the request to the next handler in the chain. * @returns An `Observable<HttpEvent<unknown>>` representing the asynchronous HTTP response. * * ### Configuration: * The interceptor relies on `INCLUDE_BEARER_TOKEN_INTERCEPTOR_CONFIG`, an injection token that holds * an array of `IncludeBearerTokenCondition` objects. Each object defines the conditions for including * the Bearer token in the request. * * #### Example Configuration: * ```typescript * provideHttpClient( * withInterceptors([includeBearerTokenInterceptor]), * { * provide: INCLUDE_BEARER_TOKEN_INTERCEPTOR_CONFIG, * useValue: [ * { * urlPattern: /^https:\/\/api\.internal\.myapp\.com\/.*\/, * httpMethods: ['GET', 'POST'], // Add the token only for GET and POST methods * }, * ], * } * ); * ``` * * ### Example Usage: