Skip to content

Commit

Permalink
feat(auth): configure auth with provider
Browse files Browse the repository at this point in the history
BREAKING CHANGE: AuthModule is deprecated and use the provideAuthentification for the configuration
  • Loading branch information
alecarn committed Apr 4, 2024
1 parent fb9d1eb commit e046947
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 99 deletions.
30 changes: 3 additions & 27 deletions packages/auth/form/src/auth-form.module.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
import { CommonModule } from '@angular/common';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { ModuleWithProviders, NgModule } from '@angular/core';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';

import { AuthInterceptor } from '@igo2/auth';
import { AuthFacebookComponent } from '@igo2/auth/facebook';
import { AuthGoogleComponent } from '@igo2/auth/google';
import { AuthInternComponent } from '@igo2/auth/internal';
import {
AuthMicrosoftComponent,
AuthMicrosoftb2cComponent,
provideAuthMicrosoft
AuthMicrosoftb2cComponent
} from '@igo2/auth/microsoft';
import { IgoLanguageModule } from '@igo2/core/language';
import { StorageService } from '@igo2/core/storage';

import { MsalModule } from '@azure/msal-angular';

import { AuthFormComponent } from './auth-form/auth-form.component';
import { AuthStorageService } from './shared/auth-storage.service';

@NgModule({
imports: [
Expand All @@ -45,23 +40,4 @@ import { AuthStorageService } from './shared/auth-storage.service';
],
exports: [AuthFormComponent]
})
export class IgoAuthFormModule {
static forRoot(): ModuleWithProviders<IgoAuthFormModule> {
return {
ngModule: IgoAuthFormModule,
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
},
{
provide: StorageService,
useClass: AuthStorageService
},
...provideAuthMicrosoft('add'),
...provideAuthMicrosoft('b2c')
]
};
}
}
export class IgoAuthFormModule {}
73 changes: 44 additions & 29 deletions packages/auth/microsoft/src/auth-microsoft.provider.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AuthFeature, AuthFeatureKind } from '@igo2/auth';
import { ConfigService } from '@igo2/core/config';

import {
Expand Down Expand Up @@ -25,6 +26,9 @@ export function MSALConfigFactory(
config: ConfigService
): PublicClientApplication {
const msConf = config.getConfig('auth.microsoft') as AuthMicrosoftOptions;
if (!msConf) {
return;
}

msConf.redirectUri = msConf?.redirectUri || window.location.href;
msConf.authority =
Expand All @@ -46,6 +50,9 @@ export function MSALConfigFactoryb2c(
const msConf = config.getConfig(
'auth.microsoftb2c.browserAuthOptions'
) as BrowserAuthOptions;
if (!msConf) {
return;
}
msConf.redirectUri = msConf?.redirectUri || window.location.href;
msConf.authority =
msConf?.authority || 'https://login.microsoftonline.com/organizations';
Expand Down Expand Up @@ -91,36 +98,44 @@ export function MSALAngularConfigFactoryb2c(
};
}

export function provideAuthMicrosoft(type?: string) {
export function withMicrosoftSupport(
type?: string
): AuthFeature<AuthFeatureKind.Microsoft> {
if (type === 'b2c') {
return [
{
provide: MSAL_INSTANCE,
useFactory: MSALConfigFactoryb2c,
deps: [ConfigService]
},
{
provide: MSAL_GUARD_CONFIG,
useFactory: MSALAngularConfigFactoryb2c,
deps: [ConfigService],
multi: true
},
MsalServiceb2c
];
return {
kind: AuthFeatureKind.Microsoft,
providers: [
{
provide: MSAL_INSTANCE,
useFactory: MSALConfigFactoryb2c,
deps: [ConfigService]
},
{
provide: MSAL_GUARD_CONFIG,
useFactory: MSALAngularConfigFactoryb2c,
deps: [ConfigService],
multi: true
},
MsalServiceb2c
]
};
} else {
return [
{
provide: MSAL_INSTANCE,
useFactory: MSALConfigFactory,
deps: [ConfigService]
},
{
provide: MSAL_GUARD_CONFIG,
useFactory: MSALAngularConfigFactory,
deps: [ConfigService],
multi: true
},
MsalService
];
return {
kind: AuthFeatureKind.Microsoft,
providers: [
{
provide: MSAL_INSTANCE,
useFactory: MSALConfigFactory,
deps: [ConfigService]
},
{
provide: MSAL_GUARD_CONFIG,
useFactory: MSALAngularConfigFactory,
deps: [ConfigService],
multi: true
},
MsalService
]
};
}
}
38 changes: 38 additions & 0 deletions packages/auth/src/lib/auth.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { CommonModule } from '@angular/common';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { ModuleWithProviders, NgModule } from '@angular/core';

import { AuthFormComponent, AuthStorageService } from '@igo2/auth/form';
import { withMicrosoftSupport } from '@igo2/auth/microsoft';
import { IgoLanguageModule } from '@igo2/core/language';
import { StorageService } from '@igo2/core/storage';

import { AuthInterceptor } from '../public_api';

/**
* @deprecated import the AuthFormComponent directly and configure the auth with provideAuthentification
*/
@NgModule({
imports: [CommonModule, IgoLanguageModule, AuthFormComponent],
exports: [AuthFormComponent]
})
export class IgoAuthFormModule {
static forRoot(): ModuleWithProviders<IgoAuthFormModule> {
return {
ngModule: IgoAuthFormModule,
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
},
{
provide: StorageService,
useClass: AuthStorageService
},
...withMicrosoftSupport('add').providers,
...withMicrosoftSupport('b2c').providers
]
};
}
}
33 changes: 33 additions & 0 deletions packages/auth/src/lib/auth.provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import {
EnvironmentProviders,
Provider,
makeEnvironmentProviders
} from '@angular/core';

import { AuthStorageService } from '@igo2/auth/form';
import { StorageService } from '@igo2/core/storage';

import { AuthFeature, AuthFeatureKind, AuthInterceptor } from './shared';

export function provideAuthentification(
...features: AuthFeature<AuthFeatureKind>[]
): EnvironmentProviders {
const providers: Provider[] = [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
},
{
provide: StorageService,
useClass: AuthStorageService
}
];

for (const feature of features) {
providers.push(...feature.providers);
}

return makeEnvironmentProviders(providers);
}
11 changes: 11 additions & 0 deletions packages/auth/src/lib/shared/auth.interface.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Provider } from '@angular/core';

