Keycloak - how to disable sharing session between two (Angular) client apps? - javascript

I have two angular client applications that use Keycloak's angular client for authentication. The problem is, that when i log in on one of them, i'm automatically being logged to another one. I have separate client for each one though.
Keycloak service initialization looks like this in both apps:
#NgModule({
declarations: [AppComponent],
imports: [
AppRoutingModule,
BrowserModule,
KeycloakAngularModule
],
providers: [KeycloakService],
entryComponents: [AppComponent]
})
export class AppModule implements DoBootstrap {
constructor(private keycloakService: KeycloakService) {
}
ngDoBootstrap(app: ApplicationRef) {
this.keycloakService
.init({config: environment.keycloak, initOptions: {onLoad: 'login-required'}})
.then(() => app.bootstrap(AppComponent));
}
}
Keycloak config for the first app:
const keycloakConfig: KeycloakConfig = {
realm: 'quick',
url: 'http://localhost:8000/auth',
clientId: 'quick-ui-customer'
};
export const environment = {
production: false,
keycloak: keycloakConfig,
};
And for the second one:
const keycloakConfig: KeycloakConfig = {
realm: 'quick',
url: 'http://localhost:8000/auth',
clientId: 'quick-ui-employee'
};
export const environment = {
production: false,
keycloak: keycloakConfig,
};

That is a core feature of Single Sign On protocol. But if you don't want to share session, then create clients in different realms.

Related

Cannot test e2e because Nestjs doesn't resolve dependencies

I have the following error :
Nest can't resolve dependencies of the ParametrageRepository (?). Please make sure that the argument DataSource at index [0] is available in the TypeOrmModule context.
My test code :
describe("ParametrageController (e2e)", () => {
let parametrage: INestApplication;
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [ParametrageModule],
}).compile();
parametrage = moduleFixture.createNestApplication();
await parametrage.init();
});
it("/ (POST)", () =>
request(parametrage.getHttpServer())
.post("/parametrage")
.send({
libelle: "GROUPE_TYPE",
liste: ["TEAM", "SERVICE", "ORGANISATION"],
})
.expect(201));
});
My module code:
#Module({
imports: [TypeOrmModule.forFeature([Parametrage])],
exports: [TypeOrmModule],
controllers: [ParametrageController],
providers: [ParametrageService, ParametrageRepository, ParametrageActions, Logger],
})
export class ParametrageModule {}
I cannot tel why I have this error since I followed the Nestjs documentation. Maybe I skipped a part I don't know. Maybe it's because of my providers that has parameters in their constructors :
My ParametrageRepository provider :
#Injectable()
export class ParametrageRepository
extends RepositoryStarter<Parametrage, IParametrageListFilter>
implements IParametrageRepository
{
constructor(#InjectDataSource() datasource: DataSource) {
super(datasource.getRepository(Parametrage));
}
I tried to add providers injection :
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [ParametrageModule],
** providers: [
{ provide: ParametrageActions, useValue: ParametrageActions },
{ provide: ParametrageRepository, useValue: ParametrageRepository },
{ provide: Logger, useValue: Logger ,
],**
}).compile();
But stil the same error, it didn't solved anything
Thanks in advance

Reload env variables when k8s configMap changes in Nest.js application

I have a Nest.js based application running in kubernetes. There is ConfigModule initialized in the app and ConfigService that reads env variable defined in configMap.
#Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
#Injectable()
export class AppService {
#Inject(ConfigService)
private config: ConfigService;
getHello(): string {
const app = this.config.get('app-name')
const psw = this.config.get('app-password')
return `name: ${app}, password: ${psw}`;
}
}
configMap.yaml is attached to my container in deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nestjs-k8s
spec:
selector:
matchLabels:
app: nestjs-k8s
replicas: 1
template:
metadata:
labels:
app: nestjs-k8s
spec:
containers:
- name: nestjs-k8s
image: multiplexor88/nestjs-k8s
ports:
- containerPort: 3000
envFrom:
- configMapRef:
name: config-map
- secretRef:
name: secret
I want to refresh my configuration in application when configMap is changed.
Is there a way to make it?
If it is not possible, then at list is somehow schedule Nest.js ConfigModule to reinitialize without application restart.

NestJs Testing with CACHE_MANAGER injected

