keycloak-angular
keycloak-angular copied to clipboard
keycloakBearerInterceptorFn example
I wrote BearerInterceptor as plain JavaScript function.
import { HttpEvent, HttpHandlerFn, HttpInterceptorFn, HttpRequest } from '@angular/common/http';
import { inject } from '@angular/core';
import { KeycloakService } from 'keycloak-angular';
import { ExcludedUrlRegex } from 'keycloak-angular/lib/core/interfaces/keycloak-options';
import { Observable, combineLatest, from, mergeMap, of } from 'rxjs';
const isUrlExcluded = ({ method, url }: HttpRequest<unknown>, { urlPattern, httpMethods }: ExcludedUrlRegex): boolean => {
const httpTest = (httpMethods?.length === 0 || httpMethods?.join().includes(method.toUpperCase())) ?? true;
const urlTest = urlPattern.test(url);
return httpTest && urlTest;
};
const conditionallyUpdateToken = async (req: HttpRequest<unknown>): Promise<boolean> => {
const keycloak = inject(KeycloakService);
if (keycloak.shouldUpdateToken(req)) {
return await keycloak.updateToken();
}
return true;
};
const handleRequestWithTokenHeader = (req: HttpRequest<unknown>, next: HttpHandlerFn): Observable<HttpEvent<unknown>> => {
const keycloak = inject(KeycloakService);
return keycloak.addTokenToHeader(req.headers).pipe(
mergeMap(headersWithBearer => {
const kcReq = req.clone({ headers: headersWithBearer });
return next(kcReq);
})
);
};
export const keycloakBearerInterceptorFn: HttpInterceptorFn = (req: HttpRequest<unknown>, next: HttpHandlerFn): Observable<HttpEvent<unknown>> => {
const keycloak = inject(KeycloakService);
const { enableBearerInterceptor, excludedUrls } = keycloak;
if (!enableBearerInterceptor) {
return next(req);
}
const shallPass: boolean = !keycloak.shouldAddToken(req) || excludedUrls.findIndex(item => isUrlExcluded(req, item)) > -1;
if (shallPass) {
return next(req);
}
return combineLatest([from(conditionallyUpdateToken(req)), of(keycloak.isLoggedIn())]).pipe(
mergeMap(([, isLoggedIn]) => (isLoggedIn ? handleRequestWithTokenHeader(req, next) : next(req)))
);
};
But I have a problem with "KeyCloakService injection".
How to use BearerInterceptor properly in Angular 17? (Ignoring the "withInterceptorsFromDi" option)
Here's a working example that lets you use KeycloakAngular without other hacks.
Just use this snippet in the providers section of your bootstrapApplication
:
importProvidersFrom(KeycloakAngularModule),
{
provide: KeycloakBearerInterceptor,
useClass: KeycloakBearerInterceptor,
},
provideHttpClient(
withInterceptors([
(req, next) => {
return inject(KeycloakBearerInterceptor)
.intercept(req, {handle: r => next(r)});
},
]),
),