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
-->customParamsAuthRequest
customParamsRefreshToken
-->customParamsRefreshTokenRequest
customParamsEndSession
-->customParamsEndSessionRequest
customTokenParams
-->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;
// ...
}