diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..1e8163db --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,33 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**Stackblitz example** +Provide a minimal [stackblitz](https://stackblitz.com/) based example that shows the issue. For this, you can use the example application of this repo and the identity providers used here. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..bbcbbe7d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/support-request--general-question.md b/.github/ISSUE_TEMPLATE/support-request--general-question.md new file mode 100644 index 00000000..0f12ae6a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/support-request--general-question.md @@ -0,0 +1,33 @@ +--- +name: Support request/ general question +about: Requesting help from the community +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**Stackblitz example** +Provide a minimal [stackblitz](https://stackblitz.com/) based example that shows the issue. For this, you can use the example application of this repo and the identity providers used here. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.gitignore b/.gitignore index ee5c9d83..84c8d4f0 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ !.vscode/extensions.json # misc +/.angular/cache /.sass-cache /connect.lock /coverage diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..d0b804da --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +# Add files here to ignore them from prettier formatting + +/dist +/coverage diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..544138be --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "singleQuote": true +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..1348ba4a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:4200", + "webRoot": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index c5d2e6d0..2d463ecb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -25,9 +25,12 @@ "typescriptreact", "yml" ], - "spellright.language": "de", + "spellright.language": [ + "en" + ], "spellright.documentTypes": [ "latex", - "plaintext" + "plaintext", + "markdown" ] } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e844bd2b..116d1ee3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,27 +1,165 @@ -# Change Log - -## Lates features - -See [Release Notes](https://github.com/manfredsteyer/angular-oauth2-oidc/releases) - -## New Features in Version 2.1 -- New Config API (the original one is still supported) -- New convenience methods in OAuthService to streamline default tasks: - - ``setupAutomaticSilentRefresh()`` - - ``loadDiscoveryDocumentAndTryLogin()`` -- Single Sign out through Session Status Change Notification according to the OpenID Connect Session Management specs. This means, you can be notified when the user logs out using at the login provider. -- Possibility to define the ValidationHandler, the Config as well as the OAuthStorage via DI -- Better structured documentation - -## New Features in Version 2 -- Token Refresh for Implicit Flow by implementing "silent refresh" -- Validating the signature of the received id_token -- Providing Events via the observable ``events``. -- The event ``token_expires`` can be used together with a silent refresh to automatically refresh a token when/ before it expires (see also property ``timeoutFactor``). - -## Breaking Changes in Version 2 -- The property ``oidc`` defaults to ``true``. -- If you are just using oauth2, you have to set ``oidc`` to ``false``. Otherwise, the validation of the user profile will fail! -- By default, ``sessionStorage`` is used. To use ``localStorage`` call method setStorage -- Demands using https as OIDC and OAuth2 relay on it. This rule can be relaxed using the property ``requireHttps``, e. g. for local testing. -- Demands that every url provided by the discovery document starts with the issuer's url. This can be relaxed by using the property ``strictDiscoveryDocumentValidation``. +## [12.0.0](https://github.com/manfredsteyer/angular-oauth2-oidc/compare/v10.0.3...v10.0.2) (2021-07-16) + + +### Bug Fixes + +* [#728](https://github.com/manfredsteyer/angular-oauth2-oidc/issues/728) ([51e438a](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/51e438a942773948f17ab108332d704b459fd789)), closes [/github.com/manfredsteyer/angular-oauth2-oidc/issues/728#issuecomment-808969225](https://github.com//github.com/manfredsteyer/angular-oauth2-oidc/issues/728/issues/issuecomment-808969225) +* clear location.hash only if it is present ([c2b2753](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/c2b2753943d59a6b4b5149f1003371338ac1a210)), closes [#970](https://github.com/manfredsteyer/angular-oauth2-oidc/issues/970) +* correctly handle ? and & in location replacements ([70fd826](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/70fd8268832aba954956542e37896252dde5cdab)) +* Disable nonce validation for id token for e2e tests ([f5bd96c](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/f5bd96ca81ec6b7af868de72b1098541264347cf)) +* fix scope/state removal for implicit flow with hash ([9e257d0](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/9e257d0d267942d716607f2a1c78700bd9d6e9ef)) +* in code flow pass options to error handler ([c9a2c55](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/c9a2c557178af26154adfbcf39e3db2d12ee0503)), closes [#972](https://github.com/manfredsteyer/angular-oauth2-oidc/issues/972) +* **jwks:** update jsrsasign dependency to 10.2.0 ([a05bd8a](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/a05bd8a106035acb51fb06fd62e17de0de8decb4)), closes [#1061](https://github.com/manfredsteyer/angular-oauth2-oidc/issues/1061) +* multiplying calls to token endpoint in code flow ([59f65d2](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/59f65d2eb9cd1a724301fb3de0b3def796920bd4)) +* Refresh tokens with a plus sign get corrupted before sending to token endpoint ([2204c5a](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/2204c5a307640d11b847a0c266b44ca2c18fd9a7)) +* **revoketokenandlogout:** 'customParameters' should accept boolean ([9761bad](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/9761baded0d85bd831947de4607296fb029579ab)) +* While Using POPUP mode, we click on login button multiple time it opens multiple popup instead of focusing already opened ([bbff95b](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/bbff95b86173fa9262bf962e7fa4cfe4121b787e)) + + +### Features + +* introduce DateTimeProvider ([0c0a4a7](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/0c0a4a7a2574c8c134fa839f7ccdee06273a0676)) +* **logout:** postLogoutRedirectUri should not default to redirectUri ([ff7d1d9](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/ff7d1d915aa19f87bcb1c2d18ac3eb280db78d3b)) +* support JWT response on userinfo endpoint ([da16494](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/da1649499376863b0ebf884748176f3b38d91899)) +* Custom grant type added (https://github.com/manfredsteyer/angular-oauth2-oidc/pull/919) +* Listen for storage to receive auth hash from popup (https://github.com/manfredsteyer/angular-oauth2-oidc/pull/935) +* Add event for unchanged session (https://github.com/manfredsteyer/angular-oauth2-oidc/pull/936) +* Add loginHint to codeFlow (https://github.com/manfredsteyer/angular-oauth2-oidc/pull/938) +* Add a windowRef option to initLoginFlowInPopup to prevent the window from beeing blocked by popup blockers (https://github.com/manfredsteyer/angular-oauth2-oidc/pull/965) +* Use configured revocationEndpoint by default (https://github.com/manfredsteyer/angular-oauth2-oidc/pull/1020) + + + +## 10.0.0 (2020-06-30) + +* chore: increase version in package.json ([84d95a7](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/84d95a7)) +* chore: make version 9.2 ready ([415e053](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/415e053)) +* chore(deps): bump jsrsasign from 8.0.12 to 8.0.19 ([4def1c1](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/4def1c1)) +* chore(deps): bump websocket-extensions from 0.1.3 to 0.1.4 ([cae715e](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/cae715e)) +* chore(release): 9.2.1 ([7a15194](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/7a15194)) +* chore(release): 9.2.2 ([40f5ae5](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/40f5ae5)) +* chore(release): 9.3.0 ([f42f943](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/f42f943)) +* refactor: inline js-sha256 ([ca435c0](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/ca435c0)) +* refactor: remove dep on contributer-table ([b486546](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/b486546)) +* refactor: use esm for sha-256 ([92ee76d](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/92ee76d)) +* feat(oauth-service): pass custom url params to logOut ([4607d55](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/4607d55)) +* feat(oauth-service): revokeTokenAndLogout with cust params ([026dcb3](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/026dcb3)) +* 'disableAtHashCheck' by default if responseType is 'id_token' ([169d749](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/169d749)) +* #825: ([38c7c3f](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/38c7c3f)), closes [#825](https://github.com/manfredsteyer/angular-oauth2-oidc/issues/825) +* #825: ([fb3afe4](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/fb3afe4)), closes [#825](https://github.com/manfredsteyer/angular-oauth2-oidc/issues/825) +* Fix issue with ambient type in constructor when running Universal with Ivy ([9e95c73](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/9e95c73)) +* Fix typo in code-flow.md ([1816e7b](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/1816e7b)) +* Replaced document by this.document #773 ([678ff95](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/678ff95)), closes [#773](https://github.com/manfredsteyer/angular-oauth2-oidc/issues/773) +* response_types including 'code' gets a code_challenge ([58a8132](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/58a8132)) +* Update code-flow.md ([5c5288c](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/5c5288c)) +* docs(readme): use our own idsvr ([65c2b95](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/65c2b95)) +* fix: loadDiscoveryDocumentAndLogin should pass state into initLoginFlow ([132c624](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/132c624)) +* fix(lib): copying LICENSE file to output build ([e89aa6d](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/e89aa6d)) + + +# [10.0.0](https://github.com/manfredsteyer/angular-oauth2-oidc/compare/9.2.0...10.0.0) (2020-06-30) + + +### Bug Fixes + +* loadDiscoveryDocumentAndLogin should pass state into initLoginFlow ([132c624](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/132c62426cfe07ddaf0eebb85bdf062ee49e4a06)) +* **lib:** copying LICENSE file to output build ([e89aa6d](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/e89aa6d90054dc4ad20f234db2107e82b11a9386)) + + +### Features + +* **oauth-service:** pass custom url params to logOut ([4607d55](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/4607d55c6bdf608a32a2a029feac9eb37bfb493d)) +* **oauth-service:** revokeTokenAndLogout with cust params ([026dcb3](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/026dcb38e4299afbab8faff1d54dba94cadc1aa6)) + + + +# [10.0.0](https://github.com/manfredsteyer/angular-oauth2-oidc/compare/v9.3.0...v10.0.0) (2020-06-30) + + + +# Changelog + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + + +### Features + +* **automatic silent refresh:** stopAutomaticRefresh stops all timers. ([8ab853b](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/8ab853bf38dd162060d7b6cbd18f7b4fd5a84f18)) +* **code-flow:** allow using implicit flow by setting useSilentRefresh to true ([93902a5](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/93902a5808bb9b75a41d4bde44c6ab763bcfa9f6)) +* **oauth-service:** pass custom url params to logOut ([4607d55](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/4607d55c6bdf608a32a2a029feac9eb37bfb493d)) +* **oauth-service:** revokeTokenAndLogout with cust params ([026dcb3](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/026dcb38e4299afbab8faff1d54dba94cadc1aa6)) +* **sample:** also use new idsvr 4 for implicit flow demo to prevent issues with same site cookies ([58c6354](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/58c63541bc7d83d72c30577da2b68ac2d1dc35b7)) +* **session checks:** Session checks work now for code flow too. Pls see Docs for details. ([4bf8901](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/4bf89014d8cc5d50ed716500e3f3ad265b4ae2db)) +* **token-revocation:** also revoke refresh_token ([429ed2c](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/429ed2c5b50c60ac857ff0ffe84c1d7fc995c6dd)) +* remove jsrsasign dependancy ([77cb37a](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/77cb37abfd08762a59b221257ed8d5d5b7c795d4)) +* Upgrade to angular 8 ([31c6273](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/31c6273b388af7e796a9ad663e346f1e33ff331c)) + + +### Bug Fixes + +* loadDiscoveryDocumentAndLogin should pass state into initLoginFlow ([132c624](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/132c62426cfe07ddaf0eebb85bdf062ee49e4a06)) +* **lib:** copying LICENSE file to output build ([e89aa6d](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/e89aa6d90054dc4ad20f234db2107e82b11a9386)) +* **revoketokenandlogout:** explicit way to revoke an access token ([c799ead](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/c799eadbfa616d459af8be1a667499834745d78f)) +* **sample:** make sense of the guard ([1cae011](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/1cae011532dc91a250368c95120812d2f78f8109)) +* [#687](https://github.com/manfredsteyer/angular-oauth2-oidc/issues/687) ([e2599e0](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/e2599e071307ae1efe1592c83bb3b7a01642a61d)) +* **code flow:** Fixed code flow for IE 11 ([0f03d39](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/0f03d393aac9fe4e26444a73884dd154318d530f)) +* **sample:** use hash-based routing ([3f44eca](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/3f44ecae157305c56ae377fcd6d2df8dfde8adf5)) +* **session state:** save session_state also when using code flow ([8fa99ff](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/8fa99ff721ea2b08f28bc5e9fa3e48a459e2a59a)) +* **state:** passing an url with a querystring as the state, e. g. url?x=1 ([71b705c](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/71b705cb5105f6dfb49aabc55607745b881c5dc3)) +* missing HttpModule dependency ([7eac8ae](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/7eac8ae5cd1fd549f3933c30790f4b802c2c09f0)) +* run tokensetup outside ngzone ([07bb62d](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/07bb62d06abb84ef2da010977d07bfd2a3805b16)) +* typo ([3d331f2](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/3d331f2166340db43f0aaca42ce8abc4913cd027)) + +### [9.2.2](https://github.com/manfredsteyer/angular-oauth2-oidc/compare/v9.2.1...v9.2.2) (2020-05-09) + +### [9.2.1](https://github.com/manfredsteyer/angular-oauth2-oidc/compare/v9.2.0...v9.2.1) (2020-04-23) + +## [9.2.0](https://github.com/manfredsteyer/angular-oauth2-oidc/compare/v9.1.0...v9.2.0) (2020-03-28) + + +### Features + +* **revoketokenandlogout:** explicit way to revoke an access token according to [RFC 7009](https://tools.ietf.org/html/rfc7009) ([c799ead](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/c799eadbfa616d459af8be1a667499834745d78f)) + +* **token-revocation:** also revoke refresh_token ([429ed2c](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/429ed2c5b50c60ac857ff0ffe84c1d7fc995c6dd)) + + +### Bug Fixes + +* **sample:** make sense of the guard ([1cae011](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/1cae011532dc91a250368c95120812d2f78f8109)) + +## 9.1.0 (2020-03-23) + + +### Features + +* **automatic silent refresh:** stopAutomaticRefresh stops all timers. ([8ab853b](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/8ab853bf38dd162060d7b6cbd18f7b4fd5a84f18)) +* **code-flow:** allow using silent refresh by setting useSilentRefresh to true ([93902a5](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/93902a5808bb9b75a41d4bde44c6ab763bcfa9f6)) +* **sample:** Also use new Identity Server 4 for implicit flow demo to prevent issues with same site cookies ([58c6354](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/58c63541bc7d83d72c30577da2b68ac2d1dc35b7)) +* **session checks:** Session checks work now for code flow too. Please see docs for details. ([4bf8901](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/4bf89014d8cc5d50ed716500e3f3ad265b4ae2db)) + + +### Bug Fixes + +* **code flow:** Fixed code flow for IE 11 ([0f03d39](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/0f03d393aac9fe4e26444a73884dd154318d530f)) +* **sample:** use hash-based routing ([3f44eca](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/3f44ecae157305c56ae377fcd6d2df8dfde8adf5)) +* **session state:** save session_state also when using code flow ([8fa99ff](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/8fa99ff721ea2b08f28bc5e9fa3e48a459e2a59a)) +* **state:** passing an url with a querystring as the state, e. g. url?x=1 ([71b705c](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/71b705cb5105f6dfb49aabc55607745b881c5dc3)) +* [#687](https://github.com/manfredsteyer/angular-oauth2-oidc/issues/687) ([e2599e0](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/e2599e071307ae1efe1592c83bb3b7a01642a61d)) +* missing HttpModule dependency ([7eac8ae](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/7eac8ae5cd1fd549f3933c30790f4b802c2c09f0)) +* run tokensetup outside ngzone ([07bb62d](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/07bb62d06abb84ef2da010977d07bfd2a3805b16)) +* typo ([3d331f2](https://github.com/manfredsteyer/angular-oauth2-oidc/commit/3d331f2166340db43f0aaca42ce8abc4913cd027)) + +### Pull Requests +- Update sample app and silent-refresh.html script #755, linjie997 +- Add optional state parameter for logout, pmccloghrylaing +- fix customHashFragment usage in tryLoginCodeFlow, roblabat +- replace document with injectionToken #741, d-moos +- Support predefined custom parameters extraction from the TokenResponse, vdveer +- Fixed not working silent refresh when using 'code' #735, ErazerBrecht + +### Thanks + +Big Thanks to all contributers: Brecht Carlier, Daniel Moos, Jie Lin, Manfred Steyer, Phil McCloghry-Laing, robin labat, vdveer + +Also, big thanks to jeroenheijmans for doing an awesome job with moderating and analyzing the issues! \ No newline at end of file diff --git a/CREDITS.md b/CREDITS.md new file mode 100644 index 00000000..95d30cbd --- /dev/null +++ b/CREDITS.md @@ -0,0 +1 @@ +This lib uses an inlined version of [js-sha256](https://www.npmjs.com/package/js-sha256) (MIT license) diff --git a/README.md b/README.md index c4bc72b3..44b87299 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,50 @@ -# angular-oauth2-oidc +# lacuna-oauth2-oidc -Support for OAuth 2 and OpenId Connect (OIDC) in Angular. +Support for OAuth 2 and OpenId Connect (OIDC) in Angular. Already prepared for the upcoming OAuth 2.1. ![OIDC Certified Logo](https://raw.githubusercontent.com/manfredsteyer/angular-oauth2-oidc/master/oidc.png) ## Credits -- [generator-angular2-library](https://github.com/jvandemo/generator-angular2-library) for scaffolding an Angular library -- [jsrasign](https://kjur.github.io/jsrsasign/) until version 5: For validating token signature and for hashing; beginning with version 6, we are using browser APIs to minimize our bundle size -- [Identity Server](https://github.com/identityserver) (used for testing with an .NET/.NET Core Backend) +- [jsrsasign](https://kjur.github.io/jsrsasign/) for validating token signature and for hashing +- [Identity Server](https://github.com/identityserver) for testing with an .NET/.NET Core Backend - [Keycloak (Redhat)](http://www.keycloak.org/) for testing with Java +- [Auth0](https://auth0.com/) ## Resources -- Sources and Sample: -https://github.com/manfredsteyer/angular-oauth2-oidc +- Sources and Sample: [https://github.com/manfredsteyer/angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc) +- Source Code Documentation: [https://manfredsteyer.github.io/angular-oauth2-oidc/docs](https://manfredsteyer.github.io/angular-oauth2-oidc/docs) +- Community-provided sample implementation: [https://github.com/jeroenheijmans/sample-angular-oauth2-oidc-with-auth-guards/](https://github.com/jeroenheijmans/sample-angular-oauth2-oidc-with-auth-guards/) -- Source Code Documentation -https://manfredsteyer.github.io/angular-oauth2-oidc/docs ## Tested Environment -Successfully tested with **Angular 7** and its Router, PathLocationStrategy as well as HashLocationStrategy and CommonJS-Bundling via webpack. At server side we've used IdentityServer (.NET/ .NET Core) and Redhat's Keycloak (Java). +Successfully tested with **Angular 4.3 to Angular 15** and its Router, PathLocationStrategy as well as HashLocationStrategy and CommonJS-Bundling via webpack. + +At server side we've used **IdentityServer** (.NET / .NET Core), Redhat's **Keycloak** (Java), and **Auth0** (Auth0 is officially supported since version 10 of this lib). For Auth0, please have a look into the respective documentation page here. + +For using this library with **Azure Active Directory** (**Azure AD**), we recommend an additional look to this [blog post](https://dev.to/yuriburger/azure-active-directory-b2c-with-pkce-for-your-angular-app-1dcg) and the example linked at the end of this blog post. + +Also, the Okta community created some guidelines on how to use this lib with Okta. See the links at the end of this page for more information. + +**Angular 15**: Use 15.x versions of this library (**should also work with older Angular versions!**). + +**Angular 14**: Use 14.x versions of this library (**should also work with older Angular versions!**). + +**Angular 13**: Use 13.x versions of this library (**should also work with older Angular versions!**). + +**Angular 12**: Use 12.x versions of this library (**should also work with older Angular versions!**). + +**Angular 11**: Use 10.x versions of this library (**should also work with older Angular versions!**). + +**Angular 10**: Use 10.x versions of this library (**should also work with older Angular versions!**). + +**Angular 9**: Use 9.x versions of this library (**should also work with older Angular versions!**). + +**Angular 8**: Use 8.x versions of this library. + +**Angular 7**: Use 7.x versions of this library. **Angular 6**: Use Version 4.x of this library. Version 4.x was tested with Angular 6. You can also try the newer version 5.x of this library which has a much smaller bundle size. @@ -30,47 +53,109 @@ Successfully tested with **Angular 7** and its Router, PathLocationStrategy as w ## Release Cycle - We plan one major release for each Angular version - - Will contain new features - - Will contain bug fixes and PRs -- Critical Bugfixes on demand + - Will contain new features + - Will contain bug fixes and PRs +- Critical bugfixes on demand ## Contributions + - Feel free to file pull requests -- The closed issues contain some ideas for PRs and enhancements (see labels) +- The issues contain some ideas for PRs and enhancements (see labels) +- If you want to contribute to the docs, you can do so in the `docs-src` folder. Make sure you update `summary.json` as well. Then generate the docs with the following commands: + + ```sh + npm install -g @compodoc/compodoc + npm run docs + ``` + +## Features -# Features -- Logging in via OAuth2 and OpenId Connect (OIDC) Implicit Flow (where a user is redirected to Identity Provider) +- Logging in via Code Flow + PKCE + - Hence, you are safe for the upcoming OAuth 2.1 +- Logging in via Implicit Flow (where a user is redirected to Identity Provider) - "Logging in" via Password Flow (where a user enters their password into the client) -- Token Refresh for Password Flow by using a Refresh Token +- Token Refresh for all supported flows - Automatically refreshing a token when/some time before it expires - Querying Userinfo Endpoint - Querying Discovery Document to ease configuration - Validating claims of the id_token regarding the specs - Hook for further custom validations - Single-Sign-Out by redirecting to the auth-server's logout-endpoint +- Tested with all modern browsers and IE +- Token Revocation according to [RFC 7009](https://tools.ietf.org/html/rfc7009#section-2.2) ## Sample-Auth-Server -You can use the OIDC-Sample-Server mentioned in the samples for Testing. It assumes, that your Web-App runs on http://localhost:8080. +You can use the OIDC-Sample-Server used in our examples. It assumes, that your Web-App runs on http://localhost:4200 -Username/Password: max/geheim +Username/Password: -*clientIds:* -- spa-demo (implicit flow) -- demo-resource-owner (resource owner password flow) +- max/geheim +- bob/bob +- alice/alice -*redirectUris:* -- localhost:[8080-8089|4200-4202] -- localhost:[8080-8089|4200-4202]/index.html -- localhost:[8080-8089|4200-4202]/silent-refresh.html +_clientIds:_ + +- spa (Code Flow + PKCE) +- implicit (implicit flow) + +_redirectUris:_ + +- localhost:[4200-4202] +- localhost:[4200-4202]/index.html +- localhost:[4200-4202]/silent-refresh.html ## Installing -``` +```sh npm i angular-oauth2-oidc --save ``` -## Importing the NgModule + +## Option 1: Standalone APIs + +If you use Standalone Components introduced with Angular 14, you can use our standalone API (call to ``provideOAuthClient``) in your ``main.ts`` to setup the ``OAuthClient``: + +```TypeScript +// main.ts -- Angular 15+ version +import { bootstrapApplication } from '@angular/platform-browser'; + +import { provideHttpClient } from '@angular/common/http'; + +import { AppComponent } from './app/app.component'; +import { provideOAuthClient } from 'angular-oauth2-oidc'; + +bootstrapApplication(AppComponent, { + providers: [ + provideHttpClient(), + provideOAuthClient() + ] +}); +``` + +As Angular 14 does have Standalone Components but no Standalone API for its ``HttpClient``, you need to go with the traditional ``HttpClientModule`` in this version: + +```TypeScript +// main.ts -- Angular 14 version +import { bootstrapApplication } from '@angular/platform-browser'; + +import { HttpClientModule } from '@angular/common/http'; + +import { AppComponent } from './app/app.component'; +import { provideOAuthClient } from 'angular-oauth2-oidc'; +import { importProvidersFrom } from '@angular/core'; + +bootstrapApplication(AppComponent, { + providers: [ + importProvidersFrom(HttpClientModule), + provideOAuthClient() + ] +}); +``` + +The ``provideOAuthClient`` function takes the same parameters as the forRoot function of the OAuthModule that is still in place for the sake of compatibility with existing code bases. + +## Option 2: Using NgModules ```TypeScript import { HttpClientModule } from '@angular/common/http'; @@ -78,7 +163,7 @@ import { OAuthModule } from 'angular-oauth2-oidc'; // etc. @NgModule({ - imports: [ + imports: [ // etc. HttpClientModule, OAuthModule.forRoot() @@ -89,149 +174,93 @@ import { OAuthModule } from 'angular-oauth2-oidc'; // etc. ], bootstrap: [ - AppComponent + AppComponent ] }) export class AppModule { } -``` +``` -## Configuring for Implicit Flow +# Logging in -This section shows how to implement login leveraging implicit flow. This is the OAuth2/OIDC flow best suitable for -Single Page Application. It sends the user to the Identity Provider's login page. After logging in, the SPA gets tokens. -This also allows for single sign on as well as single sign off. +Since Version 8, this library supports code flow and [PKCE](https://tools.ietf.org/html/rfc7636) to align with the current draft of the [OAuth 2.0 Security Best Current Practice](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13) document. This is also the foundation of the upcoming OAuth 2.1. -To configure the library, the following sample uses the new configuration API introduced with Version 2.1. -Hence, the original API is still supported. +To configure your solution for code flow + PKCE you have to set the `responseType` to `code`: ```TypeScript -import { AuthConfig } from 'angular-oauth2-oidc'; + import { AuthConfig } from 'angular-oauth2-oidc'; -export const authConfig: AuthConfig = { + export const authCodeFlowConfig: AuthConfig = { + // Url of the Identity Provider + issuer: 'https://idsvr4.azurewebsites.net', - // Url of the Identity Provider - issuer: 'https://steyer-identity-server.azurewebsites.net/identity', + // URL of the SPA to redirect the user to after login + redirectUri: window.location.origin + '/index.html', - // URL of the SPA to redirect the user to after login - redirectUri: window.location.origin + '/index.html', + // The SPA's id. The SPA is registerd with this id at the auth-server + // clientId: 'server.code', + clientId: 'spa', - // The SPA's id. The SPA is registerd with this id at the auth-server - clientId: 'spa-demo', + // Just needed if your auth server demands a secret. In general, this + // is a sign that the auth server is not configured with SPAs in mind + // and it might not enforce further best practices vital for security + // such applications. + // dummyClientSecret: 'secret', - // set the scope for the permissions the client should request - // The first three are defined by OIDC. The 4th is a usecase-specific one - scope: 'openid profile email voucher', -} -``` + responseType: 'code', -Configure the OAuthService with this config object when the application starts up: + // set the scope for the permissions the client should request + // The first four are defined by OIDC. + // Important: Request offline_access to get a refresh token + // The api scope is a usecase specific one + scope: 'openid profile email offline_access api', -```TypeScript -import { OAuthService } from 'angular-oauth2-oidc'; -import { JwksValidationHandler } from 'angular-oauth2-oidc'; -import { authConfig } from './auth.config'; -import { Component } from '@angular/core'; - -@Component({ - selector: 'flight-app', - templateUrl: './app.component.html' -}) -export class AppComponent { + showDebugInformation: true, + }; +``` - constructor(private oauthService: OAuthService) { - this.configureWithNewConfigApi(); - } +After this, you can initialize the code flow using: - private configureWithNewConfigApi() { - this.oauthService.configure(authConfig); - this.oauthService.tokenValidationHandler = new JwksValidationHandler(); - this.oauthService.loadDiscoveryDocumentAndTryLogin(); - } -} +```TypeScript +this.oauthService.initCodeFlow(); ``` -### Implementing a Login Form - -After you've configured the library, you just have to call ``initImplicitFlow`` to login using OAuth2/ OIDC. +There is also a convenience method `initLoginFlow` which initializes either the code flow or the implicit flow depending on your configuration. ```TypeScript -import { Component } from '@angular/core'; -import { OAuthService } from 'angular-oauth2-oidc'; - -@Component({ - templateUrl: "app/home.html" -}) -export class HomeComponent { +this.oauthService.initLoginFlow(); +``` - constructor(private oauthService: OAuthService) { - } +Also -- as shown in the readme -- you have to execute the following code when bootstrapping to make the library to fetch the token: - public login() { - this.oauthService.initImplicitFlow(); - } +```TypeScript +this.oauthService.configure(authCodeFlowConfig); +this.oauthService.loadDiscoveryDocumentAndTryLogin(); +``` - public logoff() { - this.oauthService.logOut(); - } +### Logging out - public get name() { - let claims = this.oauthService.getIdentityClaims(); - if (!claims) return null; - return claims.given_name; - } +The logOut method clears the used token store (by default ``sessionStorage``) and forwards the user to the auth servers logout endpoint if one was configured (manually or via the discovery document). -} +```typescript +this.oauthService.logOut(); ``` -The following snippet contains the template for the login page: - -```HTML -

- Hallo -

-

- Hallo, {{name}} -

- - - - -
- Username/Passwort zum Testen: max/geheim -
+If you want to revoke the existing access token and the existing refresh token before logging out, use the following method: + +```typescript +this.oauthService.revokeTokenAndLogout(); ``` ### Skipping the Login Form -If you don't want to display a login form that tells the user that they are redirected to the identity server, you can use the convenience function ``this.oauthService.loadDiscoveryDocumentAndLogin();`` instead of ``this.oauthService.loadDiscoveryDocumentAndTryLogin();`` when setting up the library. - -This directly redirects the user to the identity server if there are no valid tokens. +If you don't want to display a login form that tells the user that they are redirected to the identity server, you can use the convenience function `this.oauthService.loadDiscoveryDocumentAndLogin();` instead of `this.oauthService.loadDiscoveryDocumentAndTryLogin();` when setting up the library. +This directly redirects the user to the identity server if there are no valid tokens. Ensure you have your `issuer` set to your discovery document endpoint! ### Calling a Web API with an Access Token -Pass this Header to the used method of the ``Http``-Service within an Instance of the class ``Headers``: - -```TypeScript -var headers = new Headers({ - "Authorization": "Bearer " + this.oauthService.getAccessToken() -}); -``` - -If you are using the new ``HttpClient``, use the class ``HttpHeaders`` instead: - -```TypeScript -var headers = new HttpHeaders({ - "Authorization": "Bearer " + this.oauthService.getAccessToken() -}); -``` - -Since 3.1 you can also automate this task by switching ``sendAccessToken`` on and by setting ``allowedUrls`` to an array with prefixes for the respective URLs. Use lower case for the prefixes. +You can automate this task by switching `sendAccessToken` on and by setting `allowedUrls` to an array with prefixes for the respective URLs. Use lower case for the prefixes. ```TypeScript OAuthModule.forRoot({ @@ -242,26 +271,105 @@ OAuthModule.forRoot({ }) ``` +If you need more versatility, you can look in the [documentation](https://manfredsteyer.github.io/angular-oauth2-oidc/docs/additional-documentation/working-with-httpinterceptors.html) how to setup a custom interceptor. + +## Token Refresh + +See docs: https://manfredsteyer.github.io/angular-oauth2-oidc/docs/additional-documentation/refreshing-a-token.html + ## Routing -If you use the ``PathLocationStrategy`` (which is on by default) and have a general catch-all-route (``path: '**'``) you should be fine. Otherwise look up the section ``Routing with the HashStrategy`` in the [documentation](https://manfredsteyer.github.io/angular-oauth2-oidc/docs/). +If you use the `PathLocationStrategy` (which is on by default) and have a general catch-all-route (`path: '**'`) you should be fine. Otherwise look up the section `Routing with the HashStrategy` in the [documentation](https://manfredsteyer.github.io/angular-oauth2-oidc/docs/). + +## Implicit Flow -## More Documentation +Nowadays, using code flow + PKCE -- as shown above -- is the recommended OAuth 2/OIDC flow for SPAs. To use the older implicit flow, lookup this docs: https://manfredsteyer.github.io/angular-oauth2-oidc/docs/additional-documentation/using-implicit-flow.html + +## More Documentation (!) See the [documentation](https://manfredsteyer.github.io/angular-oauth2-oidc/docs/) for more information about this library. + +## Breaking Change in Version 9 + +With regards to tree shaking, beginning with version 9, the `JwksValidationHandler` has been moved to a library of its own. If you need it for implementing **implicit flow**, please install it using npm: + +``` +npm i angular-oauth2-oidc-jwks --save +``` + +After that, you can import it into your application by using this: + +```typescript +import { JwksValidationHandler } from 'angular-oauth2-oidc-jwks'; +``` + +instead of that: + +```typescript +import { JwksValidationHandler } from 'angular-oauth2-oidc'; +``` + +Please note, that this dependency is not needed for the **code flow**, which is nowadays the **recommended** flow for single page applications. This also results in smaller bundle sizes. + + + +### Breaking change in 9.1.0 + +The use of `encodeURIComponent` on the argument passed to `initImplicitFlow` and its Code Flow counterparts was mandatory before this version. + +Since that was considered a _bug_, the need to do so was removed. +Now the reverse is true **if you're upgrading from before 9.0.0**: you need to remove any call to encode URI components in your own application, as the library will now do it for you. + ## Tutorials -* [Tutorial with Demo Servers available online](https://www.softwarearchitekt.at/post/2016/07/03/authentication-in-angular-2-with-oauth2-oidc-and-guards-for-the-newest-new-router-english-version.aspx) -* [Angular Authentication with OpenID Connect and Okta in 20 Minutes](https://developer.okta.com/blog/2017/04/17/angular-authentication-with-oidc) -* [Add Authentication to Your Angular PWA](https://developer.okta.com/blog/2017/06/13/add-authentication-angular-pwa) -* [Build an Ionic App with User Authentication](https://developer.okta.com/blog/2017/08/22/build-an-ionic-app-with-user-authentication) -* [On-Site Workshops](https://www.softwarearchitekt.at) +- [Tutorial with Demo Servers available online](https://www.softwarearchitekt.at/post/2016/07/03/authentication-in-angular-2-with-oauth2-oidc-and-guards-for-the-newest-new-router-english-version.aspx) +- [Angular Authentication with OpenID Connect and Okta in 20 Minutes](https://developer.okta.com/blog/2017/04/17/angular-authentication-with-oidc) +- [Add Authentication to Your Angular PWA](https://developer.okta.com/blog/2017/06/13/add-authentication-angular-pwa) +- [Build an Ionic App with User Authentication](https://developer.okta.com/blog/2017/08/22/build-an-ionic-app-with-user-authentication) +- [On-Site Workshops](https://www.softwarearchitekt.at) +- [Angular 6 with Auth0 using this library](https://github.com/jeroenheijmans/sample-auth0-angular-oauth2-oidc) + +## Thanks to all Contributors + +[alexandis](https://github.com/alexandis)[anbiniyar](https://github.com/anbiniyar)[anoordende](https://github.com/anoordende)[ArsProgramma](https://github.com/ArsProgramma)[nihanth007](https://github.com/nihanth007) + +[bobvandevijver](https://github.com/bobvandevijver)[BobCui20](https://github.com/BobCui20)[Bottswana](https://github.com/Bottswana)[ErazerBrecht](https://github.com/ErazerBrecht)[Chris3773](https://github.com/Chris3773) + +[ChristianMurphy](https://github.com/ChristianMurphy)[d-moos](https://github.com/d-moos)[enterprisebug](https://github.com/enterprisebug)[craniodev](https://github.com/craniodev)[FabianGosebrink](https://github.com/FabianGosebrink) + +[FabienDehopre](https://github.com/FabienDehopre)[FRosner](https://github.com/FRosner)[MisterJames](https://github.com/MisterJames)[JessePreiner](https://github.com/JessePreiner)[jesusbotella](https://github.com/jesusbotella) + +[Jojofoulk](https://github.com/Jojofoulk)[kristofdegrave](https://github.com/kristofdegrave)[saxicek](https://github.com/saxicek)[lukasmatta](https://github.com/lukasmatta)[Maximaximum](https://github.com/Maximaximum) + +[mpbalmeida](https://github.com/mpbalmeida)[mhyfritz](https://github.com/mhyfritz)[mdaehnert](https://github.com/mdaehnert)[mcserra](https://github.com/mcserra)[nhumblot](https://github.com/nhumblot) + +[l1b3r](https://github.com/l1b3r)[oleersoy](https://github.com/oleersoy)[OskarsPakers](https://github.com/OskarsPakers)[hellerbarde](https://github.com/hellerbarde)[paweldyminski](https://github.com/paweldyminski) + +[bechhansen](https://github.com/bechhansen)[peterneave](https://github.com/peterneave)[pmccloghrylaing](https://github.com/pmccloghrylaing)[akehir](https://github.com/akehir)[RubenVermeulen](https://github.com/RubenVermeulen) + +[ryanmwright](https://github.com/ryanmwright)[scttcper](https://github.com/scttcper)[abshoff](https://github.com/abshoff)[SpazzMarticus](https://github.com/SpazzMarticus)[srenatus](https://github.com/srenatus) + +[sven-codeculture](https://github.com/sven-codeculture)[Rocket18](https://github.com/Rocket18)[Ceteareth](https://github.com/Ceteareth)[vadjs](https://github.com/vadjs)[Varada-Schneider](https://github.com/Varada-Schneider) + +[Gimly](https://github.com/Gimly)[akkaradej](https://github.com/akkaradej)[coyoteecd](https://github.com/coyoteecd)[darbio](https://github.com/darbio)[filipvh](https://github.com/filipvh) + +[kyubisation](https://github.com/kyubisation)[luciimon](https://github.com/luciimon)[mike-rivera](https://github.com/mike-rivera)[drobert-bfm](https://github.com/drobert-bfm)[roblabat](https://github.com/roblabat) + +[wdunn001](https://github.com/wdunn001)[adrianbenjuya](https://github.com/adrianbenjuya)[Andreas-Hjortland](https://github.com/Andreas-Hjortland)[adematte](https://github.com/adematte)[cgatian](https://github.com/cgatian) + +[dirkbolte](https://github.com/dirkbolte)[enricodeleo](https://github.com/enricodeleo)[Gregordy](https://github.com/Gregordy)[jeroenhinfi](https://github.com/jeroenhinfi)[linjie997](https://github.com/linjie997) +[jfyne](https://github.com/jfyne)[kevincathcart-cas](https://github.com/kevincathcart-cas)[martin1cerny](https://github.com/martin1cerny)[marvinosswald](https://github.com/marvinosswald)[nick1699](https://github.com/nick1699) +[paulyoder](https://github.com/paulyoder)[reda-alaoui](https://github.com/reda-alaoui)[remiburtin](https://github.com/remiburtin)[gingters](https://github.com/gingters)[kranich](https://github.com/kranich) +[StefanoChiodino](https://github.com/StefanoChiodino)[tpeter1985](https://github.com/tpeter1985)[dennisameling](https://github.com/dennisameling)[dependabot[bot]](https://github.com/apps/dependabot)[jdgeier](https://github.com/jdgeier) +[mraible](https://github.com/mraible)[ajpierson](https://github.com/ajpierson)[artnim](https://github.com/artnim)[fmalcher](https://github.com/fmalcher)[Flofie](https://github.com/Flofie) +[mabdelaal86](https://github.com/mabdelaal86)[nhance](https://github.com/nhance)[Razzeee](https://github.com/Razzeee)[maxisam](https://github.com/maxisam)[ismcagdas](https://github.com/ismcagdas) +[Toxicable](https://github.com/Toxicable)[ManuelRauber](https://github.com/ManuelRauber)[vdveer](https://github.com/vdveer)[jeroenheijmans](https://github.com/jeroenheijmans)[manfredsteyer](https://github.com/manfredsteyer) diff --git a/angular.json b/angular.json index d0d6cd06..86063239 100644 --- a/angular.json +++ b/angular.json @@ -1,5 +1,5 @@ { - "$schema": "./node_modules/@angular-devkit/core/src/workspace/workspace-schema.json", + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "projects": { @@ -10,36 +10,17 @@ "prefix": "lib", "architect": { "build": { - "builder": "@angular-devkit/build-ng-packagr:build", + "builder": "@angular-devkit/build-angular:ng-packagr", "options": { "tsConfig": "projects/lib/tsconfig.lib.json", "project": "projects/lib/ng-package.json" }, "configurations": { "production": { - "project": "projects/lib/ng-package.prod.json" + "project": "projects/lib/ng-package.prod.json", + "tsConfig": "projects/lib/tsconfig.lib.prod.json" } } - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "main": "projects/lib/src/test.ts", - "tsConfig": "projects/lib/tsconfig.spec.json", - "karmaConfig": "projects/lib/karma.conf.js" - } - }, - "lint": { - "builder": "@angular-devkit/build-angular:tslint", - "options": { - "tsConfig": [ - "projects/lib/tsconfig.lib.json", - "projects/lib/tsconfig.spec.json" - ], - "exclude": [ - "**/node_modules/**" - ] - } } } }, @@ -67,10 +48,22 @@ "projects/sample/src/styles.css", "node_modules/bootstrap/dist/css/bootstrap.css" ], - "scripts": [] + "scripts": [], + "vendorChunk": true, + "extractLicenses": false, + "buildOptimizer": false, + "sourceMap": true, + "optimization": false, + "namedChunks": true }, "configurations": { "production": { + "budgets": [ + { + "type": "anyComponentStyle", + "maximumWarning": "6kb" + } + ], "fileReplacements": [ { "replace": "projects/sample/src/environments/environment.ts", @@ -80,14 +73,13 @@ "optimization": true, "outputHashing": "all", "sourceMap": false, - "extractCss": true, "namedChunks": false, - "aot": true, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true } - } + }, + "defaultConfiguration": "" }, "serve": { "builder": "@angular-devkit/build-angular:dev-server", @@ -114,7 +106,8 @@ "tsConfig": "projects/sample/tsconfig.spec.json", "karmaConfig": "projects/sample/karma.conf.js", "styles": [ - "projects/sample/styles.css" + "projects/sample/src/styles.css", + "node_modules/bootstrap/dist/css/bootstrap.css" ], "scripts": [], "assets": [ @@ -122,39 +115,224 @@ "projects/sample/src/assets" ] } + } + } + }, + + "quickstart-demo": { + "projectType": "application", + "schematics": {}, + "root": "projects/quickstart-demo", + "sourceRoot": "projects/quickstart-demo/src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/quickstart-demo", + "index": "projects/quickstart-demo/src/index.html", + "main": "projects/quickstart-demo/src/main.ts", + "polyfills": "projects/quickstart-demo/src/polyfills.ts", + "tsConfig": "projects/quickstart-demo/tsconfig.app.json", + "aot": false, + "assets": [ + "projects/quickstart-demo/src/favicon.ico", + "projects/quickstart-demo/src/assets" + ], + "styles": ["projects/quickstart-demo/src/styles.css"], + "scripts": [], + "vendorChunk": true, + "extractLicenses": false, + "buildOptimizer": false, + "sourceMap": true, + "optimization": false, + "namedChunks": true + }, + "configurations": { + "production": { + "fileReplacements": [ + { + "replace": "projects/quickstart-demo/src/environments/environment.ts", + "with": "projects/quickstart-demo/src/environments/environment.prod.ts" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "namedChunks": false, + "aot": true, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true, + "budgets": [ + { + "type": "initial", + "maximumWarning": "2mb", + "maximumError": "5mb" + } + ] + } + }, + "defaultConfiguration": "" + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "browserTarget": "quickstart-demo:build" + + }, + "configurations": { + "production": { + "browserTarget": "quickstart-demo:build:production" + } + } }, - "lint": { - "builder": "@angular-devkit/build-angular:tslint", + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "quickstart-demo:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", "options": { - "tsConfig": [ - "projects/sample/tsconfig.app.json", - "projects/sample/tsconfig.spec.json" + "main": "projects/quickstart-demo/src/test.ts", + "polyfills": "projects/quickstart-demo/src/polyfills.ts", + "tsConfig": "projects/quickstart-demo/tsconfig.spec.json", + "karmaConfig": "projects/quickstart-demo/karma.conf.js", + "assets": [ + "projects/quickstart-demo/src/favicon.ico", + "projects/quickstart-demo/src/assets" ], - "exclude": [ - "**/node_modules/**" - ] + "styles": ["projects/quickstart-demo/src/styles.css"], + "scripts": [] + } + }, + "e2e": { + "builder": "@angular-devkit/build-angular:protractor", + "options": { + "protractorConfig": "projects/quickstart-demo/e2e/protractor.conf.js", + "devServerTarget": "quickstart-demo:serve" + }, + "configurations": { + "production": { + "devServerTarget": "quickstart-demo:serve:production" + } + } + } + } + }, + + "angular-oauth2-oidc-jwks": { + "projectType": "library", + "root": "projects/angular-oauth2-oidc-jwks", + "sourceRoot": "projects/angular-oauth2-oidc-jwks/src", + "prefix": "lib", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:ng-packagr", + "options": { + "tsConfig": "projects/angular-oauth2-oidc-jwks/tsconfig.lib.json", + "project": "projects/angular-oauth2-oidc-jwks/ng-package.json" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "projects/angular-oauth2-oidc-jwks/src/test.ts", + "tsConfig": "projects/angular-oauth2-oidc-jwks/tsconfig.spec.json", + "karmaConfig": "projects/angular-oauth2-oidc-jwks/karma.conf.js" } } } }, - "sample-e2e": { - "root": "projects/sample-e2e/", + "quickstart-standalone": { "projectType": "application", + "schematics": {}, + "root": "projects/quickstart-standalone", + "sourceRoot": "projects/quickstart-standalone/src", + "prefix": "app", "architect": { - "e2e": { - "builder": "@angular-devkit/build-angular:protractor", + "build": { + "builder": "@angular-devkit/build-angular:browser", "options": { - "protractorConfig": "projects/sample-e2e/protractor.conf.js", - "devServerTarget": "sample:serve" + "outputPath": "dist/quickstart-standalone", + "index": "projects/quickstart-standalone/src/index.html", + "main": "projects/quickstart-standalone/src/main.ts", + "polyfills": [ + "zone.js" + ], + "tsConfig": "projects/quickstart-standalone/tsconfig.app.json", + "assets": [ + "projects/quickstart-standalone/src/favicon.ico", + "projects/quickstart-standalone/src/assets" + ], + "styles": [ + "projects/quickstart-standalone/src/styles.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "browserTarget": "quickstart-standalone:build:production" + }, + "development": { + "browserTarget": "quickstart-standalone:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "quickstart-standalone:build" } }, - "lint": { - "builder": "@angular-devkit/build-angular:tslint", + "test": { + "builder": "@angular-devkit/build-angular:karma", "options": { - "tsConfig": "projects/sample-e2e/tsconfig.e2e.json", - "exclude": [ - "**/node_modules/**" - ] + "polyfills": [ + "zone.js", + "zone.js/testing" + ], + "tsConfig": "projects/quickstart-standalone/tsconfig.spec.json", + "assets": [ + "projects/quickstart-standalone/src/favicon.ico", + "projects/quickstart-standalone/src/assets" + ], + "styles": [ + "projects/quickstart-standalone/src/styles.css" + ], + "scripts": [] } } } @@ -162,7 +340,10 @@ }, "schematics": { "@schematics/angular:component": { - "styleext": "css" + "style": "css" } + }, + "cli": { + "analytics": false } -} \ No newline at end of file +} diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 00000000..e14e0dfa --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,7 @@ +/** + * To check all configuration options, please visit + * https://commitlint.js.org/#/reference-rules + */ +module.exports = { + extends: ['@commitlint/config-conventional'], +}; diff --git a/contributors.bat b/contributors.bat new file mode 100644 index 00000000..3f4863ac --- /dev/null +++ b/contributors.bat @@ -0,0 +1 @@ +npx github-contributors-list --repo angular-oauth2-oidc --owner manfredsteyer diff --git a/contributors.md b/contributors.md new file mode 100644 index 00000000..e4b53a80 --- /dev/null +++ b/contributors.md @@ -0,0 +1,42 @@ + +[alexandis](https://github.com/alexandis)[anbiniyar](https://github.com/anbiniyar)[anoordende](https://github.com/anoordende)[ArsProgramma](https://github.com/ArsProgramma)[nihanth007](https://github.com/nihanth007) + +[bobvandevijver](https://github.com/bobvandevijver)[BobCui20](https://github.com/BobCui20)[Bottswana](https://github.com/Bottswana)[ErazerBrecht](https://github.com/ErazerBrecht)[Chris3773](https://github.com/Chris3773) + +[ChristianMurphy](https://github.com/ChristianMurphy)[d-moos](https://github.com/d-moos)[enterprisebug](https://github.com/enterprisebug)[craniodev](https://github.com/craniodev)[FabianGosebrink](https://github.com/FabianGosebrink) + +[FabienDehopre](https://github.com/FabienDehopre)[FRosner](https://github.com/FRosner)[MisterJames](https://github.com/MisterJames)[JessePreiner](https://github.com/JessePreiner)[jesusbotella](https://github.com/jesusbotella) + +[Jojofoulk](https://github.com/Jojofoulk)[kristofdegrave](https://github.com/kristofdegrave)[saxicek](https://github.com/saxicek)[lukasmatta](https://github.com/lukasmatta)[Maximaximum](https://github.com/Maximaximum) + +[mpbalmeida](https://github.com/mpbalmeida)[mhyfritz](https://github.com/mhyfritz)[mdaehnert](https://github.com/mdaehnert)[mcserra](https://github.com/mcserra)[nhumblot](https://github.com/nhumblot) + +[l1b3r](https://github.com/l1b3r)[oleersoy](https://github.com/oleersoy)[OskarsPakers](https://github.com/OskarsPakers)[hellerbarde](https://github.com/hellerbarde)[paweldyminski](https://github.com/paweldyminski) + +[bechhansen](https://github.com/bechhansen)[peterneave](https://github.com/peterneave)[pmccloghrylaing](https://github.com/pmccloghrylaing)[akehir](https://github.com/akehir)[RubenVermeulen](https://github.com/RubenVermeulen) + +[ryanmwright](https://github.com/ryanmwright)[scttcper](https://github.com/scttcper)[abshoff](https://github.com/abshoff)[SpazzMarticus](https://github.com/SpazzMarticus)[srenatus](https://github.com/srenatus) + +[sven-codeculture](https://github.com/sven-codeculture)[Rocket18](https://github.com/Rocket18)[Ceteareth](https://github.com/Ceteareth)[vadjs](https://github.com/vadjs)[Varada-Schneider](https://github.com/Varada-Schneider) + +[Gimly](https://github.com/Gimly)[akkaradej](https://github.com/akkaradej)[coyoteecd](https://github.com/coyoteecd)[darbio](https://github.com/darbio)[filipvh](https://github.com/filipvh) + +[kyubisation](https://github.com/kyubisation)[luciimon](https://github.com/luciimon)[mike-rivera](https://github.com/mike-rivera)[drobert-bfm](https://github.com/drobert-bfm)[roblabat](https://github.com/roblabat) + +[wdunn001](https://github.com/wdunn001)[adrianbenjuya](https://github.com/adrianbenjuya)[Andreas-Hjortland](https://github.com/Andreas-Hjortland)[adematte](https://github.com/adematte)[cgatian](https://github.com/cgatian) + +[dirkbolte](https://github.com/dirkbolte)[enricodeleo](https://github.com/enricodeleo)[Gregordy](https://github.com/Gregordy)[jeroenhinfi](https://github.com/jeroenhinfi)[linjie997](https://github.com/linjie997) + +[jfyne](https://github.com/jfyne)[kevincathcart-cas](https://github.com/kevincathcart-cas)[martin1cerny](https://github.com/martin1cerny)[marvinosswald](https://github.com/marvinosswald)[nick1699](https://github.com/nick1699) + +[paulyoder](https://github.com/paulyoder)[reda-alaoui](https://github.com/reda-alaoui)[remiburtin](https://github.com/remiburtin)[gingters](https://github.com/gingters)[kranich](https://github.com/kranich) + +[StefanoChiodino](https://github.com/StefanoChiodino)[tpeter1985](https://github.com/tpeter1985)[dennisameling](https://github.com/dennisameling)[dependabot[bot]](https://github.com/apps/dependabot)[jdgeier](https://github.com/jdgeier) + +[mraible](https://github.com/mraible)[ajpierson](https://github.com/ajpierson)[artnim](https://github.com/artnim)[fmalcher](https://github.com/fmalcher)[Flofie](https://github.com/Flofie) + +[mabdelaal86](https://github.com/mabdelaal86)[nhance](https://github.com/nhance)[Razzeee](https://github.com/Razzeee)[maxisam](https://github.com/maxisam)[ismcagdas](https://github.com/ismcagdas) + +[Toxicable](https://github.com/Toxicable)[ManuelRauber](https://github.com/ManuelRauber)[vdveer](https://github.com/vdveer)[jeroenheijmans](https://github.com/jeroenheijmans)[manfredsteyer](https://github.com/manfredsteyer) + + diff --git a/docs-src/authsvr-auth0.md b/docs-src/authsvr-auth0.md new file mode 100644 index 00000000..f8f9f78d --- /dev/null +++ b/docs-src/authsvr-auth0.md @@ -0,0 +1,57 @@ +# Using Auth0 + +To use this lib with Auth0, open your Auth0 account and configure: + +- An app +- An API + +Configure the app to use ``refresh token rotation`` and the grant types ``authorization code`` and ``refresh token``. For grant types, see the advanced settings at the end of the settings page. + +## Configuration + +Provide a configuration like this: + +```typescript +import { AuthConfig } from 'angular-oauth2-oidc'; + +export const authConfig: AuthConfig = { + + issuer: 'https://dev-g-61sdfs.eu.auth0.com/', + + // Your app's client id: + clientId: 'opHt1Tkt9E9fVQTZPBVF1tHVhjrxvyVX', + redirectUri: window.location.origin, + + scope: 'openid profile email offline_access', + + responseType: 'code', + + logoutUrl: 'https://dev-g-61sdfs.eu.auth0.com/v2/logout', + + customQueryParams: { + // Your API's name + audience: 'http://www.angular.at/api' + }, +}; +``` + +## Getting, Using, and Refreshing a Token + +This should work as shown in the other examples in this documentation and in the readme file. + +## Logging out + +Auth0's logout endpoint expects the parameters ``client_id`` and ``returnTo``: + +```typescript +this.oauthService.revokeTokenAndLogout({ + client_id: this.oauthService.clientId, + returnTo: this.oauthService.redirectUri +}, true); +``` + +The optional 2nd parameter set to ``true`` ignores CORS issues with the logout endpoint. + +## Example + +Please find a [demo](https://github.com/manfredsteyer/auth0-demo) for using Auth0 with angular-oauth2-oidc [here](https://github.com/manfredsteyer/auth0-demo). diff --git a/docs-src/authsvr-azure-ad.md b/docs-src/authsvr-azure-ad.md new file mode 100644 index 00000000..44b91e20 --- /dev/null +++ b/docs-src/authsvr-azure-ad.md @@ -0,0 +1,3 @@ +# Using with Azure AD + +For using this library with **Azure Active Directory** (**Azure AD**), we recommend an additional look to this [blog post](https://dev.to/yuriburger/azure-active-directory-b2c-with-pkce-for-your-angular-app-1dcg) and the example linked at the end of this blog post. diff --git a/docs-src/authsvr-idsvr.md b/docs-src/authsvr-idsvr.md new file mode 100644 index 00000000..cf403f05 --- /dev/null +++ b/docs-src/authsvr-idsvr.md @@ -0,0 +1,3 @@ +# Using Identity Server + +This lib should work as shown in all examples here with Identity Server. \ No newline at end of file diff --git a/docs-src/authsvr-keycloak.md b/docs-src/authsvr-keycloak.md new file mode 100644 index 00000000..865fb23c --- /dev/null +++ b/docs-src/authsvr-keycloak.md @@ -0,0 +1,3 @@ +# Using Keycloak + +This lib should work as shown in all examples here with Keycloak. \ No newline at end of file diff --git a/docs-src/authsvr.md b/docs-src/authsvr.md new file mode 100644 index 00000000..ab684907 --- /dev/null +++ b/docs-src/authsvr.md @@ -0,0 +1,5 @@ +# Support for Auth Servers + +As this lib follows the OAuth2 and OpenId Connect specs, it should work with all compliant authorizations servers. + +However, experience shows that some authorizations servers come with some special behavior or settings. Hence, we must respect this when using this lib. \ No newline at end of file diff --git a/docs-src/code-flow.bak.md b/docs-src/code-flow.bak.md new file mode 100644 index 00000000..f964e3e9 --- /dev/null +++ b/docs-src/code-flow.bak.md @@ -0,0 +1,66 @@ +# Code Flow + +Since Version 8, this library also supports code flow and [PKCE](https://tools.ietf.org/html/rfc7636) to align with the current draft of the [OAuth 2.0 Security Best Current Practice](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13) document. + + +To configure your solution for code flow + PKCE you have to set the `responseType` to `code`: + + ```TypeScript + + import { AuthConfig } from 'angular-oauth2-oidc'; + + export const authCodeFlowConfig: AuthConfig = { + // Url of the Identity Provider + issuer: 'https://demo.identityserver.io', + + // URL of the SPA to redirect the user to after login + redirectUri: window.location.origin + '/index.html', + + // The SPA's id. The SPA is registerd with this id at the auth-server + // clientId: 'server.code', + clientId: 'spa', + + // Just needed if your auth server demands a secret. In general, this + // is a sign that the auth server is not configured with SPAs in mind + // and it might not enforce further best practices vital for security + // such applications. + // dummyClientSecret: 'secret', + + responseType: 'code', + + // set the scope for the permissions the client should request + // The first four are defined by OIDC. + // Important: Request offline_access to get a refresh token + // The api scope is a usecase specific one + scope: 'openid profile email offline_access api', + + showDebugInformation: true, + + // Not recommented: + // disablePKCI: true, + }; + ``` + +After this, you can initialize the code flow using: + +```TypeScript + +this.oauthService.initCodeFlow(); +``` + +There is also a convenience method `initLoginFlow` which initializes either the code flow or the implicit flow depending on your configuration. + +```TypeScript +this.oauthService.initLoginFlow(); +``` + +Also -- as shown in the readme -- you have to execute the following code when bootstrapping to make the library to fetch the token: + +```TypeScript +this.oauthService.configure(authCodeFlowConfig); +this.oauthService.tokenValidationHandler = new JwksValidationHandler(); +this.oauthService.loadDiscoveryDocumentAndTryLogin(); +``` + + + diff --git a/docs-src/code-flow.md b/docs-src/code-flow.md new file mode 100644 index 00000000..91bba314 --- /dev/null +++ b/docs-src/code-flow.md @@ -0,0 +1,63 @@ +# Code Flow + +Since Version 8, this library also supports code flow and [PKCE](https://tools.ietf.org/html/rfc7636) to align with the current draft of the [OAuth 2.0 Security Best Current Practice](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13) document. + + +To configure your solution for code flow + PKCE you have to set the `responseType` to `code`: + + ```TypeScript + import { AuthConfig } from 'angular-oauth2-oidc'; + + export const authCodeFlowConfig: AuthConfig = { + // Url of the Identity Provider + issuer: 'https://demo.identityserver.io', + + // URL of the SPA to redirect the user to after login + redirectUri: window.location.origin + '/index.html', + + // The SPA's id. The SPA is registered with this id at the auth-server + // clientId: 'server.code', + clientId: 'spa', + + // Just needed if your auth server demands a secret. In general, this + // is a sign that the auth server is not configured with SPAs in mind + // and it might not enforce further best practices vital for security + // such applications. + // dummyClientSecret: 'secret', + + responseType: 'code', + + // set the scope for the permissions the client should request + // The first four are defined by OIDC. + // Important: Request offline_access to get a refresh token + // The api scope is a usecase specific one + scope: 'openid profile email offline_access api', + + showDebugInformation: true, + + // Not recommended: + // disablePKCE: true, + }; + ``` + +After this, you can initialize the code flow using: + + ```TypeScript + this.oauthService.initCodeFlow(); + ``` + +There is also a convenience method `initLoginFlow` which initializes either the code flow or the implicit flow depending on your configuration. + + ```TypeScript + this.oauthService.initLoginFlow(); + ``` + +Also -- as shown in the readme -- you have to execute the following code when bootstrapping to make the library to fetch the token: + +```TypeScript +this.oauthService.configure(authCodeFlowConfig); +this.oauthService.loadDiscoveryDocumentAndTryLogin(); +``` + + + diff --git a/docs-src/configure-custom-oauthstorage.md b/docs-src/configure-custom-oauthstorage.md new file mode 100644 index 00000000..4ef39783 --- /dev/null +++ b/docs-src/configure-custom-oauthstorage.md @@ -0,0 +1,42 @@ +# Configure custom OAuthStorage + +This library uses `sessionStorage` as the default storage provider. You can customize this by using `localStorage` or your own storage solution. + +## Using localStorage +If you want to use `localStorage` instead of `sessionStorage`, you can add a provider to your AppModule. This works as follows: + +```TypeScript +import { HttpClientModule } from '@angular/common/http'; +import { OAuthModule } from 'angular-oauth2-oidc'; +// etc. + +// We need a factory, since localStorage is not available during AOT build time. +export function storageFactory() : OAuthStorage { + return localStorage +} + +@NgModule({ + imports: [ + // etc. + HttpClientModule, + OAuthModule.forRoot() + ], + declarations: [ + AppComponent, + HomeComponent, + // etc. + ], + bootstrap: [ + AppComponent + ], + providers: [ + { provide: OAuthStorage, useFactory: storageFactory } + ] +}) +export class AppModule { +} +``` + +## Custom storage solution + +If you want to use a custom storage solution, you can extend the `OAuthStorage` class. Documentation can be found [here](../classes/OAuthStorage.html#info). Then add it as a provider, just like in the `localStorage` example above. \ No newline at end of file diff --git a/docs-src/custom-date-time-provider.md b/docs-src/custom-date-time-provider.md new file mode 100644 index 00000000..b4c57583 --- /dev/null +++ b/docs-src/custom-date-time-provider.md @@ -0,0 +1,45 @@ +# Custom DateTimeProvider + +If your Identity Provider's clock is not synchronized, the validation of the token could fail. +If the deviation is only some seconds, you can use the `AuthConfig.clockSkewInSec` setting to allow a bigger time window deviation. + +However, you may need to adjust the base time, that is used for the token validation and make sure, that the `AuthConfig.clockSkewInSec` is still a small reasonable number, then you can implement a custom `DateTimeProvider`. + +To do so, create a new service that derives from `DateTimeProvider`: + +```typescript +export class MyCustomDateTimeProvider extends DateTimeProvider { + now(): number { + // Return your custom now. + return Date.now(); + } + + new(): Date { + // Return your custom new Date(). + return new Date(); + } +} +``` + +Then, override the provider via dependency injection in your application: + +```typescript +@NgModule({ + imports: [ + // etc. + OAuthModule.forRoot() + ], + providers: [ + { provide: DateTimeProvider, useClass: MyCustomDateTimeProvider } // <- add this + ], + declarations: [ + AppComponent, + // etc. + ], + bootstrap: [ + AppComponent + ] +}) +export class AppModule { +} +``` diff --git a/docs-src/discovery-document-validation.md b/docs-src/discovery-document-validation.md new file mode 100644 index 00000000..8014c6d7 --- /dev/null +++ b/docs-src/discovery-document-validation.md @@ -0,0 +1,30 @@ +# Discovery Document Validation + +The configuration parameter `strictDiscoveryDocumentValidation` is set `true` by default. This ensures that all of the endpoints provided via the ID Provider discovery document share the same base URL as the `issuer` parameter. + +Several ID Providers (i.e. Google OpenID, WS02-IS, PingOne) provide different domains or path params for various endpoints in the discovery document. These providers may still adhere to the [OpenID Connect Provider Configuration specification](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse), but will fail to pass this library's discovery document validation. + +To use this library with an ID Provider that does not maintain a consistent base URL across the discovery document endpoints, set the `strictDiscoveryDocumentValidation` parameter to `false` in your configuration: + +```TypeScript +import { AuthConfig } from 'angular-oauth2-oidc'; + +export const authConfig: AuthConfig = { + + // Url of the Identity Provider + issuer: 'https://steyer-identity-server.azurewebsites.net/identity', + + // URL of the SPA to redirect the user to after login + redirectUri: window.location.origin + '/index.html', + + // The SPA's id. The SPA is registerd with this id at the auth-server + clientId: 'spa-demo', + + // set the scope for the permissions the client should request + // The first three are defined by OIDC. The 4th is a usecase-specific one + scope: 'openid profile email voucher', + + // turn off validation that discovery document endpoints start with the issuer url defined above + strictDiscoveryDocumentValidation: false +} +``` \ No newline at end of file diff --git a/docs-src/events.md b/docs-src/events.md index 4c7e5c6e..8c050226 100644 --- a/docs-src/events.md +++ b/docs-src/events.md @@ -1,11 +1,39 @@ # Events -The library informs you about its tasks and state using events: +The library informs you about its tasks and state using [events](https://manfredsteyer.github.io/angular-oauth2-oidc/docs/injectables/OAuthService.html#events). +This is an `Observable` which publishes a stream of events as they occur in the service. +You can log these events to the console for debugging information. + +A short snippet you could use: ```TypeScript -this.oauthService.events.subscribe(e => { - console.debug('oauth/oidc event', e); -}) +this.oauthService.events.subscribe(e => console.log(e)); ``` -For a full list of available events see the string based enum in the file ``events.ts``. +Or a longer, more extensive version that logs them at different levels: + +```TypeScript +import { OAuthErrorEvent } from 'angular-oauth2-oidc'; + +// ... + +this.authService.events.subscribe(event => { + if (event instanceof OAuthErrorEvent) { + console.error(event); + } else { + console.warn(event); + } +}); +``` + +Here's a list of the main events you might encounter: + +- `discovery_document_loaded` is published whenever the service has retrieved the openid configuration and successfully saved the `jwks` information +- `invalid_nonce_in_state` is published during `tryLogin`, when an access token has been requested and the state check was not disabled via the options, only in case the nonce is not as expected (see OAuth2 spec for more details about the nonce) +- `user_profile_loaded` is published just before `loadUserProfile()` successfully resolves +- `token_received` is published whenever the requested token(s) have been successfully received and stored +- `silently_refreshed` is published when the silent refresh timer has gone off and the library has also successfully refreshed the tokens (only applicable to Implicit Flow) +- `silent_refresh_timeout` is published if the silent refresh timer has gone off but it takes too long to successfully refresh +- `session_error` will only be published if the session checks encounter an error + +For a full list of available events see the string based enum in [the file `events.ts`](https://github.com/manfredsteyer/angular-oauth2-oidc/blob/master/projects/lib/src/events.ts). diff --git a/docs-src/implicit-flow-config-discovery.md b/docs-src/implicit-flow-config-discovery.md index b29f4e4a..cc4d506a 100644 --- a/docs-src/implicit-flow-config-discovery.md +++ b/docs-src/implicit-flow-config-discovery.md @@ -1,5 +1,7 @@ # Original Config API +> This describes the older config API which is nowadays only supported for the sake of backwards compatibility. + To configure the library you just have to set some properties on startup. For this, the following sample uses the constructor of the AppComponent which is called before routing kicks in. Please note that the following sample uses the original config API. For information about the new config API have a look to the project's README above. @@ -37,3 +39,5 @@ export class AppComponent { } ``` + +If you find yourself receiving errors related to discovery document validation, your ID Provider may have OAuth2 endpoints that do not use the `issuer` value as a consistent base URL. You can turn off strict validation of discovery document endpoints for this scenario. See [Discovery Document Validation](https://manfredsteyer.github.io/angular-oauth2-oidc/docs/additional-documentation/discovery-document-validation.html) for details. \ No newline at end of file diff --git a/docs-src/implicit-flow.md b/docs-src/implicit-flow.md new file mode 100644 index 00000000..38a490dd --- /dev/null +++ b/docs-src/implicit-flow.md @@ -0,0 +1,106 @@ +## Configuring for Implicit Flow + +This section shows how to implement login leveraging implicit flow. This is the OAuth2/OIDC flow which was originally intended for Single Page Application. + +Meanwhile using **Code Flow** instead is a **best practice** and with OAuth 2.1 implicit flow will be **deprecated***. + +```TypeScript +import { AuthConfig } from 'angular-oauth2-oidc'; + +export const authConfig: AuthConfig = { + // Url of the Identity Provider + issuer: 'https://steyer-identity-server.azurewebsites.net/identity', + + // URL of the SPA to redirect the user to after login + redirectUri: window.location.origin + '/index.html', + + // The SPA's id. The SPA is registered with this id at the auth-server + clientId: 'spa-demo', + + // set the scope for the permissions the client should request + // The first three are defined by OIDC. The 4th is a usecase-specific one + scope: 'openid profile email voucher', +} +``` + +Configure the ``OAuthService`` with this config object when the application starts up: + +```TypeScript +import { OAuthService } from 'angular-oauth2-oidc'; +import { JwksValidationHandler } from 'angular-oauth2-oidc'; +import { authConfig } from './auth.config'; +import { Component } from '@angular/core'; + +@Component({ + selector: 'flight-app', + templateUrl: './app.component.html' +}) +export class AppComponent { + + constructor(private oauthService: OAuthService) { + this.configure(); + } + + private configure() { + this.oauthService.configure(authConfig); + this.oauthService.tokenValidationHandler = new JwksValidationHandler(); + this.oauthService.loadDiscoveryDocumentAndTryLogin(); + } +} +``` + +### Implementing a Login Form + +After you've configured the library, you just have to call ``initImplicitFlow`` to login using OAuth2/ OIDC. + +```TypeScript +import { Component } from '@angular/core'; +import { OAuthService } from 'angular-oauth2-oidc'; + +@Component({ + templateUrl: "app/home.html" +}) +export class HomeComponent { + + constructor(private oauthService: OAuthService) { + } + + public login() { + this.oauthService.initLoginFlow(); + } + + public logoff() { + this.oauthService.logOut(); + } + + public get name() { + let claims = this.oauthService.getIdentityClaims(); + if (!claims) return null; + return claims.given_name; + } + +} +``` + +The following snippet contains the template for the login page: + +```HTML +

+ Hallo +

+

+ Hallo, {{name}} +

+ + + + +
+ Username/Passwort zum Testen: max/geheim +
+``` + diff --git a/docs-src/password-flow.md b/docs-src/password-flow.md index 8ed366de..24841c75 100644 --- a/docs-src/password-flow.md +++ b/docs-src/password-flow.md @@ -2,9 +2,11 @@ This section shows how to use the password flow, which demands the user to directly enter his or her password into the client. -Please note that from an OAuth2/OIDC perspective, the implicit flow is better suited for logging into a SPA and the flow described here should only be used, +Please note that from an OAuth2/OIDC perspective, the code flow is better suited for logging into a SPA and the flow described here should only be used, when a) there is a strong trust relations ship between the client and the auth server and when b) other flows are not possible. +Please also note that with **OAuth 2.1**, **password flow** will be **deprecated**. + ## Configure Library for Password Flow (using discovery document) To configure the library you just have to set some properties on startup. For this, the following sample uses the constructor of the AppComponent which is called before routing kicks in. diff --git a/docs-src/popup.md b/docs-src/popup.md new file mode 100644 index 00000000..6087b45c --- /dev/null +++ b/docs-src/popup.md @@ -0,0 +1,13 @@ +# Logging in With a Popup + +Thanks to a great community contribution, this library also supports logging the user in via a popup. For this, you need to do two things: + +- Use ``initLoginFlowInPopup`` instead of ``initLoginFlow``. +- Create and configure a ``silent-refresh.html`` as described [here](./silent-refresh.md) *. + +\* Please note this does not mean that you have to use silent refresh too. + +Also, for your ``silent-refresh.html``, make sure you are also targeting +``window.opener`` and fall back to ``window.parent``: + +**Please note**: IE sets opener to null under specific security settings. This prevents making this work. diff --git a/docs-src/session-checks.md b/docs-src/session-checks.md index b8b76b2a..b7ad2331 100644 --- a/docs-src/session-checks.md +++ b/docs-src/session-checks.md @@ -29,6 +29,12 @@ export const authConfig: AuthConfig = { } ``` +## Refresh + +Please note that the lib performs a token refresh when the session changes to get the newest information about the current session. When using implicit flow, this means you have to configure [silent refresh](./silent-refresh.html); when using code flow you either need silent refresh or a [refresh token](./refreshing-a-token.html). + +If using refresh tokens, your Auth Server needs to bind them to the current session's lifetime. Unfortunately, the used version of Identity Server 4, shown in the docs and in the example applications, does not support this at the moment. + ## Events To get notified, you can hook up for the event ``session_terminated``: diff --git a/docs-src/silent-refresh.md b/docs-src/silent-refresh.md index 0fba058f..3c232a3c 100644 --- a/docs-src/silent-refresh.md +++ b/docs-src/silent-refresh.md @@ -1,6 +1,8 @@ -# Refreshing a Token when using Implicit Flow (Silent Refresh) +## Refreshing when using Implicit Flow (Implicit Flow and Code Flow) -To refresh your tokens when using implicit flow you can use a silent refresh. This is a well-known solution that compensates the fact that implicit flow does not allow for issuing a refresh token. It uses a hidden iframe to get another token from the auth-server. When the user is there still logged in (by using a cookie) it will respond without user interaction and provide new tokens. +**Notes for Code Flow**: You can also use this strategy for refreshing tokens when using code flow. However, please note, the strategy described within [Token Refresh](./token-refresh.html) is far easier in this case. + +To refresh your tokens when using implicit flow you can use a silent refresh. This is a well-known solution that compensates the fact that implicit flow does not allow for issuing a refresh token. It uses a hidden iframe to get another token from the auth server. When the user is there still logged in (by using a cookie) it will respond without user interaction and provide new tokens. To use this approach, setup a redirect uri for the silent refresh. @@ -22,6 +24,11 @@ export const authConfig: AuthConfig = { // URL of the SPA to redirect the user after silent refresh silentRefreshRedirectUri: window.location.origin + '/silent-refresh.html', + // defaults to true for implicit flow and false for code flow + // as for code code the default is using a refresh_token + // Also see docs section 'Token Refresh' + useSilentRefresh: true, + // The SPA's id. The SPA is registerd with this id at the auth-server clientId: 'spa-demo', @@ -45,12 +52,48 @@ This file is loaded into the hidden iframe after getting new tokens. Its only ta ``` +This simple implementation within silent-refresh.html is sufficient in most cases. It takes care of the hash fragment as well as of the query string (property search). For **edge cases** you need to check if the received hash fragment is a token response. For this, please go with the following **more advanced implementation**: + +```html + + + + + +``` +The above example checks if the message in the URL (either hash or query string) is indeed a message returned with a response from an authentication provider and not an arbitrary value and then attempts to forward this message to a parent widow either by `.parent` (when this html is loaded in an iframe as a result of silent refresh) or by `.opener` (when the html is loaded into a popup during initial login) or finally using a storage event (as a fallback for complex cases, e.g. initial login in a popup with a cross-domain auth provider). + + Please make sure that this file is copied to your output directory by your build task. When using the CLI you can define it as an asset for this. For this, you have to add the following line to the file ``.angular-cli.json``: ```JSON @@ -72,7 +115,8 @@ this When there is an error in the iframe that prevents the communication with the main application, silentRefresh will give you a timeout. To configure the timespan for this, you can set the property ``silentRefreshTimeout`` (msec). The default value is 20.000 (20 seconds). -### Automatically refreshing a token when/ before it expires +### Automatically refreshing a token when/ before it expires (Code Flow and Implicit Flow) + To automatically refresh a token when/ some time before it expires, just call the following method after configuring the OAuthService: diff --git a/docs-src/skipping-login-form.md b/docs-src/skipping-login-form.md new file mode 100644 index 00000000..3c0f54b3 --- /dev/null +++ b/docs-src/skipping-login-form.md @@ -0,0 +1,36 @@ +# Manually Skipping the Login Form + +First, try to use the ``loadDiscoveryDocumentAndLogin`` method instead of ``loadDiscoveryDocumentAndTryLogin``. If you need more control, the following could be interesting for you. + +```TypeScript +this.oauthService + .loadDiscoveryDocumentAndTryLogin(/* { your LoginOptions }*/) // checks to see if the current url contains id token and access token + .(hasReceivedTokens => { + // this would have stored all the tokens needed + if (hasReceivedTokens) { + // carry on with your app + return Promise.resolve(); + + /* if you wish to do something when the user receives tokens from the identity server, + * use the event stream or the `onTokenReceived` callback in LoginOptions. + * + * this.oauthService.events(filter(e => e.type === 'token_received')).subscribe() + */ + } else { + // may want to check if you were previously authenticated + if (this.oauthService.hasValidAccessToken() && this.oauthService.hasValidIdToken()) { + return Promise.resolve(); + } else { + // to safe guard this from progressing through the calling promise, + // resolve it when it directed to the sign up page + return new Promise(resolve => { + this.oauthService.initLoginFlow(); + // example if you are using explicit flow + this.window.addEventListener('unload', () => { + resolve(true); + }); + }); + } + } + }) +``` \ No newline at end of file diff --git a/docs-src/summary.json b/docs-src/summary.json index fdeb85c0..454bd44e 100644 --- a/docs-src/summary.json +++ b/docs-src/summary.json @@ -8,9 +8,17 @@ "file": "preserving-state.md" }, { - "title": "Refreshing a Token (Silent Refresh)", + "title": "Refreshing a Token", + "file": "token-refresh.md" + }, + { + "title": "Silent Refresh", "file": "silent-refresh.md" }, + { + "title": "Token Refresh", + "file": "token-refresh.md" + }, { "title": "Working with HttpInterceptors", "file": "interceptors.md" @@ -19,6 +27,10 @@ "title": "Callback after login", "file": "callback-after-login.md" }, + { + "title": "Popup-based Login", + "file": "popup.md" + }, { "title": "Custom Query Parameters", "file": "custom-query-parameter.md" @@ -47,16 +59,55 @@ "title": "Configure Library for Implicit Flow without discovery document", "file": "implicit-flow-config-no-discovery.md" }, + { + "title": "Using an ID Provider that Fails Discovery Document Validation", + "file": "discovery-document-validation.md" + }, { "title": "Using SystemJS", "file": "systemjs.md" }, { - "title": "Original Config API", - "file": "implicit-flow-config-discovery.md" + "title": "Using Implicit Flow", + "file": "implicit-flow.md" }, { "title": "Using Password Flow", "file": "password-flow.md" + }, + { + "title": "Configure custom OAuthStorage", + "file": "configure-custom-oauthstorage.md" + }, + { + "title": "Manually Skipping Login Form", + "file": "skipping-login-form.md" + }, + { + "title": "Original Config API", + "file": "implicit-flow-config-discovery.md" + }, + { + "title": "Authorization Servers", + "file": "authsvr.md", + "children": [ + { + "title": "Using Identity Server", + "file": "authsvr-idsvr.md" + }, + { + "title": "Using Keycloak", + "file": "authsvr-keycloak.md" + }, + { + "title": "Auth0", + "file": "authsvr-auth0.md" + }, + { + "title": "Azure AD (Active Directory)", + "file": "authsvr-azure-ad.md" + } + ] } + ] diff --git a/docs-src/token-refresh.md b/docs-src/token-refresh.md new file mode 100644 index 00000000..d79af269 --- /dev/null +++ b/docs-src/token-refresh.md @@ -0,0 +1,22 @@ +# Refreshing a Token using Code Flow (not Implicit Flow!) + +When using code flow, you can get an ``refresh_token``. While the original standard DOES NOT allow this for SPAs, the mentioned [OAuth 2.0 Security Best Current Practice](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13) document proposes to ease this limitation. However, it specifies a list of requirements one should take care about before using ``refresh_tokens``. Please make sure you respect those requirements. + +Please also note, that you have to request the ``offline_access`` scope to get a refresh token. + +To refresh your token, just call the ``refreshToken`` method: + +```typescript +this.oauthService.refreshToken(); +``` + + +## Automatically refreshing a token when/ before it expires (Code Flow and Implicit Flow) + +To automatically refresh a token when/ some time before it expires, just call the following method after configuring the ``OAuthService``: + +```TypeScript +this.oauthService.setupAutomaticSilentRefresh(); +``` + +By default, this event is fired after 75% of the token's life time is over. You can adjust this factor by setting the property ``timeoutFactor`` to a value between 0 and 1. For instance, 0.5 means, that the event is fired after half of the life time is over and 0.33 triggers the event after a third. diff --git a/docs/additional-documentation/adapt-id_token-validation.html b/docs/additional-documentation/adapt-id_token-validation.html index 0d875738..87e77f21 100644 --- a/docs/additional-documentation/adapt-id_token-validation.html +++ b/docs/additional-documentation/adapt-id_token-validation.html @@ -8,595 +8,34 @@ - + + -