<commit_before># 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.

## Breaking Changes

### Configuration

#### New Param `configId`

To identify a configuration a new parameter called `configId` was introduced. This is being filled from the lib when the user does not set it explicitly in the config. If set, the configured value is taken. It is optional. For a single config this param is not really important. For multiple configs this param is important.

```ts
export interface OpenIdConfiguration {
  configId?: string;
  // ...
}
```

#### `authWellknownEndpoint` renamed to `authWellknownEndpointUrl`

Old:

```ts
export interface OpenIdConfiguration {
  authWellknownEndpoint?: string;
  // ...
}
```

New:

```ts
export interface OpenIdConfiguration {
  authWellknownEndpointUrl?: string;
  // ...
}
```

#### AuthWellKnownEndpoints are now part of the config

In the previous version the `AuthWellKnownEndpoints` have been a special parameter which you could pass. The type is the same but the property is now part of the configuration. The parameter to pass is in the `withConfig` method was removed.

Old:

```ts
const config = { ... };
const authWellKnown = { ... };
```

New:

```ts

const config = {
  authWellKnown: { ... }
  // other values...
};
```

#### `autoUserinfo` --> `AutoUserInfo`

The casing was corrected in the config.

Old:

```ts
export interface OpenIdConfiguration {
  autoUserinfo?: boolean;
  // ...
}
```

New:

```ts
export interface OpenIdConfiguration {
  autoUserInfo?: boolean;
  // ...
}
```

### custom params have been renamed:

old:

```ts
customParams: {
	// yourParam: 'your_value',
},
customParamsRefreshToken: {
	// yourParam: 'your_value',
},
customParamsEndSession: {
	// yourParam: 'your_value',
},
```

new:

```ts
customParamsAuthRequest: {
	// yourParam: 'your_value',
},
customParamsRefreshTokenRequest: {
	// yourParam: 'your_value',
},
customParamsEndSessionRequest: {
	// yourParam: 'your_value',
},
customParamsCodeRequest: {
	// yourParam: 'your_value',
},
```

### Configuration in App Module

#### Old:

```ts
import { HttpClientModule } from '@angular/common/http';
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { AuthModule, LogLevel, OidcConfigService } from 'angular-auth-oidc-client';
// ...

export function configureAuth(oidcConfigService: OidcConfigService) {
  return () =>
    oidcConfigService.withConfig({
      stsServer: '<your sts address here>',
      redirectUrl: window.location.origin,
      postLogoutRedirectUri: window.location.origin,
      clientId: 'angularClient',
      scope: 'openid profile email',
      responseType: 'code',
      silentRenew: true,
      silentRenewUrl: `${window.location.origin}/silent-renew.html`,
      logLevel: LogLevel.Debug,
    });
}

@NgModule({
  // ...
  imports: [
    // ...
    AuthModule.forRoot(),
  ],
  providers: [
    OidcConfigService,
    {
      provide: APP_INITIALIZER,
      useFactory: configureAuth,
      deps: [OidcConfigService],
      multi: true,
    },
  ],
  // ...
})
export class AppModule {}
```

#### New:

```typescript
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { AuthModule, LogLevel } from 'angular-auth-oidc-client';
// ...

@NgModule({
  // ...
  imports: [
    // ...
    AuthModule.forRoot({
      config: {
        stsServer: '<your sts address here>',
        redirectUrl: window.location.origin,
        postLogoutRedirectUri: window.location.origin,
        clientId: 'angularClient',
        scope: 'openid profile email',
        responseType: 'code',
        silentRenew: true,
        silentRenewUrl: `${window.location.origin}/silent-renew.html`,
        logLevel: LogLevel.Debug,
      },
    }),
  ],
  // ...
})
export class AppModule {}
```

#### Old (with Http Loading)

```typescript
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 {
        stsServer: customConfig.stsServer,
        //...
      };
    }),
    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 (with HTTP Loading)

```typescript
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 {
          stsServer: customConfig.stsServer,
          //...
        };
      })
    )
    .toPromise();

  return new StsConfigHttpLoader(config$);
};

