Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Custom Params for EndSession and RefreshTokens Renew #1093

Merged
merged 12 commits into from
May 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 25 additions & 32 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,34 +1,27 @@
{
"editor.codeActionsOnSave": {
"source.organizeImports": true
},
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[less]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"cSpell.words": [
"Authorisation",
"autologin",
"azuread",
"jwtkeys",
"oidc",
"openid"
]
"editor.codeActionsOnSave": {
"source.organizeImports": true
},
"editor.formatOnSave": true,
"editor.formatOnPaste": false,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[less]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"cSpell.words": ["Authorisation", "autologin", "azuread", "jwtkeys", "oidc", "openid"]
}
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
## Angular Lib for OpenID Connect/OAuth2 Changelog

### 2021-05-04 Version 11.6.9

- Support Custom Params for EndSession and RefreshTokens Renew
- [PR](https://github.com/damienbod/angular-auth-oidc-client/pull/1093)
- Added Auth0 example

### 2021-05-04 Version 11.6.8

- bugfix incorrect storage for silent renew, requires Json object
Expand Down
104 changes: 104 additions & 0 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,110 @@
}
}
},

"sample-code-flow-auth0": {
"projectType": "application",
"schematics": {},
"root": "projects/sample-code-flow-auth0",
"sourceRoot": "projects/sample-code-flow-auth0/src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/sample-code-flow-auth0",
"index": "projects/sample-code-flow-auth0/src/index.html",
"main": "projects/sample-code-flow-auth0/src/main.ts",
"polyfills": "projects/sample-code-flow-auth0/src/polyfills.ts",
"tsConfig": "projects/sample-code-flow-auth0/tsconfig.app.json",
"aot": true,
"assets": ["projects/sample-code-flow-auth0/src/favicon.ico", "projects/sample-code-flow-auth0/src/assets"],
"styles": ["projects/sample-code-flow-auth0/src/styles.css"],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "projects/sample-code-flow-auth0/src/environments/environment.ts",
"with": "projects/sample-code-flow-auth0/src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "sample-code-flow-auth0:build",
"sslKey": "certs/dev_localhost.key",
"sslCert": "certs/dev_localhost.pem",
"port": 4204
},
"configurations": {
"production": {
"browserTarget": "sample-code-flow-auth0:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "sample-code-flow-auth0:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/sample-code-flow-auth0/src/test.ts",
"polyfills": "projects/sample-code-flow-auth0/src/polyfills.ts",
"tsConfig": "projects/sample-code-flow-auth0/tsconfig.spec.json",
"karmaConfig": "projects/sample-code-flow-auth0/karma.conf.js",
"assets": ["projects/sample-code-flow-auth0/src/favicon.ico", "projects/sample-code-flow-auth0/src/assets"],
"styles": ["projects/sample-code-flow-auth0/src/styles.css"],
"scripts": []
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": ["projects/sample-code-flow-auth0/**/*.ts", "projects/sample-code-flow-auth0/**/*.html"]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "projects/sample-code-flow-auth0/e2e/protractor.conf.js",
"devServerTarget": "sample-code-flow-auth0:serve"
},
"configurations": {
"production": {
"devServerTarget": "sample-code-flow-auth0:serve:production"
}
}
}
}
},