I have some service in which I inject the CACHE_MANAGER in the constructor
import { CACHE_MANAGER, Inject, Injectable } from '#nestjs/common';
import { Cache } from 'cache-manager';
...
export class ManagerService {
constructor(#Inject(CACHE_MANAGER) private cacheManager: Cache) {}
...
}
That gives me an error when I test the modules the import those service
Nest can't resolve dependencies of the ManagerService (?). Please make sure that the argument CACHE_MANAGER at index [0] is available in the Web3ManagerService context.
I'm relatively new to NestJs so I really cannot figure out how to solve it
To inject the cache manager provider under the CACHE_MANAGER, you need to import the nestjs module that creates this provider into the module that has the ManagerService
#Module({
imports: [CacheModule.register()], // <<<<
providers: [ManagerService],
})
export class AppModule {}
like the docs shows https://docs.nestjs.com/techniques/caching
I just had the same problem and resolved it this way:
manager.service.spec.ts
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ManagerService, { provide: CACHE_MANAGER, useValue: {} }],
}).compile();
service = module.get<ManagerService>(ManagerService);
});
Set isGlobal: true:
CacheModule.register({
url: process.env.REDIS_URL,
db: 0,
port: parseInt(process.env.REDIS_PORT),
password: process.env.REDIS_PASSWORD,
isGlobal: true, //<<<<<<<
})

How can I use interceptor in neo4j-graphql-js endpoint with nestjs framework?

I am using the neo4j-graphql-js library to translate graphql queries to cypher and I need to implement an interceptor to verify that what is returning belongs to the user who is asking for it. For this I need to implement the interceptor but the problem I have is that I have no resolvers since it generates the liberia. How can I make it go through the interceptor? If the interceptor cannot be used, is there a way to implement a middleware in the response?
I'm using nestjs framework. And I use a neo4j database.
Thank you.
Module:
#Module({
imports: [
GraphQLModule.forRootAsync({
useClass: GraphqlConfigService,
}),
],
providers: [neo4jProvider],
})
export class GraphqlModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(GraphQLAuthMiddleware,GraphQLRoleMiddleware)
.forRoutes('graphql');
}
}
#Injectable()
export class GraphqlConfigService implements GqlOptionsFactory {
async createGqlOptions(): Promise<GqlModuleOptions> {
const schema = buildSchema();
return {
playground: true,
schema: schema,
path: '/graphql/queries',
context: {
driver: neo4j.driver(
'bolt://neo4j_db:7687',
neo4j.auth.basic('neo4j', 'root')
)
}
};
}
}
function buildSchema(): GraphQLSchema {
return makeAugmentedSchema({
typeDefs,
config: {
query: true,
mutation: true
}
});
}
You can bind your interceptor globally either by using the app.useGlobalInterceptors(MyCustomInterceptor) method in your main.ts or in any module you can add the interceptor in your providers array
#Module({
imports: [/* your imports*/],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: MyCustomInterceptor
},
/* the rest of your providers*/
],
})
export class GraphqlModule {}
APP_INTERCEPTOR is imported from #nestjs/core. Keep in mind, this does bind the interceptor globally. All requests to your server will go through this interceptor.

Angular CLI 6.x environment files for a library

I've created a library with the new CLI 6.x. I've also created an Angular service inside it and I would like to use different URLs for my dev and prod environment. So I created an environment.ts and an environment.prod.ts file in my library folder.
//dev
export const environment = {
production: false,
url: 'dev-url'
};
//prod
export const environment = {
production: true,
url: 'prod-url'
};
I also added the 'fileReplacements' property to the angular.json file:
"configurations": {
"production": {
"fileReplacements": [{
"replace": "projects/tk-shared/src/environments/environment.ts",
"with": "projects/tk-shared/src/environments/environment.prod.ts"
}],
"project": "projects/tk-shared/ng-package.prod.json"
}
}
Compiling the library with the ng build tk-shared works and uses the dev settings, however when compiling with ng build --prod tk-shared I get the following error:
Schema validation failed with the following errors: Data path "" should NOT have additional properties(fileReplacements).
My tip is that the reason is that tk-shared has the projectType: "library" property in angular.json.
Anyway, is it possible to use environment files in a library?
Thanks, #R. Richards for pointing me to the right solution!
These two sources helped me figure out how to do this injection correctly: LINK1 and LINK2.
So what I did ...
Created an InjectionToken and modified my TkSharedModule:
export const BASE_URL = new InjectionToken<string>('BASE_URL');
//...
export class TkSharedModule {
static forRoot(host: string) {
return {
ngModule: TkSharedModule,
providers: [{
provide: BASE_URL,
useValue: host
}]
}
}
}
Provided a value for this token from the environment files in my AppModule:
import {environment} from '../environments/environment';
//...
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
TkSharedModule.forRoot(environment.url)
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
And finally injected this value in my service:
//MyServiceService
import { BASE_URL } from '../tk-shared.module';
constructor(#Inject(BASE_URL) BASE_URL: string) {
console.log('base url', BASE_URL);
}

Categories

Resources