@NgModule({
  imports: [
    AuthModule.forRoot({
      loader: {
        provide: StsConfigLoader,
        useFactory: httpLoaderFactory,
        deps: [HttpClient],
      },
    }),
  ],
  exports: [AuthModule],
})
export class AuthConfigModule {}
```

### Return type of `checkAuth()` method is now an object `LoginResponse`

In the previous version the `checkAuth` method only returned if you are authenticated or not. New the method returns the `LoginResponse` object which provides

```typescript
export interface LoginResponse {
  isAuthenticated: boolean;
  userData?: any;
  accessToken?: string;
  errorMessage?: string;
}
```

#### Old

```typescript
this.oidcSecurityService.checkAuth().subscribe((isAuthenticated) => {
  console.log('app authenticated', isAuthenticated);
});
```

#### New

```typescript
this.oidcSecurityService.checkAuth().subscribe(({ isAuthenticated }) => {
  console.log('app authenticated', isAuthenticated);
});
```

Or if you want to have all information

```typescript
this.oidcSecurityService.checkAuth().subscribe(({ isAuthenticated, userData, accessToken, errorMessage }) => {
  console.log(isAuthenticated);
  console.log(userData);
  console.log(accessToken);
  console.log(errorMessage);
});
```

### Authorization Result has been updated with breaking changes

`AuthorizationResult` has been updated to return a boolean called `isAuthenticated` instead of an `AuthorizedState` enum value called `authorizationState`

### Old

```typescript
import { Component, OnInit } from '@angular/core';
import { PublicEventsService, EventTypes, OidcClientNotification, AuthorizationResult, AuthorizedState } from 'angular-auth-oidc-client';
import { filter } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
  title = 'AuthTest';
  constructor(private readonly eventService: PublicEventsService) {}

  ngOnInit(): void {
    this.eventService
      .registerForEvents()
      .pipe(filter((notification) => notification.type === EventTypes.NewAuthorizationResult))
      .subscribe((result: OidcClientNotification<AuthorizationResult>) => {
        console.log('NewAuthorizationResult', result);
        console.log('isAuthenticated', result.value.authorizationState === AuthorizedState.Authorized);
      });
  }
}
```

### New

```typescript
import { Component, OnInit } from '@angular/core';
import { PublicEventsService, EventTypes, OidcClientNotification, AuthorizationResult } from 'angular-auth-oidc-client';
import { filter } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
  title = 'AuthTest';
  constructor(private readonly eventService: PublicEventsService) {}

  ngOnInit(): void {
    this.eventService
      .registerForEvents()
      .pipe(filter((notification) => notification.type === EventTypes.NewAuthorizationResult))
      .subscribe((result: OidcClientNotification<AuthorizationResult>) => {
        console.log('NewAuthorizationResult', result);
        console.log('isAuthenticated', result.value.isAuthenticated);
      });
  }
}
```

### `logoff` expects object now

The parameter to be passed into the `logoff` method is now an object with the properties `urlHandler` and `customParams` which provides you to pass custom parameters to the logoff url.

#### Old

```typescript
logoff(urlHandler?: (url: string) => any) {
  return this.logoffRevocationService.logoff(urlHandler);
}
```

called with

```typescript
const urlHandler = () => {};
service.logoff(urlHandler);
```

#### New

```typescript
logoff(authOptions?: AuthOptions) {
  const { urlHandler, customParams } = authOptions || {};
}
```

called with

```typescript
const urlHandler = () => {};
const customParams = /* */; // pass them if you want to
service.logoff({ urlHandler, customParams });
```
<commit_msg>more changes<commit_after># 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.

## Breaking Changes

### Configuration

#### New Param `configId`

To identify a configuration a new parameter called `configId` was introduced. This is being filled from the lib when the user does not set it explicitly in the config. If set, the configured value is taken. It is optional. For a single config this param is not really important. For multiple configs this param is important.

```ts
export interface OpenIdConfiguration {
  configId?: string;
  // ...
}
```

#### `authWellknownEndpoint` renamed to `authWellknownEndpointUrl`

Old:

```ts
export interface OpenIdConfiguration {
  authWellknownEndpoint?: string;
  // ...
}
```

New:

```ts
export interface OpenIdConfiguration {
  authWellknownEndpointUrl?: string;
  // ...
}
```

#### AuthWellKnownEndpoints are now part of the config

In the previous version the `AuthWellKnownEndpoints` have been a special parameter which you could pass. The type is the same but the property is now part of the configuration. The parameter to pass is in the `withConfig` method was removed.

Old:

```ts
const config = { ... };
const authWellKnown = { ... };
```

New:

```ts

const config = {
  authWellKnown: { ... }
  // other values...
};
```

#### `autoUserinfo` --> `AutoUserInfo`

The casing was corrected in the config.

Old:

```ts
export interface OpenIdConfiguration {
  autoUserinfo?: boolean;
  // ...
}
```

New:

```ts
export interface OpenIdConfiguration {
  autoUserInfo?: boolean;
  // ...
}
```

#### Custom Params to pass to requests have been renamed

Old:

```ts
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:

```ts
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 };
  // ...
}
```

### Configuration in App Module

#### Old:

```ts
import { HttpClientModule } from '@angular/common/http';
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { AuthModule, LogLevel, OidcConfigService } from 'angular-auth-oidc-client';
// ...

export function configureAuth(oidcConfigService: OidcConfigService) {
  return () =>
    oidcConfigService.withConfig({
      stsServer: '<your sts address here>',
      redirectUrl: window.location.origin,
      postLogoutRedirectUri: window.location.origin,
      clientId: 'angularClient',
      scope: 'openid profile email',
      responseType: 'code',
      silentRenew: true,
      silentRenewUrl: `${window.location.origin}/silent-renew.html`,
      logLevel: LogLevel.Debug,
    });
}

@NgModule({
  // ...
  imports: [
    // ...
    AuthModule.forRoot(),
  ],
  providers: [
    OidcConfigService,
    {
      provide: APP_INITIALIZER,
      useFactory: configureAuth,
      deps: [OidcConfigService],
      multi: true,
    },
  ],
  // ...
})
export class AppModule {}
```

