From 717f8b68fb65793f1ae3c3893041d8339af13633 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 7 Aug 2020 18:25:36 +0300 Subject: [PATCH 01/17] test: update initial-utils.spec --- npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts index c81ce081b2..1657f418e3 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts @@ -32,6 +32,7 @@ describe('InitialUtils', () => { const injector = spectator.inject(Injector); const injectorSpy = jest.spyOn(injector, 'get'); const store = spectator.inject(Store); + const oAuthService = spectator.inject(OAuthService); const dispatchSpy = jest.spyOn(store, 'dispatch'); const parseTenantFromUrlSpy = jest.spyOn(multiTenancyUtils, 'parseTenantFromUrl'); const getRemoteEnvSpy = jest.spyOn(environmentUtils, 'getRemoteEnv'); @@ -40,6 +41,7 @@ describe('InitialUtils', () => { injectorSpy.mockReturnValueOnce(store); injectorSpy.mockReturnValueOnce({ skipGetAppConfiguration: false }); + injectorSpy.mockReturnValueOnce(oAuthService); injectorSpy.mockReturnValueOnce({ hasValidAccessToken: () => false }); dispatchSpy.mockReturnValue(of('test')); From bbad96fdc2f2e4864e3f2dbb2c8aaa257d367867 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 7 Aug 2020 18:28:16 +0300 Subject: [PATCH 02/17] feat: create authentication-flow.guard --- .../account/src/lib/account-routing.module.ts | 2 ++ .../packages/account/src/lib/account.module.ts | 2 ++ .../src/lib/guards/authentication-flow.guard.ts | 17 +++++++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts diff --git a/npm/ng-packs/packages/account/src/lib/account-routing.module.ts b/npm/ng-packs/packages/account/src/lib/account-routing.module.ts index 2225e7c592..a77ea4134b 100644 --- a/npm/ng-packs/packages/account/src/lib/account-routing.module.ts +++ b/npm/ng-packs/packages/account/src/lib/account-routing.module.ts @@ -10,12 +10,14 @@ import { LoginComponent } from './components/login/login.component'; import { ManageProfileComponent } from './components/manage-profile/manage-profile.component'; import { RegisterComponent } from './components/register/register.component'; import { eAccountComponents } from './enums/components'; +import { AuthenticationFlowGuard } from './guards/authentication-flow.guard'; const routes: Routes = [ { path: '', pathMatch: 'full', redirectTo: 'login' }, { path: '', component: DynamicLayoutComponent, + canActivate: [AuthenticationFlowGuard], children: [ { path: 'login', diff --git a/npm/ng-packs/packages/account/src/lib/account.module.ts b/npm/ng-packs/packages/account/src/lib/account.module.ts index 0ee605a75a..7f2151dfd1 100644 --- a/npm/ng-packs/packages/account/src/lib/account.module.ts +++ b/npm/ng-packs/packages/account/src/lib/account.module.ts @@ -14,6 +14,7 @@ import { TenantBoxComponent } from './components/tenant-box/tenant-box.component import { Options } from './models/options'; import { ACCOUNT_OPTIONS } from './tokens/options.token'; import { accountOptionsFactory } from './utils/factory-utils'; +import { AuthenticationFlowGuard } from './guards/authentication-flow.guard'; @NgModule({ declarations: [ @@ -39,6 +40,7 @@ export class AccountModule { return { ngModule: AccountModule, providers: [ + AuthenticationFlowGuard, { provide: ACCOUNT_OPTIONS, useValue: options }, { provide: 'ACCOUNT_OPTIONS', diff --git a/npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts b/npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts new file mode 100644 index 0000000000..bd22318acd --- /dev/null +++ b/npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@angular/core'; +import { CanActivate } from '@angular/router'; +import { OAuthService } from 'angular-oauth2-oidc'; + +@Injectable() +export class AuthenticationFlowGuard implements CanActivate { + constructor(private oauthService: OAuthService) {} + + canActivate() { + if (this.oauthService.responseType === 'code') { + this.oauthService.initCodeFlow(); + return false; + } + + return true; + } +} From e049d02ef4d1fda603309d30c3ab2d4ee20700c2 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 7 Aug 2020 18:30:08 +0300 Subject: [PATCH 03/17] feat: change the oauth configuration according to code flow --- .../dev-app/src/environments/environment.prod.ts | 11 ++++++----- .../apps/dev-app/src/environments/environment.ts | 11 ++++++----- .../angular/src/environments/environment.prod.ts | 14 ++++++-------- .../app/angular/src/environments/environment.ts | 15 ++++++--------- 4 files changed, 24 insertions(+), 27 deletions(-) diff --git a/npm/ng-packs/apps/dev-app/src/environments/environment.prod.ts b/npm/ng-packs/apps/dev-app/src/environments/environment.prod.ts index 21e1302773..70af33346f 100644 --- a/npm/ng-packs/apps/dev-app/src/environments/environment.prod.ts +++ b/npm/ng-packs/apps/dev-app/src/environments/environment.prod.ts @@ -1,20 +1,21 @@ import { Config } from '@abp/ng.core'; +const baseUrl = 'http://localhost:4200'; + export const environment = { production: true, hmr: false, application: { - baseUrl: 'http://localhost:4200/', + baseUrl, name: 'MyProjectName', logoUrl: '', }, oAuthConfig: { issuer: 'https://localhost:44305', + redirectUri: baseUrl, clientId: 'MyProjectName_App', - dummyClientSecret: '1q2w3e*', - scope: 'MyProjectName', - oidc: false, - requireHttps: true, + responseType: 'code', + scope: 'offline_access MyProjectName', }, apis: { default: { diff --git a/npm/ng-packs/apps/dev-app/src/environments/environment.ts b/npm/ng-packs/apps/dev-app/src/environments/environment.ts index 8cae243d46..2bf42cf7dc 100644 --- a/npm/ng-packs/apps/dev-app/src/environments/environment.ts +++ b/npm/ng-packs/apps/dev-app/src/environments/environment.ts @@ -1,20 +1,21 @@ import { Config } from '@abp/ng.core'; +const baseUrl = 'http://localhost:4200'; + export const environment = { production: false, hmr: false, application: { - baseUrl: 'http://localhost:4200/', + baseUrl, name: 'MyProjectName', logoUrl: '', }, oAuthConfig: { issuer: 'https://localhost:44305', + redirectUri: baseUrl, clientId: 'MyProjectName_App', - dummyClientSecret: '1q2w3e*', - scope: 'MyProjectName', - oidc: false, - requireHttps: true, + responseType: 'code', + scope: 'offline_access MyProjectName', }, apis: { default: { diff --git a/templates/app/angular/src/environments/environment.prod.ts b/templates/app/angular/src/environments/environment.prod.ts index cfe0401dee..719dd1fe53 100644 --- a/templates/app/angular/src/environments/environment.prod.ts +++ b/templates/app/angular/src/environments/environment.prod.ts @@ -1,26 +1,24 @@ import { Config } from '@abp/ng.core'; +const baseUrl = 'http://localhost:4200'; + export const environment = { production: true, application: { - baseUrl: 'http://localhost:4200/', + baseUrl, name: 'MyProjectName', logoUrl: '', }, oAuthConfig: { issuer: 'https://localhost:44305', + redirectUri: baseUrl, clientId: 'MyProjectName_App', - dummyClientSecret: '1q2w3e*', - scope: 'MyProjectName', - oidc: false, - requireHttps: true, + responseType: 'code', + scope: 'offline_access MyProjectName', }, apis: { default: { url: 'https://localhost:44305', }, }, - localization: { - defaultResourceName: 'MyProjectName', - }, } as Config.Environment; diff --git a/templates/app/angular/src/environments/environment.ts b/templates/app/angular/src/environments/environment.ts index 2039e8a2dc..cb0be073c2 100644 --- a/templates/app/angular/src/environments/environment.ts +++ b/templates/app/angular/src/environments/environment.ts @@ -1,27 +1,24 @@ import { Config } from '@abp/ng.core'; +const baseUrl = 'http://localhost:4200'; + export const environment = { production: false, application: { - baseUrl: 'http://localhost:4200/', + baseUrl, name: 'MyProjectName', logoUrl: '', }, oAuthConfig: { issuer: 'https://localhost:44305', + redirectUri: baseUrl, clientId: 'MyProjectName_App', - dummyClientSecret: '1q2w3e*', - scope: 'MyProjectName', - showDebugInformation: true, - oidc: false, - requireHttps: true, + responseType: 'code', + scope: 'offline_access MyProjectName', }, apis: { default: { url: 'https://localhost:44305', }, }, - localization: { - defaultResourceName: 'MyProjectName', - }, } as Config.Environment; From f14396e7d8243266f0110de367a23fa15175ba05 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 7 Aug 2020 18:30:32 +0300 Subject: [PATCH 04/17] feat: call setupAutomaticSilentRefresh on app initialization --- .../core/src/lib/handlers/oauth-configuration.handler.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/npm/ng-packs/packages/core/src/lib/handlers/oauth-configuration.handler.ts b/npm/ng-packs/packages/core/src/lib/handlers/oauth-configuration.handler.ts index d9c6806900..b3f1b62a23 100644 --- a/npm/ng-packs/packages/core/src/lib/handlers/oauth-configuration.handler.ts +++ b/npm/ng-packs/packages/core/src/lib/handlers/oauth-configuration.handler.ts @@ -17,6 +17,9 @@ export class OAuthConfigurationHandler { @Inject(CORE_OPTIONS) private options: ABP.Root, ) { this.oAuthService.configure(this.options.environment.oAuthConfig); + if (this.oAuthService.responseType === 'code') { + this.oAuthService.setupAutomaticSilentRefresh(); + } this.listenToSetEnvironment(); } From 014a2fc1670d75a9745d32e89c49a48cca897480 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 7 Aug 2020 18:30:54 +0300 Subject: [PATCH 05/17] feat: add an if condition to auth service for code flow --- .../packages/core/src/lib/services/auth.service.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/services/auth.service.ts b/npm/ng-packs/packages/core/src/lib/services/auth.service.ts index 3a343fd2cb..063b1bc74f 100644 --- a/npm/ng-packs/packages/core/src/lib/services/auth.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/auth.service.ts @@ -3,13 +3,13 @@ import { Inject, Injectable, Optional } from '@angular/core'; import { Navigate } from '@ngxs/router-plugin'; import { Store } from '@ngxs/store'; import { OAuthService } from 'angular-oauth2-oidc'; -import { from, Observable } from 'rxjs'; -import { switchMap, tap, take } from 'rxjs/operators'; +import { from, Observable, of } from 'rxjs'; +import { switchMap, take, tap } from 'rxjs/operators'; import snq from 'snq'; import { GetAppConfiguration } from '../actions/config.actions'; +import { ConfigState } from '../states/config.state'; import { SessionState } from '../states/session.state'; import { RestService } from './rest.service'; -import { ConfigState } from '../states/config.state'; @Injectable({ providedIn: 'root', @@ -48,6 +48,11 @@ export class AuthService { logout(): Observable { const issuer = this.store.selectSnapshot(ConfigState.getDeep('environment.oAuthConfig.issuer')); + if (this.oAuthService.responseType === 'code') { + this.oAuthService.logOut(); + return of(null); + } + return this.rest .request( { @@ -59,7 +64,7 @@ export class AuthService { ) .pipe( switchMap(() => { - this.oAuthService.logOut(true); + this.oAuthService.logOut(); return this.store.dispatch(new GetAppConfiguration()); }), ); From 5fa82a25d7e9be9d00cd2ead99edd1a4bbc101d1 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 7 Aug 2020 18:31:12 +0300 Subject: [PATCH 06/17] feat: call loadDiscoveryDocumentAndTryLogin method in initial-utils --- npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts index a79077b89d..b1f9701343 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts @@ -14,6 +14,11 @@ export function getInitialData(injector: Injector) { const fn = async () => { const store: Store = injector.get(Store); const options = injector.get(CORE_OPTIONS) as ABP.Root; + const oAuthService = injector.get(OAuthService); + + if (oAuthService.responseType === 'code') { + await oAuthService.loadDiscoveryDocumentAndTryLogin(); + } await getRemoteEnv(injector, options.environment); await parseTenantFromUrl(injector); From 577386600b0d60f42aba141109158e552f30265b Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 7 Aug 2020 18:31:25 +0300 Subject: [PATCH 07/17] chore: updata angular-oauth2-oidc version --- npm/ng-packs/package.json | 2 +- npm/ng-packs/packages/core/package.json | 2 +- npm/ng-packs/yarn.lock | 102 +++++++++++++++--------- 3 files changed, 65 insertions(+), 41 deletions(-) diff --git a/npm/ng-packs/package.json b/npm/ng-packs/package.json index fa58409270..658c2dac67 100644 --- a/npm/ng-packs/package.json +++ b/npm/ng-packs/package.json @@ -60,7 +60,7 @@ "@swimlane/ngx-datatable": "^17.0.0", "@types/jest": "^25.2.3", "@types/node": "^12.11.1", - "angular-oauth2-oidc": "^9.2.2", + "angular-oauth2-oidc": "^10.0.3", "bootstrap": "^4.5.0", "chart.js": "^2.9.3", "codelyzer": "^5.1.2", diff --git a/npm/ng-packs/packages/core/package.json b/npm/ng-packs/packages/core/package.json index 4053f0fcc4..4ccafae3a0 100644 --- a/npm/ng-packs/packages/core/package.json +++ b/npm/ng-packs/packages/core/package.json @@ -12,7 +12,7 @@ "@ngxs/router-plugin": "^3.6.2", "@ngxs/storage-plugin": "^3.6.2", "@ngxs/store": "^3.6.2", - "angular-oauth2-oidc": "^9.2.2", + "angular-oauth2-oidc": "^10.0.0", "just-clone": "^3.1.0", "just-compare": "^1.3.0", "snq": "^1.0.3", diff --git a/npm/ng-packs/yarn.lock b/npm/ng-packs/yarn.lock index 56434e11b2..850b85c248 100644 --- a/npm/ng-packs/yarn.lock +++ b/npm/ng-packs/yarn.lock @@ -715,9 +715,9 @@ js-tokens "^4.0.0" "@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.11.1", "@babel/parser@^7.8.3", "@babel/parser@^7.8.6", "@babel/parser@^7.9.6": - version "7.11.1" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.1.tgz#d91a387990b21e5d20047b336bb19b0553f02ff5" - integrity sha512-u9QMIRdKVF7hfEkb3nu2LgZDIzCQPv+yHD9Eg6ruoJLjkrQ9fFz4IBSlF/9XwoNri9+2F1IY+dYuOfZrXq8t3w== + version "7.11.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.2.tgz#0882ab8a455df3065ea2dcb4c753b2460a24bead" + integrity sha512-Vuj/+7vLo6l1Vi7uuO+1ngCDNeVmNbTngcJFKCR/oEtz8tKz0CJxZEGmPt9KcIloZhOZ3Zit6xbpXT2MDlS9Vw== "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.10.5" @@ -1224,9 +1224,9 @@ regenerator-runtime "^0.13.4" "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4": - version "7.11.1" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.1.tgz#087afc57e7bf1073e792fe54f8fb3cfa752f9230" - integrity sha512-nH5y8fLvVl3HAb+ezbgcgwrH8QbClWo8xzkOu7+oyqngo3EVorwpWJQaqXPjGRpfj7mQvsJCl/S8knkfkPWqrw== + version "7.11.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" + integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== dependencies: regenerator-runtime "^0.13.4" @@ -2736,9 +2736,9 @@ integrity sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g== "@types/node@^12.11.1": - version "12.12.53" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.53.tgz#be0d375933c3d15ef2380dafb3b0350ea7021129" - integrity sha512-51MYTDTyCziHb70wtGNFRwB4l+5JNvdqzFSkbDvpbftEgVUBEE+T5f7pROhWMp/fxp07oNIEQZd5bbfAH22ohQ== + version "12.12.54" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.54.tgz#a4b58d8df3a4677b6c08bfbc94b7ad7a7a5f82d1" + integrity sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w== "@types/node@^8.0.31": version "8.10.62" @@ -2814,9 +2814,9 @@ integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw== "@types/yargs@^13.0.0": - version "13.0.9" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.9.tgz#44028e974343c7afcf3960f1a2b1099c39a7b5e1" - integrity sha512-xrvhZ4DZewMDhoH1utLtOAwYQy60eYFoXeje30TzM3VOvQlBwQaEpKFq5m34k1wOw2AKIi2pwtiAjdmhvlBUzg== + version "13.0.10" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.10.tgz#e77bf3fc73c781d48c2eb541f87c453e321e5f4b" + integrity sha512-MU10TSgzNABgdzKvQVW1nuuT+sgBMWeXNc3XOs5YXV5SDAK+PPja2eUuBNB9iqElu03xyEDqlnGw0jgl4nbqGQ== dependencies: "@types/yargs-parser" "*" @@ -3120,6 +3120,20 @@ alphanum-sort@^1.0.0: resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= +angular-oauth2-oidc-jwks@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/angular-oauth2-oidc-jwks/-/angular-oauth2-oidc-jwks-9.0.0.tgz#f11e4e561ff423928ab63ca2cca84703a00ff85d" + integrity sha512-3hTJc7vEI/ka/nnliMcCQuDnszzL3AhGInBBbn96BO+ZOdvP/4PbEumUsDto2WRpPMPxD6HAmExwYeQWljcc5A== + dependencies: + jsrsasign "^8.0.12" + +angular-oauth2-oidc@^10.0.3: + version "10.0.3" + resolved "https://registry.yarnpkg.com/angular-oauth2-oidc/-/angular-oauth2-oidc-10.0.3.tgz#612ef75c2e07b56592d2506f9618ee6a61857ad9" + integrity sha512-9wC8I3e3cN6rMBOlo5JB2y3Fd2erp8pJ67t4vEVzyPbnRG6BJ4rreSOznSL9zw/2SjhC9kRV2OfFie29CUCzEg== + dependencies: + tslib "^2.0.0" + angular-oauth2-oidc@^9.2.2: version "9.2.2" resolved "https://registry.yarnpkg.com/angular-oauth2-oidc/-/angular-oauth2-oidc-9.2.2.tgz#2b888337953a8773e0269b5ef1709f30316448f1" @@ -3678,9 +3692,9 @@ boolbase@^1.0.0, boolbase@~1.0.0: integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= bootstrap@^4.5.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.1.tgz#f7322c7dd3e6376d430efc0c3f57e4d8005eb5b2" - integrity sha512-bxUooHBSbvefnIZfjD0LE8nfdPKrtiFy2sgrxQwUZ0UpFzpjVbVMUxaGIoo9XWT4B2LG1HX6UQg0UMOakT0prQ== + version "4.5.2" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.2.tgz#a85c4eda59155f0d71186b6e6ad9b875813779ab" + integrity sha512-vlGn0bcySYl/iV+BGA544JkkZP5LB3jsmkeKLFQakCOwCM3AOk7VkldBz4jrzSe+Z0Ezn99NVXa1o45cQY4R6A== boxen@^4.2.0: version "4.2.0" @@ -3806,14 +3820,14 @@ browserify-zlib@^0.2.0: pako "~1.0.5" browserslist@^4.0.0, browserslist@^4.11.1, browserslist@^4.12.0, browserslist@^4.7.0, browserslist@^4.8.5, browserslist@^4.9.1: - version "4.13.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.13.0.tgz#42556cba011e1b0a2775b611cba6a8eca18e940d" - integrity sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ== + version "4.14.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.0.tgz#2908951abfe4ec98737b72f34c3bcedc8d43b000" + integrity sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ== dependencies: - caniuse-lite "^1.0.30001093" - electron-to-chromium "^1.3.488" - escalade "^3.0.1" - node-releases "^1.1.58" + caniuse-lite "^1.0.30001111" + electron-to-chromium "^1.3.523" + escalade "^3.0.2" + node-releases "^1.1.60" browserstack@^1.5.1: version "1.6.0" @@ -4095,10 +4109,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001032, caniuse-lite@^1.0.30001061, caniuse-lite@^1.0.30001093, caniuse-lite@^1.0.30001109: - version "1.0.30001111" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001111.tgz#dd0ce822c70eb6c7c068e4a55c22e19ec1501298" - integrity sha512-xnDje2wchd/8mlJu8sXvWxOGvMgv+uT3iZ3bkIAynKOzToCssWCmkz/ZIkQBs/2pUB4uwnJKVORWQ31UkbVjOg== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001032, caniuse-lite@^1.0.30001061, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001111: + version "1.0.30001112" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001112.tgz#0fffc3b934ff56ff0548c37bc9dad7d882bcf672" + integrity sha512-J05RTQlqsatidif/38aN3PGULCLrg8OYQOlJUKbeYVzC2mGZkZLIztwRlB3MtrfLmawUmjFlNJvy/uhwniIe1Q== canonical-path@1.0.0: version "1.0.0" @@ -4182,9 +4196,9 @@ chartjs-color@^2.1.0: color-convert "^1.9.3" "chokidar@>=2.0.0 <4.0.0", chokidar@^3.0.0, chokidar@^3.0.2, chokidar@^3.2.1, chokidar@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.1.tgz#e905bdecf10eaa0a0b1db0c664481cc4cbc22ba1" - integrity sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g== + version "3.4.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" + integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -5675,10 +5689,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.488: - version "1.3.520" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.520.tgz#dfda0a14a4aed785cbddfdb505ea122f75978392" - integrity sha512-q6H9E1sXDCjRHP+X06vcP+N0ki8ZvYoRPZfKnDuiRX10WWXxEHzKFVf4O9rBFMpuPtR3M+2KAdJnugJoBBp3Rw== +electron-to-chromium@^1.3.523: + version "1.3.524" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.524.tgz#dd49646594466192de35956a5369bb20d616aa78" + integrity sha512-ZUvklIBkfXQyA6IeiEss1nfKRICcdB5afAGZAaPGaExdfrkpUu/WWVO+X7QpNnphaVMllXnAcvKnVPdyM+DCPQ== elliptic@^6.5.3: version "6.5.3" @@ -5848,7 +5862,7 @@ es6-symbol@^3.1.1, es6-symbol@~3.1.3: d "^1.0.1" ext "^1.1.2" -escalade@^3.0.1: +escalade@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4" integrity sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ== @@ -8449,6 +8463,11 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jsrsasign@^8.0.12: + version "8.0.23" + resolved "https://registry.yarnpkg.com/jsrsasign/-/jsrsasign-8.0.23.tgz#4427ed0bbbd809d65b8e5ac9d48ba5383b49ee0c" + integrity sha512-COwd/XmwaxBwf/6E3FO21DGK504KdjfNMYv6hVd2q6W6lzTeaL2UKQ0cIBw6SFMBCdaQl8fGUm4dHFt7Wmo9xw== + jszip@^3.1.3: version "3.5.0" resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.5.0.tgz#b4fd1f368245346658e781fec9675802489e15f6" @@ -9565,7 +9584,7 @@ node-notifier@^6.0.0: shellwords "^0.1.1" which "^1.3.1" -node-releases@^1.1.58: +node-releases@^1.1.60: version "1.1.60" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084" integrity sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA== @@ -13092,16 +13111,16 @@ ts-pnp@^1.1.6: integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== ts-toolbelt@^6.9.9: - version "6.14.0" - resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.14.0.tgz#6f1082c5f59b39ff5d71ff427207bb92ffca4534" - integrity sha512-/EihMSk7AQn1n1zad6765tZNr7OCxAP75nS/VGzcZlWLlDa2izLJZV7SJSNDweSKusKuTDyHZhKFyUZW6UUnqg== + version "6.15.0" + resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.15.0.tgz#e1806c4904f5dc819d8dd2c48e09ccc60bfb742f" + integrity sha512-WuXbnXmVgzAGdruH7jbYf4j/0Y4anfMOD0KUU8iw6/4SbzdQVpfso4BJ1Z/t7hKLN2++gWYIseaw/ciyWKLreQ== tsickle@^0.38.1: version "0.38.1" resolved "https://registry.yarnpkg.com/tsickle/-/tsickle-0.38.1.tgz#30762db759d40c435943093b6972c7f2efb384ef" integrity sha512-4xZfvC6+etRu6ivKCNqMOd1FqcY/m6JY3Y+yr5+Xw+i751ciwrWINi6x/3l1ekcODH9GZhlf0ny2LpzWxnjWYA== -tslib@2.0.0, tslib@^2.0.0: +tslib@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3" integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g== @@ -13111,6 +13130,11 @@ tslib@^1.10.0, tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== +tslib@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e" + integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ== + tslint@~6.1.0: version "6.1.3" resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904" From 8b3758d395801e78671b858830f18217e6ae045d Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 7 Aug 2020 18:32:58 +0300 Subject: [PATCH 08/17] chore: change redirecting to login method in home component --- .../apps/dev-app/src/app/home/home.component.html | 7 +------ npm/ng-packs/apps/dev-app/src/app/home/home.component.ts | 4 ++++ templates/app/angular/src/app/home/home.component.html | 8 +------- templates/app/angular/src/app/home/home.component.ts | 4 ++++ 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/npm/ng-packs/apps/dev-app/src/app/home/home.component.html b/npm/ng-packs/apps/dev-app/src/app/home/home.component.html index 2733150b71..ae3196c0c6 100644 --- a/npm/ng-packs/apps/dev-app/src/app/home/home.component.html +++ b/npm/ng-packs/apps/dev-app/src/app/home/home.component.html @@ -8,12 +8,7 @@ abp.io - {{ 'AbpIdentity::Login' | abpLocalization }} diff --git a/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts b/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts index a42b960493..9daacbabaf 100644 --- a/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts +++ b/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts @@ -11,4 +11,8 @@ export class HomeComponent { } constructor(private oAuthService: OAuthService) {} + + login() { + this.oAuthService.initCodeFlow(); + } } diff --git a/templates/app/angular/src/app/home/home.component.html b/templates/app/angular/src/app/home/home.component.html index f4d41daf4f..fc7a0a4183 100644 --- a/templates/app/angular/src/app/home/home.component.html +++ b/templates/app/angular/src/app/home/home.component.html @@ -8,13 +8,7 @@ abp.io - {{ 'AbpAccount::Login' | abpLocalization }} diff --git a/templates/app/angular/src/app/home/home.component.ts b/templates/app/angular/src/app/home/home.component.ts index a42b960493..9daacbabaf 100644 --- a/templates/app/angular/src/app/home/home.component.ts +++ b/templates/app/angular/src/app/home/home.component.ts @@ -11,4 +11,8 @@ export class HomeComponent { } constructor(private oAuthService: OAuthService) {} + + login() { + this.oAuthService.initCodeFlow(); + } } From 25e18b52a835303604a0cccd937aa496a789fc0f Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Mon, 10 Aug 2020 17:30:07 +0300 Subject: [PATCH 09/17] feat: create oauth strategy --- .../packages/core/src/lib/strategies/index.ts | 1 + .../core/src/lib/strategies/oauth.strategy.ts | 112 ++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 npm/ng-packs/packages/core/src/lib/strategies/oauth.strategy.ts diff --git a/npm/ng-packs/packages/core/src/lib/strategies/index.ts b/npm/ng-packs/packages/core/src/lib/strategies/index.ts index 2e621e7907..d2a56ad2a6 100644 --- a/npm/ng-packs/packages/core/src/lib/strategies/index.ts +++ b/npm/ng-packs/packages/core/src/lib/strategies/index.ts @@ -5,4 +5,5 @@ export * from './context.strategy'; export * from './cross-origin.strategy'; export * from './dom.strategy'; export * from './loading.strategy'; +export * from './oauth.strategy'; export * from './projection.strategy'; diff --git a/npm/ng-packs/packages/core/src/lib/strategies/oauth.strategy.ts b/npm/ng-packs/packages/core/src/lib/strategies/oauth.strategy.ts new file mode 100644 index 0000000000..b9f05d9021 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/strategies/oauth.strategy.ts @@ -0,0 +1,112 @@ +import { Injector } from '@angular/core'; +import { Store } from '@ngxs/store'; +import { AuthConfig, OAuthService, OAuthSuccessEvent } from 'angular-oauth2-oidc'; +import { ConfigState } from '../states/config.state'; +import { CORE_OPTIONS } from '../tokens/options.token'; +import { Router } from '@angular/router'; +import { Observable, of } from 'rxjs'; +import { RestService } from '../services/rest.service'; +import { switchMap } from 'rxjs/operators'; +import { GetAppConfiguration } from '../actions/config.actions'; + +export abstract class OAuthStrategy { + protected oAuthService: OAuthService; + protected oAuthConfig: AuthConfig; + abstract navigateToLogin(): void; + abstract canActivate(): boolean; + abstract logOut(): Observable; + + private catchError = err => { + // TODO: handle the error + }; + + constructor(protected injector: Injector) { + this.oAuthService = injector.get(OAuthService); + this.oAuthConfig = injector.get(CORE_OPTIONS).environment.oAuthConfig; + } + + async init(): Promise { + this.oAuthService.configure(this.oAuthConfig); + return this.oAuthService.loadDiscoveryDocument().catch(this.catchError); + } +} + +export class OAuthCodeFlowStrategy extends OAuthStrategy { + async init() { + return super + .init() + .then(() => this.oAuthService.tryLogin()) + .then(() => this.oAuthService.setupAutomaticSilentRefresh()); + } + + navigateToLogin() { + this.oAuthService.initCodeFlow(); + } + + canActivate() { + this.oAuthService.initCodeFlow(); + return false; + } + + logOut() { + this.oAuthService.logOut(); + return of(null); + } +} + +export class OAuthPasswordFlowStrategy extends OAuthStrategy { + navigateToLogin() { + const router = this.injector.get(Router); + router.navigateByUrl('/account/login'); + } + + canActivate() { + return true; + } + + logOut() { + const store = this.injector.get(Store); + const rest = this.injector.get(RestService); + + const issuer = store.selectSnapshot(ConfigState.getDeep('environment.oAuthConfig.issuer')); + return rest + .request( + { + method: 'GET', + url: '/api/account/logout', + }, + null, + issuer, + ) + .pipe( + switchMap(() => { + this.oAuthService.logOut(); + return store.dispatch(new GetAppConfiguration()); + }), + ); + } +} + +export const OAUTH_STRATEGY = { + async Init(injector: Injector) { + return getOAuthStrategy(injector).init(); + }, + NavigateToLogin(injector: Injector) { + return getOAuthStrategy(injector).navigateToLogin(); + }, + CanActivate(injector: Injector) { + return getOAuthStrategy(injector).canActivate(); + }, + LogOut(injector: Injector) { + return getOAuthStrategy(injector).logOut(); + }, +}; + +function getOAuthStrategy(injector: Injector) { + const codeFlow = + injector + .get(Store) + .selectSnapshot(ConfigState.getDeep('environment.oAuthConfig.responseType')) === 'code'; + + return codeFlow ? new OAuthCodeFlowStrategy(injector) : new OAuthPasswordFlowStrategy(injector); +} From a67c552393cf409ec887024a1f32b224a1f62d08 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Mon, 10 Aug 2020 17:30:34 +0300 Subject: [PATCH 10/17] feat: implement the oauth strategy --- .../dev-app/src/app/home/home.component.ts | 7 ++-- .../account/src/lib/account-routing.module.ts | 3 +- .../lib/guards/authentication-flow.guard.ts | 13 +++---- .../handlers/oauth-configuration.handler.ts | 5 --- .../core/src/lib/services/auth.service.ts | 36 +++++++------------ .../core/src/lib/utils/initial-utils.ts | 7 ++-- .../nav-items/current-user.component.ts | 8 ++--- .../angular/src/app/home/home.component.ts | 7 ++-- 8 files changed, 33 insertions(+), 53 deletions(-) diff --git a/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts b/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts index 9daacbabaf..720034d928 100644 --- a/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts +++ b/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts @@ -1,4 +1,5 @@ -import { Component } from '@angular/core'; +import { OAUTH_STRATEGY } from '@abp/ng.core'; +import { Component, Injector } from '@angular/core'; import { OAuthService } from 'angular-oauth2-oidc'; @Component({ @@ -10,9 +11,9 @@ export class HomeComponent { return this.oAuthService.hasValidAccessToken(); } - constructor(private oAuthService: OAuthService) {} + constructor(private oAuthService: OAuthService, private injector: Injector) {} login() { - this.oAuthService.initCodeFlow(); + OAUTH_STRATEGY.NavigateToLogin(this.injector); } } diff --git a/npm/ng-packs/packages/account/src/lib/account-routing.module.ts b/npm/ng-packs/packages/account/src/lib/account-routing.module.ts index a77ea4134b..6883921202 100644 --- a/npm/ng-packs/packages/account/src/lib/account-routing.module.ts +++ b/npm/ng-packs/packages/account/src/lib/account-routing.module.ts @@ -17,11 +17,11 @@ const routes: Routes = [ { path: '', component: DynamicLayoutComponent, - canActivate: [AuthenticationFlowGuard], children: [ { path: 'login', component: ReplaceableRouteContainerComponent, + canActivate: [AuthenticationFlowGuard], data: { replaceableComponent: { key: eAccountComponents.Login, @@ -32,6 +32,7 @@ const routes: Routes = [ { path: 'register', component: ReplaceableRouteContainerComponent, + canActivate: [AuthenticationFlowGuard], data: { replaceableComponent: { key: eAccountComponents.Register, diff --git a/npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts b/npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts index bd22318acd..f892916582 100644 --- a/npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts +++ b/npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts @@ -1,17 +1,12 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Injector } from '@angular/core'; import { CanActivate } from '@angular/router'; -import { OAuthService } from 'angular-oauth2-oidc'; +import { OAUTH_STRATEGY } from '@abp/ng.core'; @Injectable() export class AuthenticationFlowGuard implements CanActivate { - constructor(private oauthService: OAuthService) {} + constructor(private injector: Injector) {} canActivate() { - if (this.oauthService.responseType === 'code') { - this.oauthService.initCodeFlow(); - return false; - } - - return true; + return OAUTH_STRATEGY.CanActivate(this.injector); } } diff --git a/npm/ng-packs/packages/core/src/lib/handlers/oauth-configuration.handler.ts b/npm/ng-packs/packages/core/src/lib/handlers/oauth-configuration.handler.ts index b3f1b62a23..e0505d2f2d 100644 --- a/npm/ng-packs/packages/core/src/lib/handlers/oauth-configuration.handler.ts +++ b/npm/ng-packs/packages/core/src/lib/handlers/oauth-configuration.handler.ts @@ -16,11 +16,6 @@ export class OAuthConfigurationHandler { private oAuthService: OAuthService, @Inject(CORE_OPTIONS) private options: ABP.Root, ) { - this.oAuthService.configure(this.options.environment.oAuthConfig); - if (this.oAuthService.responseType === 'code') { - this.oAuthService.setupAutomaticSilentRefresh(); - } - this.listenToSetEnvironment(); } diff --git a/npm/ng-packs/packages/core/src/lib/services/auth.service.ts b/npm/ng-packs/packages/core/src/lib/services/auth.service.ts index 063b1bc74f..3d4bdb9a0a 100644 --- a/npm/ng-packs/packages/core/src/lib/services/auth.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/auth.service.ts @@ -1,14 +1,15 @@ import { HttpHeaders } from '@angular/common/http'; -import { Inject, Injectable, Optional } from '@angular/core'; +import { Inject, Injectable, Injector, Optional } from '@angular/core'; import { Navigate } from '@ngxs/router-plugin'; import { Store } from '@ngxs/store'; import { OAuthService } from 'angular-oauth2-oidc'; -import { from, Observable, of } from 'rxjs'; +import { from, Observable } from 'rxjs'; import { switchMap, take, tap } from 'rxjs/operators'; import snq from 'snq'; import { GetAppConfiguration } from '../actions/config.actions'; import { ConfigState } from '../states/config.state'; import { SessionState } from '../states/session.state'; +import { OAUTH_STRATEGY } from '../strategies/oauth.strategy'; import { RestService } from './rest.service'; @Injectable({ @@ -16,6 +17,7 @@ import { RestService } from './rest.service'; }) export class AuthService { constructor( + private injector: Injector, private rest: RestService, private oAuthService: OAuthService, private store: Store, @@ -45,28 +47,16 @@ export class AuthService { ); } - logout(): Observable { - const issuer = this.store.selectSnapshot(ConfigState.getDeep('environment.oAuthConfig.issuer')); - - if (this.oAuthService.responseType === 'code') { - this.oAuthService.logOut(); - return of(null); + /** + * @deprecated use LogOut prop of OAUTH_STRATEGY instead, will be deleted in v3.3 + */ + logout(): Observable { + if (!this.store.selectSnapshot(ConfigState.getDeep('environment.production'))) { + console.warn( + 'The logout method of AuthService is depracated. Use LogOut prop of OAUTH_STRATEGY instead.', + ); } - return this.rest - .request( - { - method: 'GET', - url: '/api/account/logout', - }, - null, - issuer, - ) - .pipe( - switchMap(() => { - this.oAuthService.logOut(); - return this.store.dispatch(new GetAppConfiguration()); - }), - ); + return OAUTH_STRATEGY.LogOut(this.injector); } } diff --git a/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts index b1f9701343..17d39ed2c0 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts @@ -9,19 +9,16 @@ import { ConfigState } from '../states/config.state'; import { CORE_OPTIONS } from '../tokens/options.token'; import { getRemoteEnv } from './environment-utils'; import { parseTenantFromUrl } from './multi-tenancy-utils'; +import { OAUTH_STRATEGY } from '../strategies/oauth.strategy'; export function getInitialData(injector: Injector) { const fn = async () => { const store: Store = injector.get(Store); const options = injector.get(CORE_OPTIONS) as ABP.Root; - const oAuthService = injector.get(OAuthService); - - if (oAuthService.responseType === 'code') { - await oAuthService.loadDiscoveryDocumentAndTryLogin(); - } await getRemoteEnv(injector, options.environment); await parseTenantFromUrl(injector); + await OAUTH_STRATEGY.Init(injector); if (options.skipGetAppConfiguration) return; diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts index 70238d3538..6969de8ced 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts @@ -1,5 +1,5 @@ -import { ApplicationConfiguration, AuthService, ConfigState } from '@abp/ng.core'; -import { Component, OnInit } from '@angular/core'; +import { ApplicationConfiguration, OAUTH_STRATEGY, ConfigState } from '@abp/ng.core'; +import { Component, OnInit, Injector } from '@angular/core'; import { Router } from '@angular/router'; import { Select } from '@ngxs/store'; import { Observable } from 'rxjs'; @@ -55,12 +55,12 @@ export class CurrentUserComponent implements OnInit { return window.innerWidth < 992; } - constructor(private authService: AuthService, private router: Router) {} + constructor(private injector: Injector, private router: Router) {} ngOnInit() {} logout() { - this.authService.logout().subscribe(() => { + OAUTH_STRATEGY.LogOut(this.injector).subscribe(() => { this.router.navigate(['/'], { state: { redirectUrl: this.router.url } }); }); } diff --git a/templates/app/angular/src/app/home/home.component.ts b/templates/app/angular/src/app/home/home.component.ts index 9daacbabaf..720034d928 100644 --- a/templates/app/angular/src/app/home/home.component.ts +++ b/templates/app/angular/src/app/home/home.component.ts @@ -1,4 +1,5 @@ -import { Component } from '@angular/core'; +import { OAUTH_STRATEGY } from '@abp/ng.core'; +import { Component, Injector } from '@angular/core'; import { OAuthService } from 'angular-oauth2-oidc'; @Component({ @@ -10,9 +11,9 @@ export class HomeComponent { return this.oAuthService.hasValidAccessToken(); } - constructor(private oAuthService: OAuthService) {} + constructor(private oAuthService: OAuthService, private injector: Injector) {} login() { - this.oAuthService.initCodeFlow(); + OAUTH_STRATEGY.NavigateToLogin(this.injector); } } From 8ed298365817686a032cd1fd6cac01977bba65c2 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Mon, 10 Aug 2020 18:01:36 +0300 Subject: [PATCH 11/17] test: fix getInitialData fn of initial-utils file test --- .../packages/core/src/lib/tests/initial-utils.spec.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts index 1657f418e3..e0074e936f 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts @@ -8,6 +8,7 @@ import { CORE_OPTIONS } from '../tokens/options.token'; import { checkAccessToken, getInitialData, localeInitializer } from '../utils'; import * as multiTenancyUtils from '../utils/multi-tenancy-utils'; import * as environmentUtils from '../utils/environment-utils'; +import { OAUTH_STRATEGY } from '../strategies/oauth.strategy'; @Component({ selector: 'abp-dummy', @@ -32,18 +33,18 @@ describe('InitialUtils', () => { const injector = spectator.inject(Injector); const injectorSpy = jest.spyOn(injector, 'get'); const store = spectator.inject(Store); - const oAuthService = spectator.inject(OAuthService); const dispatchSpy = jest.spyOn(store, 'dispatch'); const parseTenantFromUrlSpy = jest.spyOn(multiTenancyUtils, 'parseTenantFromUrl'); const getRemoteEnvSpy = jest.spyOn(environmentUtils, 'getRemoteEnv'); + const initOAuthSpy = jest.spyOn(OAUTH_STRATEGY, 'Init'); parseTenantFromUrlSpy.mockReturnValue(Promise.resolve()); getRemoteEnvSpy.mockReturnValue(Promise.resolve()); injectorSpy.mockReturnValueOnce(store); injectorSpy.mockReturnValueOnce({ skipGetAppConfiguration: false }); - injectorSpy.mockReturnValueOnce(oAuthService); injectorSpy.mockReturnValueOnce({ hasValidAccessToken: () => false }); dispatchSpy.mockReturnValue(of('test')); + initOAuthSpy.mockReturnValue(Promise.resolve()); expect(typeof getInitialData(injector)).toBe('function'); expect(await getInitialData(injector)()).toBe('test'); From f1240ef79a460c82aa4d8844515fedd703200f26 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 11 Aug 2020 10:46:08 +0300 Subject: [PATCH 12/17] chore: remove CoreModule from identity-routing.module & organize imports --- .../packages/identity/src/lib/identity-routing.module.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/npm/ng-packs/packages/identity/src/lib/identity-routing.module.ts b/npm/ng-packs/packages/identity/src/lib/identity-routing.module.ts index f7d5463fcd..27986ae0d7 100644 --- a/npm/ng-packs/packages/identity/src/lib/identity-routing.module.ts +++ b/npm/ng-packs/packages/identity/src/lib/identity-routing.module.ts @@ -2,12 +2,11 @@ import { AuthGuard, DynamicLayoutComponent, PermissionGuard, - CoreModule, - ReplaceableRouteContainerComponent, ReplaceableComponents, + ReplaceableRouteContainerComponent, } from '@abp/ng.core'; -import { NgModule, Type } from '@angular/core'; -import { RouterModule, Routes, Router, ActivatedRoute } from '@angular/router'; +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; import { RolesComponent } from './components/roles/roles.component'; import { UsersComponent } from './components/users/users.component'; import { eIdentityComponents } from './enums/components'; @@ -46,7 +45,7 @@ const routes: Routes = [ ]; @NgModule({ - imports: [RouterModule.forChild(routes), CoreModule], + imports: [RouterModule.forChild(routes)], exports: [RouterModule], }) export class IdentityRoutingModule {} From ad1107189e8e89c3c400d6741e06fde548d607dc Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 11 Aug 2020 11:06:37 +0300 Subject: [PATCH 13/17] chore: export the authentication guard --- npm/ng-packs/packages/account/src/lib/guards/index.ts | 1 + npm/ng-packs/packages/account/src/public-api.ts | 3 ++- .../packages/core/src/lib/strategies/oauth.strategy.ts | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 npm/ng-packs/packages/account/src/lib/guards/index.ts diff --git a/npm/ng-packs/packages/account/src/lib/guards/index.ts b/npm/ng-packs/packages/account/src/lib/guards/index.ts new file mode 100644 index 0000000000..382170b2b1 --- /dev/null +++ b/npm/ng-packs/packages/account/src/lib/guards/index.ts @@ -0,0 +1 @@ +export * from './authentication-flow.guard'; diff --git a/npm/ng-packs/packages/account/src/public-api.ts b/npm/ng-packs/packages/account/src/public-api.ts index 8d1ef3c43a..aebccb74cc 100644 --- a/npm/ng-packs/packages/account/src/public-api.ts +++ b/npm/ng-packs/packages/account/src/public-api.ts @@ -1,6 +1,7 @@ export * from './lib/account.module'; export * from './lib/components'; export * from './lib/enums'; -export * from './lib/tokens'; +export * from './lib/guards'; export * from './lib/models'; export * from './lib/services'; +export * from './lib/tokens'; diff --git a/npm/ng-packs/packages/core/src/lib/strategies/oauth.strategy.ts b/npm/ng-packs/packages/core/src/lib/strategies/oauth.strategy.ts index b9f05d9021..b01de5e936 100644 --- a/npm/ng-packs/packages/core/src/lib/strategies/oauth.strategy.ts +++ b/npm/ng-packs/packages/core/src/lib/strategies/oauth.strategy.ts @@ -25,7 +25,7 @@ export abstract class OAuthStrategy { this.oAuthConfig = injector.get(CORE_OPTIONS).environment.oAuthConfig; } - async init(): Promise { + async init(): Promise { this.oAuthService.configure(this.oAuthConfig); return this.oAuthService.loadDiscoveryDocument().catch(this.catchError); } From ed1c200bf4ef0c8ae3b16a9694a507313fa98852 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 11 Aug 2020 15:09:41 +0300 Subject: [PATCH 14/17] refactor: rename oauth strategty and improve it --- .../dev-app/src/app/home/home.component.ts | 8 +-- .../lib/guards/authentication-flow.guard.ts | 11 ++-- .../core/src/lib/services/auth.service.ts | 59 +++++++++++++---- ...auth.strategy.ts => auth-flow.strategy.ts} | 65 +++++++++---------- .../packages/core/src/lib/strategies/index.ts | 2 +- .../core/src/lib/utils/initial-utils.ts | 4 +- npm/ng-packs/yarn.lock | 12 ---- .../angular/src/app/home/home.component.ts | 8 +-- 8 files changed, 96 insertions(+), 73 deletions(-) rename npm/ng-packs/packages/core/src/lib/strategies/{oauth.strategy.ts => auth-flow.strategy.ts} (62%) diff --git a/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts b/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts index 720034d928..3790f8fe3f 100644 --- a/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts +++ b/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts @@ -1,5 +1,5 @@ -import { OAUTH_STRATEGY } from '@abp/ng.core'; -import { Component, Injector } from '@angular/core'; +import { AuthService } from '@abp/ng.core'; +import { Component } from '@angular/core'; import { OAuthService } from 'angular-oauth2-oidc'; @Component({ @@ -11,9 +11,9 @@ export class HomeComponent { return this.oAuthService.hasValidAccessToken(); } - constructor(private oAuthService: OAuthService, private injector: Injector) {} + constructor(private oAuthService: OAuthService, private authService: AuthService) {} login() { - OAUTH_STRATEGY.NavigateToLogin(this.injector); + this.authService.initLogin(); } } diff --git a/npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts b/npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts index f892916582..7cb719628e 100644 --- a/npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts +++ b/npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts @@ -1,12 +1,15 @@ -import { Injectable, Injector } from '@angular/core'; +import { AuthService } from '@abp/ng.core'; +import { Injectable } from '@angular/core'; import { CanActivate } from '@angular/router'; -import { OAUTH_STRATEGY } from '@abp/ng.core'; @Injectable() export class AuthenticationFlowGuard implements CanActivate { - constructor(private injector: Injector) {} + constructor(private authService: AuthService) {} canActivate() { - return OAUTH_STRATEGY.CanActivate(this.injector); + if (this.authService.isInternalAuth) return true; + + this.authService.initLogin(); + return false; } } diff --git a/npm/ng-packs/packages/core/src/lib/services/auth.service.ts b/npm/ng-packs/packages/core/src/lib/services/auth.service.ts index 3d4bdb9a0a..6502bc3a61 100644 --- a/npm/ng-packs/packages/core/src/lib/services/auth.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/auth.service.ts @@ -1,28 +1,62 @@ import { HttpHeaders } from '@angular/common/http'; import { Inject, Injectable, Injector, Optional } from '@angular/core'; import { Navigate } from '@ngxs/router-plugin'; -import { Store } from '@ngxs/store'; +import { Store, Actions, ofActionSuccessful } from '@ngxs/store'; import { OAuthService } from 'angular-oauth2-oidc'; import { from, Observable } from 'rxjs'; import { switchMap, take, tap } from 'rxjs/operators'; import snq from 'snq'; -import { GetAppConfiguration } from '../actions/config.actions'; +import { GetAppConfiguration, SetEnvironment } from '../actions/config.actions'; import { ConfigState } from '../states/config.state'; import { SessionState } from '../states/session.state'; -import { OAUTH_STRATEGY } from '../strategies/oauth.strategy'; import { RestService } from './rest.service'; +import { + AuthCodeFlowStrategy, + AuthPasswordFlowStrategy, + AUTH_FLOW_STRATEGY, +} from '../strategies/auth-flow.strategy'; @Injectable({ providedIn: 'root', }) export class AuthService { + private flow: string; + private strategy: AuthCodeFlowStrategy | AuthPasswordFlowStrategy; + + get isInternalAuth() { + return this.strategy.isInternalAuth; + } + constructor( + private actions: Actions, private injector: Injector, private rest: RestService, private oAuthService: OAuthService, private store: Store, @Optional() @Inject('ACCOUNT_OPTIONS') private options: any, - ) {} + ) { + this.setStrategy(); + this.listenToSetEnvironment(); + } + + private setStrategy = () => { + const flow = + this.store.selectSnapshot(ConfigState.getDeep('environment.oAuthConfig.responseType')) || + 'password'; + if (this.flow === flow) return; + + if (this.strategy) this.strategy.destroy(); + + this.flow = flow; + this.strategy = + this.flow === 'code' + ? AUTH_FLOW_STRATEGY.Code(this.injector) + : AUTH_FLOW_STRATEGY.Password(this.injector); + }; + + private listenToSetEnvironment() { + this.actions.pipe(ofActionSuccessful(SetEnvironment)).subscribe(this.setStrategy); + } login(username: string, password: string): Observable { const tenant = this.store.selectSnapshot(SessionState.getTenant); @@ -47,16 +81,15 @@ export class AuthService { ); } - /** - * @deprecated use LogOut prop of OAUTH_STRATEGY instead, will be deleted in v3.3 - */ + async init() { + return await this.strategy.init(); + } + logout(): Observable { - if (!this.store.selectSnapshot(ConfigState.getDeep('environment.production'))) { - console.warn( - 'The logout method of AuthService is depracated. Use LogOut prop of OAUTH_STRATEGY instead.', - ); - } + return this.strategy.logout(); + } - return OAUTH_STRATEGY.LogOut(this.injector); + initLogin() { + this.strategy.login(); } } diff --git a/npm/ng-packs/packages/core/src/lib/strategies/oauth.strategy.ts b/npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts similarity index 62% rename from npm/ng-packs/packages/core/src/lib/strategies/oauth.strategy.ts rename to npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts index b01de5e936..cf8f9c039a 100644 --- a/npm/ng-packs/packages/core/src/lib/strategies/oauth.strategy.ts +++ b/npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts @@ -1,6 +1,6 @@ import { Injector } from '@angular/core'; import { Store } from '@ngxs/store'; -import { AuthConfig, OAuthService, OAuthSuccessEvent } from 'angular-oauth2-oidc'; +import { AuthConfig, OAuthService } from 'angular-oauth2-oidc'; import { ConfigState } from '../states/config.state'; import { CORE_OPTIONS } from '../tokens/options.token'; import { Router } from '@angular/router'; @@ -9,12 +9,18 @@ import { RestService } from '../services/rest.service'; import { switchMap } from 'rxjs/operators'; import { GetAppConfiguration } from '../actions/config.actions'; -export abstract class OAuthStrategy { +export abstract class AuthFlowStrategy { + protected abstract _isInternalAuth: boolean; + get isInternalAuth(): boolean { + return this._isInternalAuth; + } + protected oAuthService: OAuthService; protected oAuthConfig: AuthConfig; - abstract navigateToLogin(): void; - abstract canActivate(): boolean; - abstract logOut(): Observable; + abstract checkIfInternalAuth(): boolean; + abstract login(): void; + abstract logout(): Observable; + abstract destroy(): void; private catchError = err => { // TODO: handle the error @@ -31,7 +37,9 @@ export abstract class OAuthStrategy { } } -export class OAuthCodeFlowStrategy extends OAuthStrategy { +export class AuthCodeFlowStrategy extends AuthFlowStrategy { + protected _isInternalAuth = false; + async init() { return super .init() @@ -39,32 +47,36 @@ export class OAuthCodeFlowStrategy extends OAuthStrategy { .then(() => this.oAuthService.setupAutomaticSilentRefresh()); } - navigateToLogin() { + login() { this.oAuthService.initCodeFlow(); } - canActivate() { + checkIfInternalAuth() { this.oAuthService.initCodeFlow(); return false; } - logOut() { + logout() { this.oAuthService.logOut(); return of(null); } + + destroy() {} } -export class OAuthPasswordFlowStrategy extends OAuthStrategy { - navigateToLogin() { +export class AuthPasswordFlowStrategy extends AuthFlowStrategy { + protected _isInternalAuth = true; + + login() { const router = this.injector.get(Router); router.navigateByUrl('/account/login'); } - canActivate() { + checkIfInternalAuth() { return true; } - logOut() { + logout() { const store = this.injector.get(Store); const rest = this.injector.get(RestService); @@ -85,28 +97,15 @@ export class OAuthPasswordFlowStrategy extends OAuthStrategy { }), ); } + + destroy() {} } -export const OAUTH_STRATEGY = { - async Init(injector: Injector) { - return getOAuthStrategy(injector).init(); +export const AUTH_FLOW_STRATEGY = { + Code(injector: Injector) { + return new AuthCodeFlowStrategy(injector); }, - NavigateToLogin(injector: Injector) { - return getOAuthStrategy(injector).navigateToLogin(); - }, - CanActivate(injector: Injector) { - return getOAuthStrategy(injector).canActivate(); - }, - LogOut(injector: Injector) { - return getOAuthStrategy(injector).logOut(); + Password(injector: Injector) { + return new AuthPasswordFlowStrategy(injector); }, }; - -function getOAuthStrategy(injector: Injector) { - const codeFlow = - injector - .get(Store) - .selectSnapshot(ConfigState.getDeep('environment.oAuthConfig.responseType')) === 'code'; - - return codeFlow ? new OAuthCodeFlowStrategy(injector) : new OAuthPasswordFlowStrategy(injector); -} diff --git a/npm/ng-packs/packages/core/src/lib/strategies/index.ts b/npm/ng-packs/packages/core/src/lib/strategies/index.ts index d2a56ad2a6..d71f952307 100644 --- a/npm/ng-packs/packages/core/src/lib/strategies/index.ts +++ b/npm/ng-packs/packages/core/src/lib/strategies/index.ts @@ -1,3 +1,4 @@ +export * from './auth-flow.strategy'; export * from './container.strategy'; export * from './content-security.strategy'; export * from './content.strategy'; @@ -5,5 +6,4 @@ export * from './context.strategy'; export * from './cross-origin.strategy'; export * from './dom.strategy'; export * from './loading.strategy'; -export * from './oauth.strategy'; export * from './projection.strategy'; diff --git a/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts index 17d39ed2c0..73e986493c 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts @@ -9,7 +9,7 @@ import { ConfigState } from '../states/config.state'; import { CORE_OPTIONS } from '../tokens/options.token'; import { getRemoteEnv } from './environment-utils'; import { parseTenantFromUrl } from './multi-tenancy-utils'; -import { OAUTH_STRATEGY } from '../strategies/oauth.strategy'; +import { AuthService } from '../services/auth.service'; export function getInitialData(injector: Injector) { const fn = async () => { @@ -18,7 +18,7 @@ export function getInitialData(injector: Injector) { await getRemoteEnv(injector, options.environment); await parseTenantFromUrl(injector); - await OAUTH_STRATEGY.Init(injector); + await injector.get(AuthService).init(); if (options.skipGetAppConfiguration) return; diff --git a/npm/ng-packs/yarn.lock b/npm/ng-packs/yarn.lock index 850b85c248..612ce7011d 100644 --- a/npm/ng-packs/yarn.lock +++ b/npm/ng-packs/yarn.lock @@ -3120,13 +3120,6 @@ alphanum-sort@^1.0.0: resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= -angular-oauth2-oidc-jwks@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/angular-oauth2-oidc-jwks/-/angular-oauth2-oidc-jwks-9.0.0.tgz#f11e4e561ff423928ab63ca2cca84703a00ff85d" - integrity sha512-3hTJc7vEI/ka/nnliMcCQuDnszzL3AhGInBBbn96BO+ZOdvP/4PbEumUsDto2WRpPMPxD6HAmExwYeQWljcc5A== - dependencies: - jsrsasign "^8.0.12" - angular-oauth2-oidc@^10.0.3: version "10.0.3" resolved "https://registry.yarnpkg.com/angular-oauth2-oidc/-/angular-oauth2-oidc-10.0.3.tgz#612ef75c2e07b56592d2506f9618ee6a61857ad9" @@ -8463,11 +8456,6 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -jsrsasign@^8.0.12: - version "8.0.23" - resolved "https://registry.yarnpkg.com/jsrsasign/-/jsrsasign-8.0.23.tgz#4427ed0bbbd809d65b8e5ac9d48ba5383b49ee0c" - integrity sha512-COwd/XmwaxBwf/6E3FO21DGK504KdjfNMYv6hVd2q6W6lzTeaL2UKQ0cIBw6SFMBCdaQl8fGUm4dHFt7Wmo9xw== - jszip@^3.1.3: version "3.5.0" resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.5.0.tgz#b4fd1f368245346658e781fec9675802489e15f6" diff --git a/templates/app/angular/src/app/home/home.component.ts b/templates/app/angular/src/app/home/home.component.ts index 720034d928..3790f8fe3f 100644 --- a/templates/app/angular/src/app/home/home.component.ts +++ b/templates/app/angular/src/app/home/home.component.ts @@ -1,5 +1,5 @@ -import { OAUTH_STRATEGY } from '@abp/ng.core'; -import { Component, Injector } from '@angular/core'; +import { AuthService } from '@abp/ng.core'; +import { Component } from '@angular/core'; import { OAuthService } from 'angular-oauth2-oidc'; @Component({ @@ -11,9 +11,9 @@ export class HomeComponent { return this.oAuthService.hasValidAccessToken(); } - constructor(private oAuthService: OAuthService, private injector: Injector) {} + constructor(private oAuthService: OAuthService, private authService: AuthService) {} login() { - OAUTH_STRATEGY.NavigateToLogin(this.injector); + this.authService.initLogin(); } } From ede9dc9b8cfcc3c3604068e2fb72b9e58f6dc42a Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 11 Aug 2020 15:13:56 +0300 Subject: [PATCH 15/17] test: fix testing error --- .../packages/core/src/lib/tests/initial-utils.spec.ts | 6 ++---- npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts index e0074e936f..07dfc84d67 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts @@ -6,9 +6,8 @@ import { of } from 'rxjs'; import { GetAppConfiguration } from '../actions'; import { CORE_OPTIONS } from '../tokens/options.token'; import { checkAccessToken, getInitialData, localeInitializer } from '../utils'; -import * as multiTenancyUtils from '../utils/multi-tenancy-utils'; import * as environmentUtils from '../utils/environment-utils'; -import { OAUTH_STRATEGY } from '../strategies/oauth.strategy'; +import * as multiTenancyUtils from '../utils/multi-tenancy-utils'; @Component({ selector: 'abp-dummy', @@ -36,15 +35,14 @@ describe('InitialUtils', () => { const dispatchSpy = jest.spyOn(store, 'dispatch'); const parseTenantFromUrlSpy = jest.spyOn(multiTenancyUtils, 'parseTenantFromUrl'); const getRemoteEnvSpy = jest.spyOn(environmentUtils, 'getRemoteEnv'); - const initOAuthSpy = jest.spyOn(OAUTH_STRATEGY, 'Init'); parseTenantFromUrlSpy.mockReturnValue(Promise.resolve()); getRemoteEnvSpy.mockReturnValue(Promise.resolve()); injectorSpy.mockReturnValueOnce(store); injectorSpy.mockReturnValueOnce({ skipGetAppConfiguration: false }); + injectorSpy.mockReturnValueOnce({ init: () => null }); injectorSpy.mockReturnValueOnce({ hasValidAccessToken: () => false }); dispatchSpy.mockReturnValue(of('test')); - initOAuthSpy.mockReturnValue(Promise.resolve()); expect(typeof getInitialData(injector)).toBe('function'); expect(await getInitialData(injector)()).toBe('test'); diff --git a/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts index 73e986493c..36e2c22bca 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts @@ -5,11 +5,11 @@ import { OAuthService } from 'angular-oauth2-oidc'; import { tap } from 'rxjs/operators'; import { GetAppConfiguration } from '../actions/config.actions'; import { ABP } from '../models/common'; +import { AuthService } from '../services/auth.service'; import { ConfigState } from '../states/config.state'; import { CORE_OPTIONS } from '../tokens/options.token'; import { getRemoteEnv } from './environment-utils'; import { parseTenantFromUrl } from './multi-tenancy-utils'; -import { AuthService } from '../services/auth.service'; export function getInitialData(injector: Injector) { const fn = async () => { From da1c0ad7938394f416efd353a6274e2a91c4e27e Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 11 Aug 2020 15:23:20 +0300 Subject: [PATCH 16/17] refactor: improve code quality --- .../packages/core/src/lib/services/auth.service.ts | 10 +++------- .../core/src/lib/strategies/auth-flow.strategy.ts | 9 +++------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/services/auth.service.ts b/npm/ng-packs/packages/core/src/lib/services/auth.service.ts index 6502bc3a61..6b86b580df 100644 --- a/npm/ng-packs/packages/core/src/lib/services/auth.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/auth.service.ts @@ -1,7 +1,7 @@ import { HttpHeaders } from '@angular/common/http'; import { Inject, Injectable, Injector, Optional } from '@angular/core'; import { Navigate } from '@ngxs/router-plugin'; -import { Store, Actions, ofActionSuccessful } from '@ngxs/store'; +import { Actions, ofActionSuccessful, Store } from '@ngxs/store'; import { OAuthService } from 'angular-oauth2-oidc'; import { from, Observable } from 'rxjs'; import { switchMap, take, tap } from 'rxjs/operators'; @@ -9,19 +9,15 @@ import snq from 'snq'; import { GetAppConfiguration, SetEnvironment } from '../actions/config.actions'; import { ConfigState } from '../states/config.state'; import { SessionState } from '../states/session.state'; +import { AuthFlowStrategy, AUTH_FLOW_STRATEGY } from '../strategies/auth-flow.strategy'; import { RestService } from './rest.service'; -import { - AuthCodeFlowStrategy, - AuthPasswordFlowStrategy, - AUTH_FLOW_STRATEGY, -} from '../strategies/auth-flow.strategy'; @Injectable({ providedIn: 'root', }) export class AuthService { private flow: string; - private strategy: AuthCodeFlowStrategy | AuthPasswordFlowStrategy; + private strategy: AuthFlowStrategy; get isInternalAuth() { return this.strategy.isInternalAuth; diff --git a/npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts b/npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts index cf8f9c039a..b7aa5601e2 100644 --- a/npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts +++ b/npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts @@ -10,10 +10,7 @@ import { switchMap } from 'rxjs/operators'; import { GetAppConfiguration } from '../actions/config.actions'; export abstract class AuthFlowStrategy { - protected abstract _isInternalAuth: boolean; - get isInternalAuth(): boolean { - return this._isInternalAuth; - } + abstract readonly isInternalAuth: boolean; protected oAuthService: OAuthService; protected oAuthConfig: AuthConfig; @@ -38,7 +35,7 @@ export abstract class AuthFlowStrategy { } export class AuthCodeFlowStrategy extends AuthFlowStrategy { - protected _isInternalAuth = false; + readonly isInternalAuth = false; async init() { return super @@ -65,7 +62,7 @@ export class AuthCodeFlowStrategy extends AuthFlowStrategy { } export class AuthPasswordFlowStrategy extends AuthFlowStrategy { - protected _isInternalAuth = true; + readonly isInternalAuth = true; login() { const router = this.injector.get(Router); From dec9694549e5d3e71282cc131a5770ba4bc7485e Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 11 Aug 2020 15:35:02 +0300 Subject: [PATCH 17/17] fix: remove a constant that is not found --- npm/ng-packs/package.json | 2 +- .../lib/components/nav-items/current-user.component.ts | 8 ++++---- npm/ng-packs/packages/theme-shared/package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/npm/ng-packs/package.json b/npm/ng-packs/package.json index 658c2dac67..0951ad2d1c 100644 --- a/npm/ng-packs/package.json +++ b/npm/ng-packs/package.json @@ -51,7 +51,7 @@ "@fortawesome/fontawesome-free": "^5.13.0", "@ng-bootstrap/ng-bootstrap": "^6.1.0", "@ngneat/spectator": "^5.11.0", - "@ngx-validate/core": "^0.0.10", + "@ngx-validate/core": "^0.0.11", "@ngxs/devtools-plugin": "^3.6.2", "@ngxs/logger-plugin": "^3.6.2", "@ngxs/router-plugin": "^3.6.2", diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts index 6969de8ced..6f362b0ee8 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts @@ -1,5 +1,5 @@ -import { ApplicationConfiguration, OAUTH_STRATEGY, ConfigState } from '@abp/ng.core'; -import { Component, OnInit, Injector } from '@angular/core'; +import { ApplicationConfiguration, ConfigState, AuthService } from '@abp/ng.core'; +import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { Select } from '@ngxs/store'; import { Observable } from 'rxjs'; @@ -55,12 +55,12 @@ export class CurrentUserComponent implements OnInit { return window.innerWidth < 992; } - constructor(private injector: Injector, private router: Router) {} + constructor(private authService: AuthService, private router: Router) {} ngOnInit() {} logout() { - OAUTH_STRATEGY.LogOut(this.injector).subscribe(() => { + this.authService.logout().subscribe(() => { this.router.navigate(['/'], { state: { redirectUrl: this.router.url } }); }); } diff --git a/npm/ng-packs/packages/theme-shared/package.json b/npm/ng-packs/packages/theme-shared/package.json index 1558f1c824..ee2b5d7ffa 100644 --- a/npm/ng-packs/packages/theme-shared/package.json +++ b/npm/ng-packs/packages/theme-shared/package.json @@ -10,7 +10,7 @@ "@abp/ng.core": "~3.0.5", "@fortawesome/fontawesome-free": "^5.13.1", "@ng-bootstrap/ng-bootstrap": "^6.1.0", - "@ngx-validate/core": "^0.0.10", + "@ngx-validate/core": "^0.0.11", "@swimlane/ngx-datatable": "^17.0.0", "bootstrap": "^4.5.0", "chart.js": "^2.9.3",