keycloak-angular with angulareelements和Standalone Component(



我有一个angular应用程序(和一个nestjs后端),我试图处理用户登录与keycloak的帮助。正如这个充满流行语的问题标题所述,我有点"奇怪"。架构。

  • 我想在angular (works)
  • 的帮助下创建一个custom element
  • 我认为我不需要自己的模块为我构建的组件,所以它是一个standalone component(工程)
  • 我使用keycloak-angular在主。(工作,我得到一个令牌,用户名,角色,…)
  • 我将HttpClient用于该组件(自定义元素)对其后端的请求(请求确实有效,但未添加承载令牌)

根据keycloak-angular的自述:

"默认情况下,所有HttpClient请求都会添加Authorizationheader"

同样,当我在keycloakService.init方法中设置的KeycloakOptions中添加shouldAddToken函数时,该函数永远不会被调用。

我想,也许组件中的HttpClient是另一个实例,而不是main中的实例。但我检查过了,是同一个实例。我设置了(httpService as any).mytest = 1;在主。

你知道我会错过什么吗?

main.ts中的相关代码

(async () => {
// inspired by https://www.angulararchitects.io/aktuelles/angular-elements-web-components-with-standalone-components/
const app = await createApplication({
providers: [
provideHttpClient(),
KeycloakService,
{
// I guess this should not be necessary, but I tryed anyway
provide: HTTP_INTERCEPTORS,
useClass: KeycloakBearerInterceptor,
multi: true,
deps: [KeycloakService]
},
],
});

try {
await initializeKeycloak(app);
} catch (err: any) {
console.error('Seems like there was a problem with the login', err);
return;
}
// register my root component as CustomElement
customElements.define(
'my-component',
createCustomElement(AppComponent, { injector: app.injector })
);
})();    
async function initializeKeycloak(app: ApplicationRef) {

const keycloakService = app.injector.get(KeycloakService);

return keycloakService.init({

// keycloak address and client data coming from environment file
config: environment.keycloak.config,
/* without this getUsername() returns the Error "User not logged in or user profile was not loaded." */
loadUserProfileAtStartUp: true,
initOptions: {
enableLogging: true,
onLoad: 'login-required',
// someone on the web had the same problem (no auth header) and fixed it with this (not sure if this is relevant, it does not help in my case)
silentCheckSsoRedirectUri:
window.location.origin + '/assets/silent-check-sso.html',
},
shouldAddToken: (request) => {
// is never logged
console.log('XXXXXXXXXXX addToken?', request);
return true;
}

}).then(async loggedIn =>  {
if (loggedIn) {

// returns sane data
console.log("loggedIn: ", {
loggedIn,
username: keycloakService.getUsername(),
roles: keycloakService.getUserRoles().join(', '),
jwt: jwt_decode(await keycloakService.getToken())
});

// returns true
console.log("keycloakService.enableBearerInterceptor", keycloakService.enableBearerInterceptor);
} else {
console.log(`keycloak.init returned ` + loggedIn);
}

return loggedIn;
});
}

更新

有两件事我不确定,这可能导致Keycloak拦截器不添加承载令牌:

如果域名不同,可能没有添加它们?

  • 我的keycloak是在http://test.local:8080
  • 我的angular app在http://localhost:4200
  • 我的后端应用程序在http://localhost:3333

也许HttpInterceptor需要被添加到每个模块做http请求?!已经尝试将以下内容添加到我的AppModule导入的一个模块中(没有成功),该模块通过HttpClient进行请求。

{
provide: HTTP_INTERCEPTORS,
useClass: KeycloakBearerInterceptor,  
multi: true, 
...

HttpClient在任何地方都是相同的实例(如前所述)。

问题解决

因为我使用的是一个独立的组件,所以我不能把HttpClientModule添加到AppModule的imports数组中。新方法是方法吗?provideHttpClient.

而不是像这样添加结构到您的提供者数组

{
// I guess this should not be necessary, but I tryed anyway
provide: HTTP_INTERCEPTORS,
useClass: KeycloakBearerInterceptor,
multi: true,
deps: [KeycloakService]
},

你可以添加新的"函数拦截器";到provideHttpClient像这样

provideHttpClient(
withInterceptors([ requestInterceptor ]) 
)

其中requestInterceptor是一个简单的函数而不是一个服务

function requestInterceptor(
req: HttpRequest<unknown>,
next: HttpHandlerFn
): Observable<HttpEvent<unknown>> {
...
}

你也可以添加">遗留拦截器";像以前一样,但是你必须告诉新的API去搜索它们,并通过withInterceptorsFromDi()将它们注入到你的提供商中。而这正是我的代码中所缺少的。

现在的样子

const app = await createApplication({
providers: [
...,
provideHttpClient(
withInterceptors([
// just testing the new way of intercepting
requestInterceptor
]),
withInterceptorsFromDi()
),
KeycloakAngularModule,
KeycloakService,
KeycloakBearerInterceptor,
{
provide: HTTP_INTERCEPTORS,
useClass: KeycloakBearerInterceptor,
multi: true,
deps: [KeycloakService]
},
{
// testing own legacy interceptor
provide: HTTP_INTERCEPTORS,
useClass: LoggingInterceptor,
multi: true
},
],
});

所有3个拦截器都有效。

这篇文章是我穿着闪亮盔甲的骑士

最新更新