#### New:

```typescript
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { AuthModule, LogLevel } from 'angular-auth-oidc-client';
// ...

@NgModule({
  // ...
  imports: [
    // ...
    AuthModule.forRoot({
      config: {
        stsServer: '<your sts address here>',
        redirectUrl: window.location.origin,
        postLogoutRedirectUri: window.location.origin,
        clientId: 'angularClient',
        scope: 'openid profile email',
        responseType: 'code',
        silentRenew: true,
        silentRenewUrl: `${window.location.origin}/silent-renew.html`,
        logLevel: LogLevel.Debug,
      },
    }),
  ],
  // ...
})
export class AppModule {}
```

#### Old (with Http Loading)

```typescript
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 {
        stsServer: customConfig.stsServer,
        //...
      };
    }),
    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 (with HTTP Loading)

```typescript
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 {
          stsServer: customConfig.stsServer,
          //...
        };
      })
    )
    .toPromise();

  return new StsConfigHttpLoader(config$);
};

@NgModule({
  imports: [
    AuthModule.forRoot({
      loader: {
        provide: StsConfigLoader,
        useFactory: httpLoaderFactory,
        deps: [HttpClient],
      },
    }),
  ],
  exports: [AuthModule],
})
export class AuthConfigModule {}
```

### Return type of `checkAuth()` method is now an object `LoginResponse`

In the previous version the `checkAuth` method only returned if you are authenticated or not. New the method returns the `LoginResponse` object which provides

```typescript
export interface LoginResponse {
  isAuthenticated: boolean;
  userData?: any;
  accessToken?: string;
  errorMessage?: string;
}
```

#### Old

```typescript
this.oidcSecurityService.checkAuth().subscribe((isAuthenticated) => {
  console.log('app authenticated', isAuthenticated);
});
```

#### New

```typescript
this.oidcSecurityService.checkAuth().subscribe(({ isAuthenticated }) => {
  console.log('app authenticated', isAuthenticated);
});
```

Or if you want to have all information

```typescript
this.oidcSecurityService.checkAuth().subscribe(({ isAuthenticated, userData, accessToken, errorMessage }) => {
  console.log(isAuthenticated);
  console.log(userData);
  console.log(accessToken);
  console.log(errorMessage);
});
```

### Authorization Result has been updated with breaking changes

`AuthorizationResult` has been updated to return a boolean called `isAuthenticated` instead of an `AuthorizedState` enum value called `authorizationState`

### Old

```typescript
import { Component, OnInit } from '@angular/core';
import { PublicEventsService, EventTypes, OidcClientNotification, AuthorizationResult, AuthorizedState } from 'angular-auth-oidc-client';
import { filter } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
  title = 'AuthTest';
  constructor(private readonly eventService: PublicEventsService) {}

  ngOnInit(): void {
    this.eventService
      .registerForEvents()
      .pipe(filter((notification) => notification.type === EventTypes.NewAuthorizationResult))
      .subscribe((result: OidcClientNotification<AuthorizationResult>) => {
        console.log('NewAuthorizationResult', result);
        console.log('isAuthenticated', result.value.authorizationState === AuthorizedState.Authorized);
      });
  }
}
```

### New

```typescript
import { Component, OnInit } from '@angular/core';
import { PublicEventsService, EventTypes, OidcClientNotification, AuthorizationResult } from 'angular-auth-oidc-client';
import { filter } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
  title = 'AuthTest';
  constructor(private readonly eventService: PublicEventsService) {}

  ngOnInit(): void {
    this.eventService
      .registerForEvents()
      .pipe(filter((notification) => notification.type === EventTypes.NewAuthorizationResult))
      .subscribe((result: OidcClientNotification<AuthorizationResult>) => {
        console.log('NewAuthorizationResult', result);
        console.log('isAuthenticated', result.value.isAuthenticated);
      });
  }
}
```

### `logoff` expects object now

The parameter to be passed into the `logoff` method is now an object with the properties `urlHandler` and `customParams` which provides you to pass custom parameters to the logoff url.

#### Old

```typescript
logoff(urlHandler?: (url: string) => any) {
  return this.logoffRevocationService.logoff(urlHandler);
}
```

called with

```typescript
const urlHandler = () => {};
service.logoff(urlHandler);
```

#### New

```typescript
logoff(authOptions?: AuthOptions) {
  const { urlHandler, customParams } = authOptions || {};
}
```

called with

```typescript
const urlHandler = () => {};
const customParams = /* */; // pass them if you want to
service.logoff({ urlHandler, customParams });
```

{'fraction_non_alphanumeric': 0.13195292279142454, 'fraction_numerical': 0.0005860233432631733, 'mean_word_length': 3.2450248756218905, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 49, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '137814', 'n_tokens_mistral': 6264, 'n_tokens_neox': 5907, 'n_words': 1548}