"sample-code-flow-refresh-tokens": {
"projectType": "application",
"schematics": {},
Expand Down
2 changes: 2 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,5 @@ In this document are all the values which can be set to configure this library.
| `customTokenParams` | `{ [key: string]: string, number, boolean }` | extra parameters can be added to the token URL request. | No |
| `refreshTokenRetryInSeconds` | `number` | Controls the periodic retry time interval for retrieving new tokens in seconds, default = 3. `silentRenewTimeoutInSeconds` and `tokenRefreshInSeconds` are upper bounds for this value. | No |
| `ngswBypass` | `boolean` | Adds the `ngsw-bypass` param to all requests ([Angular Docu](https://angular.io/guide/service-worker-devops#bypassing-the-service-worker)). | No |
| `customParamsRefreshToken` | `{ [key: string]: string, number, boolean }` | Extra parameters to add to the refresh token request body. | No |
| `customParamsEndSession` | `{ [key: string]: string, number, boolean }` | Extra parameters to add to the endsession request body. | No |
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"bugs": {
"url": "https://github.com/damienbod/angular-auth-oidc-client/issues"
},
"version": "11.6.8",
"version": "11.6.9",
"scripts": {
"ng": "ng",
"build": "npm run build-lib",
Expand All @@ -35,6 +35,7 @@
"start-sample-code-flow-popup": "ng serve sample-code-flow-popup --ssl -o",
"start-sample-code-flow-http-config": "ng serve sample-code-flow-http-config --ssl -o",
"start-sample-code-flow-refresh-tokens": "ng serve sample-code-flow-refresh-tokens --ssl -o",
"start-sample-code-flow-auth0": "ng serve sample-code-flow-auth0 --ssl -o",
"start-sample-code-flow-par": "ng serve sample-code-flow-par --ssl -o",
"start-sample-code-flow-azure-b2c": "ng serve sample-code-flow-azure-b2c --ssl -o",
"start-sample-code-flow-azuread": "ng serve sample-code-flow-azuread --ssl -o",
Expand Down
2 changes: 1 addition & 1 deletion projects/angular-auth-oidc-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"authorization"
],
"license": "MIT",
"version": "11.6.8",
"version": "11.6.9",
"description": "Angular Lib for OpenID Connect & OAuth2",
"schematics": "./schematics/collection.json"
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,24 @@ export class PeriodicallyTokenCheckService {

this.flowsDataService.setSilentRenewRunning();

if (this.flowHelper.isCurrentFlowCodeFlowWithRefreshTokens()) {
// Retrieve Dynamically Set Custom Params for refresh body
const customParamsRefresh: { [key: string]: string | number | boolean } = this.storagePersistenceService.read(
'storageCustomParamsRefresh'
);
const { customParamsRefreshToken } = this.configurationProvider.getOpenIDConfiguration();

const mergedParams = { ...customParamsRefresh, ...customParamsRefreshToken };

// Refresh Session using Refresh tokens
return this.refreshSessionRefreshTokenService.refreshSessionWithRefreshTokens(mergedParams);
}

// Retrieve Dynamically Set Custom Params
const customParams: { [key: string]: string | number | boolean } = this.storagePersistenceService.read(
'storageCustomRequestParams'
);

if (this.flowHelper.isCurrentFlowCodeFlowWithRefreshTokens()) {
// Refresh Session using Refresh tokens
return this.refreshSessionRefreshTokenService.refreshSessionWithRefreshTokens(customParams);
}

return this.refreshSessionIframeService.refreshSessionWithIframe(customParams);
})
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { CallbackContext } from '../flows/callback-context';
import { FlowsService } from '../flows/flows.service';
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
import { LoggerService } from '../logging/logger.service';
import { IntervallService } from './intervall.service';
import { CallbackContext } from '../flows/callback-context';

@Injectable({ providedIn: 'root' })
export class RefreshSessionRefreshTokenService {
Expand All @@ -16,10 +16,10 @@ export class RefreshSessionRefreshTokenService {
private intervalService: IntervallService
) {}

refreshSessionWithRefreshTokens(customParams?: { [key: string]: string | number | boolean }): Observable<CallbackContext> {
refreshSessionWithRefreshTokens(customParamsRefresh?: { [key: string]: string | number | boolean }): Observable<CallbackContext> {
this.loggerService.logDebug('BEGIN refresh session Authorize');

return this.flowsService.processRefreshToken(customParams).pipe(
return this.flowsService.processRefreshToken(customParamsRefresh).pipe(
catchError((error) => {
this.intervalService.stopPeriodicallTokenCheck();
this.resetAuthDataService.resetAuthorizationData();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { map, mergeMap, retryWhen, switchMap, take, timeout } from 'rxjs/operato
import { AuthStateService } from '../authState/auth-state.service';
import { AuthWellKnownService } from '../config/auth-well-known.service';
import { ConfigurationProvider } from '../config/config.provider';
import { CallbackContext } from '../flows/callback-context';
import { FlowsDataService } from '../flows/flows-data.service';
import { RefreshSessionIframeService } from '../iframe/refresh-session-iframe.service';
import { SilentRenewService } from '../iframe/silent-renew.service';
import { LoggerService } from '../logging/logger.service';
import { TokenResponse } from '../tokens/token-response';
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
import { RefreshSessionRefreshTokenService } from './refresh-session-refresh-token.service';
import { TokenResponse } from '../tokens/token-response';
import { CallbackContext } from '../flows/callback-context';

export const MAX_RETRY_ATTEMPTS = 3;
@Injectable({ providedIn: 'root' })
Expand All @@ -28,9 +28,11 @@ export class RefreshSessionService {
private refreshSessionRefreshTokenService: RefreshSessionRefreshTokenService
) {}

forceRefreshSession(customParams?: { [key: string]: string | number | boolean }): Observable<TokenResponse | null> {
forceRefreshSession(extraCustomParams?: { [key: string]: string | number | boolean }): Observable<TokenResponse | null> {
if (this.flowHelper.isCurrentFlowCodeFlowWithRefreshTokens()) {
return this.startRefreshSession(customParams).pipe(
const { customParamsRefreshToken } = this.configurationProvider.getOpenIDConfiguration();
const mergedParams = { ...extraCustomParams, ...customParamsRefreshToken };
return this.startRefreshSession(mergedParams).pipe(
map(() => {
const isAuthenticated = this.authStateService.areAuthStorageTokensValid();
if (isAuthenticated) {
Expand All @@ -49,7 +51,7 @@ export class RefreshSessionService {
const timeOutTime = silentRenewTimeoutInSeconds * 1000;

return forkJoin([
this.startRefreshSession(customParams),
this.startRefreshSession(extraCustomParams),
this.silentRenewService.refreshSessionWithIFrameCompleted$.pipe(take(1)),
]).pipe(
timeout(timeOutTime),
Expand All @@ -68,7 +70,9 @@ export class RefreshSessionService {
);
}

private startRefreshSession(customParams?: { [key: string]: string | number | boolean }): Observable<boolean | CallbackContext | null> {
private startRefreshSession(extraCustomParams?: {
[key: string]: string | number | boolean;
}): Observable<boolean | CallbackContext | null> {
const isSilentRenewRunning = this.flowsDataService.isSilentRenewRunning();
this.loggerService.logDebug(`Checking: silentRenewRunning: ${isSilentRenewRunning}`);
const shouldBeExecuted = !isSilentRenewRunning;
Expand All @@ -90,10 +94,10 @@ export class RefreshSessionService {

if (this.flowHelper.isCurrentFlowCodeFlowWithRefreshTokens()) {
// Refresh Session using Refresh tokens
return this.refreshSessionRefreshTokenService.refreshSessionWithRefreshTokens(customParams);
return this.refreshSessionRefreshTokenService.refreshSessionWithRefreshTokens(extraCustomParams);
}

return this.refreshSessionIframeService.refreshSessionWithIframe(customParams);
return this.refreshSessionIframeService.refreshSessionWithIframe(extraCustomParams);
})
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ describe('ConfigurationProviderTests', () => {
disableIatOffsetValidation: false,
storage: sessionStorage,
customParams: {},
customParamsRefreshToken: {},
customParamsEndSession: {},
eagerLoadAuthWellKnownEndpoints: true,
disableRefreshIdTokenAuthTimeValidation: false,
tokenRefreshInSeconds: 4,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export const DEFAULT_CONFIG: OpenIdConfiguration = {
disableIatOffsetValidation: false,
storage: typeof Storage !== 'undefined' ? sessionStorage : null,
customParams: {},
customParamsRefreshToken: {},
customParamsEndSession: {},
eagerLoadAuthWellKnownEndpoints: true,
disableRefreshIdTokenAuthTimeValidation: false,
tokenRefreshInSeconds: 4,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,13 @@ export interface OpenIdConfiguration {
storage?: any;
/** Extra parameters to add to the authorization URL request */
customParams?: { [key: string]: string | number | boolean };

/** Extra parameters to add to the refresh token request body */
customParamsRefreshToken?: { [key: string]: string | number | boolean };

/** Extra parameters to add to the authorization EndSession request */
customParamsEndSession?: { [key: string]: string | number | boolean };

/** Extra parameters to add to the token URL request */
customTokenParams?: { [key: string]: string | number | boolean };
/** Denotes if the AuthWellKnownEndpoints should be loaded at startup or when the user calls the authorize method. */
Expand Down
Loading