Version 11 to 12
Version 12 introduces a big new feature with supporting multiple configurations and with that multiple identity provider. With that the configuration and the interface for the users changes.
We also introduced an easier way of configuring the lib from the start to align in best practices.
Bootstrapping the lib
To make the configuration at the start easier and to be able to pass multiple configs we re-wrote the bootstrapping process of the lib.
Static configuration
Old:
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { AuthModule, OidcConfigService } from 'angular-auth-oidc-client';
// ...
export function configureAuth(oidcConfigService: OidcConfigService) {
return () =>
oidcConfigService.withConfig({
/* your config here */
});
}
@NgModule({
// ...
imports: [
// ...
AuthModule.forRoot(),
],
providers: [
OidcConfigService,
{
provide: APP_INITIALIZER,
useFactory: configureAuth,
deps: [OidcConfigService],
multi: true,
},
],
// ...
})
export class AppModule {}
New:
import { NgModule } from '@angular/core';
import { AuthModule } from 'angular-auth-oidc-client';
// ...
@NgModule({
// ...
imports: [
// ...
AuthModule.forRoot({
config: {
/* your config here */
},
}),
],
// ...
})
export class AppModule {}
Loading config from endpoint (http)
Old
import { HttpClient } from '@angular/common/http';
import { APP_INITIALIZER, NgModule } from '@angular/core';
import {
AuthModule,
OidcConfigService,
OidcSecurityService,
} from 'angular-auth-oidc-client';
import { map, switchMap } from 'rxjs/operators';
export function configureAuth(
oidcConfigService: OidcConfigService,
httpClient: HttpClient
) {
const setupAction$ = httpClient.get<any>(`https://...`).pipe(
map((customConfig) => {
return {
/* your config mapping here */
};
}),
switchMap((config) => oidcConfigService.withConfig(config))
);
return () => setupAction$.toPromise();
}
@NgModule({
imports: [AuthModule.forRoot()],
providers: [
OidcSecurityService,
OidcConfigService,
{
provide: APP_INITIALIZER,
useFactory: configureAuth,
deps: [OidcConfigService, HttpClient],
multi: true,
},
],
exports: [AuthModule],
})
export class AuthConfigModule {}
New
import { HttpClient } from '@angular/common/http';
import { NgModule } from '@angular/core';
import {
AuthModule,
StsConfigHttpLoader,
StsConfigLoader,
} from 'angular-auth-oidc-client';
import { map } from 'rxjs/operators';
export const httpLoaderFactory = (httpClient: HttpClient) => {
const config$ = httpClient
.get<any>(`https://...`)
.pipe(
map((customConfig: any) => {
return {
/* your config mapping here */
};
})
)
.toPromise();
return new StsConfigHttpLoader(config$);
};
@NgModule({
imports: [
AuthModule.forRoot({
loader: {
provide: StsConfigLoader,
useFactory: httpLoaderFactory,
deps: [HttpClient],
},
}),
],
exports: [AuthModule],
})
export class AuthConfigModule {}
Configuration
authWellknownEndpoint renamed to authWellknownEndpointUrl
Old:
export interface OpenIdConfiguration {
authWellknownEndpoint?: string;
// ...
}
New:
export interface OpenIdConfiguration {
authWellknownEndpointUrl?: string;
// ...
}
AuthWellKnownEndpoints are now part of the config
In the previous version, authWellKnownEndpoints was a separate parameter you could provide alongside the config in withConfig to configure your Security Token Service's Well-Known Endpoints. This parameter still exists, and it is of the same type, but it's now a parameter on the config object rather than being a separate parameter on withConfig(..., authwellKonwn)
Old:
const config = { ... };
const authWellknownEndpoints = { ... };
New:
const config = {
authWellknownEndpoints: { ... }
// other values...
};
autoUserinfo --> autoUserInfo
The casing was corrected in the config.
Old:
export interface OpenIdConfiguration {
autoUserinfo?: boolean;
// ...
}
New:
export interface OpenIdConfiguration {
autoUserInfo?: boolean;
// ...
}
Custom Params to pass to requests have been renamed
customParams-->customParamsAuthRequestcustomParamsRefreshToken-->customParamsRefreshTokenRequestcustomParamsEndSession-->customParamsEndSessionRequestcustomTokenParams-->customParamsCodeRequest
Old:
export interface OpenIdConfiguration {
customParams?: { [key: string]: string | number | boolean };
customParamsRefreshToken?: { [key: string]: string | number | boolean };
customParamsEndSession?: { [key: string]: string | number | boolean };
customTokenParams?: { [key: string]: string | number | boolean };
// ...
}
New:
export interface OpenIdConfiguration {
customParamsAuthRequest?: { [key: string]: string | number | boolean };
customParamsRefreshTokenRequest?: {
[key: string]: string | number | boolean;
};
customParamsEndSessionRequest?: { [key: string]: string | number | boolean };
customParamsCodeRequest?: { [key: string]: string | number | boolean };
// ...
}
Service OidcSecurityService
Getter for configuration replaced by method and object PublicConfiguration deleted
The getter for the active configuration was removed as well as the object PublicConfiguration as return type. Since the AuthWellKnownEndpoints parameter is now part of the config, the property was replaced with methods to get the configuration directly. Please read below on how to get the currently used configuration.
Old:
export class OidcSecurityService {
get configuration(): PublicConfiguration {}
}
used with
const configuration = this.oidcSecurityService.configuration;
New:
getConfigurations(): OpenIdConfiguration[] { }
getConfiguration(configId?: string): OpenIdConfiguration { }
used with
const configurations = this.oidcSecurityService.getConfigurations();
const configuration = this.oidcSecurityService.getConfiguration();
// or
const configuration = this.oidcSecurityService.getConfiguration('configId');
getToken() renamed to getAccessToken()
Old
const accessToken = this.oidcSecurityService.getToken();
New
const accessToken = this.oidcSecurityService.getAccessToken();
checkAuth() returning LoginResponse instead of boolean
The checkAuth() method no longer returns a boolean value denoting the authentication status. Instead, an object is returned containing:
{
isAuthenticated: boolean;
userData: any;
accessToken: string;
idToken: string;
configId: string;
errorMessage?: string;
}
Old:
this.oidcSecurityService.checkAuth().subscribe((isAuthenticated) => {});
New:
this.oidcSecurityService.checkAuth().subscribe(({ isAuthenticated }) => {});
Or
this.oidcSecurityService
.checkAuth()
.subscribe(
({ isAuthenticated, userData, accessToken, idToken, configId }) => {
// ...use data
}
);
checkAuthIncludingServer() returning LoginResponse instead of boolean
See checkAuth() returning LoginResponse instead of boolean.
Same applies for checkAuthIncludingServer()
forceRefreshSession() returning LoginResponse instead of TokenResponse
See checkAuth() returning LoginResponse instead of boolean.
Same return value applies for forceRefreshSession().
Old:
this.oidcSecurityService
.forceRefreshSession()
.subscribe((isAuthenticated) => {});
New:
this.oidcSecurityService.checkAuth().subscribe(({ isAuthenticated }) => {});
isAuthenticated$ returning AuthenticatedResult instead of boolean only
Old:
this.oidcSecurityService.isAuthenticated$.subscribe((isAuthenticated) => {});
New:
this.oidcSecurityService.isAuthenticated$.subscribe(
({ isAuthenticated, allConfigsAuthenticated }) => {}
);
userData$ returning UserDataResult instead of any only
Old:
this.oidcSecurityService.userData$.subscribe((userData) => {});
New:
Single Config:
this.oidcSecurityService.userData$.subscribe(({ userData }) => {});
Multiple Configs:
this.oidcSecurityService.userData$.subscribe(({ allUserData }) => {});
authorize(...) has new configId as first parameter
Because V12 introduces multiple configs, the first parameter is now configId.
Old:
const authOptions = {...}
this.oidcSecurityService.authorize(authOptions)
New:
const authOptions = {...}
const configIdOrNull = ./*...*/;
this.oidcSecurityService.authorize(configIdOrNull, authOptions)
logoffAndRevokeTokens(...) has new configId as first parameter
Because V12 introduces multiple configs, the first parameter is now configId.
Old:
const authOptions = {...}
this.oidcSecurityService.logoffAndRevokeTokens(authOptions)
New:
const authOptions = {...}
const configIdOrNull = ./*...*/;
this.oidcSecurityService.logoffAndRevokeTokens(configIdOrNull, authOptions)
logoff(...) has new parameters
Because V12 introduces multiple configs, the first parameter is now configId and the second parameter is AuthOptions.
Old:
logoff(urlHandler?: (url: string) => any) { }
called with
const urlHandler = () => {};
service.logoff(urlHandler);
New:
const authOptions = { urlHandler = () => {}, ...}
const configIdOrNull = ./*...*/;
this.oidcSecurityService.logoff(configIdOrNull, authOptions)
Interface AuthorizationResult changed and renamed to AuthStateResult
The old interface AuthorizationResult had the following structure:
export interface AuthorizationResult {
authorizationState: AuthorizedState;
validationResult: ValidationResult;
isRenewProcess: boolean;
}
The interface was renamed and the authorizationState: AuthorizedState; was converted into a boolean and renamed.
Old:
export interface AuthorizationResult {
authorizationState: AuthorizedState;
validationResult: ValidationResult;
isRenewProcess: boolean;
}
this.eventService
.registerForEvents()
.pipe(
filter(
(notification) => notification.type === EventTypes.NewAuthorizationResult
)
)
.subscribe((result: OidcClientNotification<AuthorizationResult>) => {
console.log(
'isAuthenticated',
result.value.authorizationState === AuthorizedState.Authorized
);
});
New
export interface AuthStateResult {
isAuthenticated: boolean;
validationResult: ValidationResult;
isRenewProcess: boolean;
}
this.eventService
.registerForEvents()
.pipe(
filter(
(notification) => notification.type === EventTypes.NewAuthenticationResult
)
)
.subscribe((result: OidcClientNotification<AuthStateResult>) => {
console.log('isAuthenticated', result.isAuthenticated);
});
NewAuthorizationResult was renamed to NewAuthenticationResult
The event has changed from NewAuthorizationResult to NewAuthenticationResult
Old:
this.eventService
.registerForEvents()
.pipe(
filter(
(notification) => notification.type === EventTypes.NewAuthorizationResult
)
)
.subscribe((result: OidcClientNotification<AuthorizationResult>) => {});
New:
this.eventService
.registerForEvents()
.pipe(
filter(
(notification) => notification.type === EventTypes.NewAuthenticationResult
)
)
.subscribe((result: OidcClientNotification<AuthStateResult>) => {});
AutoLoginGuard --> AutoLoginAllRoutesGuard and AutoLoginPartialRoutesGuard
Due to a lot of feedback about the AutoLoginGuard and usage we did not expect in that way we decided to give the AuthGuard a brush and divided it into a AutoLoginAllRoutesGuard when you want to secure your complete app and an AutoLoginPartialRoutesGuard if some of your routes are publicly accessible.
Please refer to the docs about more information.
Old (securing the whole app)
import { AutoLoginGuard } from 'angular-auth-oidc-client';
const appRoutes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'home' },
{ path: 'home', component: HomeComponent, canActivate: [AutoLoginGuard] },
{
path: 'protected',
component: ProtectedComponent,
canActivate: [AutoLoginGuard],
},
{
path: 'forbidden',
component: ForbiddenComponent,
canActivate: [AutoLoginGuard],
},
{
path: 'customers',
loadChildren: () =>
import('./customers/customers.module').then((m) => m.CustomersModule),
canLoad: [AutoLoginGuard],
},
{ path: 'unauthorized', component: UnauthorizedComponent },
];
New (securing the whole app)
import { AutoLoginAllRoutesGuard } from 'angular-auth-oidc-client';
const appRoutes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'home' },
{
path: 'home',
component: HomeComponent,
canActivate: [AutoLoginAllRoutesGuard],
},
{
path: 'protected',
component: ProtectedComponent,
canActivate: [AutoLoginAllRoutesGuard],
},
{
path: 'forbidden',
component: ForbiddenComponent,
canActivate: [AutoLoginAllRoutesGuard],
},
{
path: 'customers',
loadChildren: () =>
import('./customers/customers.module').then((m) => m.CustomersModule),
canLoad: [AutoLoginAllRoutesGuard],
},
{ path: 'unauthorized', component: UnauthorizedComponent },
];
Old (securing parts of the app)
import { AutoLoginGuard } from 'angular-auth-oidc-client';
const appRoutes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'home' },
{ path: 'home', component: HomeComponent },
{
path: 'protected',
component: ProtectedComponent,
canActivate: [AutoLoginGuard],
},
{
path: 'forbidden',
component: ForbiddenComponent,
canActivate: [AutoLoginGuard],
},
{
path: 'customers',
loadChildren: () =>
import('./customers/customers.module').then((m) => m.CustomersModule),
canLoad: [AutoLoginGuard],
},
{ path: 'unauthorized', component: UnauthorizedComponent },
];
New (securing parts of the app)
import { AutoLoginPartialRoutesGuard } from 'angular-auth-oidc-client';
const appRoutes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'home' },
{ path: 'home', component: HomeComponent },
{
path: 'protected',
component: ProtectedComponent,
canActivate: [AutoLoginPartialRoutesGuard],
},
{
path: 'forbidden',
component: ForbiddenComponent,
canActivate: [AutoLoginPartialRoutesGuard],
},
{
path: 'customers',
loadChildren: () =>
import('./customers/customers.module').then((m) => m.CustomersModule),
canLoad: [AutoLoginPartialRoutesGuard],
},
{ path: 'unauthorized', component: UnauthorizedComponent },
];
stsServer --> authority
Renaming the stsServer to authority. The authority issues tokens. Sometimes this is called secure token service, auth server, identity provider. The authority can also be the issuer but does not have to be.
Old:
export interface OpenIdConfiguration {
stsServer: string;
// ...
}
New:
export interface OpenIdConfiguration {
authority: string;
// ...
}