import { BaseUser } from '@igo2/core/user';

export interface User extends BaseUser {
Expand Down Expand Up @@ -40,3 +42,12 @@ export interface WithCredentialsOptions {
export interface AuthInternOptions {
enabled?: boolean;
}

export interface AuthFeature<KindT extends AuthFeatureKind> {
kind: KindT;
providers: Provider[];
}

export declare enum AuthFeatureKind {
Microsoft = 0
}
2 changes: 2 additions & 0 deletions packages/auth/src/public_api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/*
* Public API Surface of auth
*/
export * from './lib/auth.module';
export * from './lib/auth.provider';
export * from './lib/shared/auth.service';
export * from './lib/shared/logged.guard';
export * from './lib/shared/auth.guard';
Expand Down
54 changes: 11 additions & 43 deletions projects/demo/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { provideHttpClient, withJsonpSupport } from '@angular/common/http';
import {
APP_INITIALIZER,
ApplicationRef,
enableProdMode,
importProvidersFrom
} from '@angular/core';
import { enableProdMode, importProvidersFrom } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
Expand All @@ -27,9 +22,10 @@ import {
withPreloading
} from '@angular/router';

import { provideAuthentification } from '@igo2/auth';
import { IgoCoreModule } from '@igo2/core';
import { provideConfigOptions } from '@igo2/core/config';
import { LanguageService } from '@igo2/core/language';
import { provideRootTranslation } from '@igo2/core/language';
import {
IgoDirectionsModule,
IgoGeoWorkspaceModule,
Expand All @@ -38,8 +34,6 @@ import {
provideWorkspaceSearchSource
} from '@igo2/geo';

import { concatMap, first } from 'rxjs';

import { AppComponent } from './app/app.component';
import { routes } from './app/app.routing';
import { environment } from './environments/environment';
Expand Down Expand Up @@ -70,46 +64,20 @@ bootstrapApplication(AppComponent, {
IgoDirectionsModule
),
provideHttpClient(withJsonpSupport()),
provideRouter(routes, withPreloading(PreloadAllModules)),
provideAnimations(),
provideConfigOptions({
default: environment.igo
}),
provideRouter(routes, withPreloading(PreloadAllModules)),
provideRootTranslation(),
provideAuthentification(),
provideOsrmDirectionsSource(),
provideIChercheSearchSource(),
provideWorkspaceSearchSource(),
{
provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
useValue: { appearance: 'outline' }
},
{
provide: APP_INITIALIZER,
useFactory: appInitializerFactory,
deps: [ApplicationRef, LanguageService],
multi: true
},
{ provide: MAT_TOOLTIP_DEFAULT_OPTIONS, useValue: defaultTooltipOptions },
provideAnimations(),
provideOsrmDirectionsSource(),
provideIChercheSearchSource(),
provideWorkspaceSearchSource()
{ provide: MAT_TOOLTIP_DEFAULT_OPTIONS, useValue: defaultTooltipOptions }
]
}).catch((err) => console.log(err));

export function appInitializerFactory(
applicationRef: ApplicationRef,
languageService: LanguageService
) {
return () =>
new Promise<any>((resolve: any) => {
applicationRef.isStable
.pipe(
first((isStable) => isStable === true),
concatMap(() => {
const lang = languageService.getLanguage();
return languageService.translate.getTranslation(lang);
})
)
.subscribe((translations) => {
const lang = languageService.getLanguage();
languageService.translate.setTranslation(lang, translations);
resolve();
});
});
}

0 comments on commit e046947

Please sign in to comment.