├── .circleci
└── config.yml
├── .editorconfig
├── .github
├── CODEOWNERS
├── ISSUE_TEMPLATE.md
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .lintstagedrc
├── .prettierignore
├── .prettierrc
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── commitlint.config.js
├── lerna.json
├── package.json
├── packages
└── @ngx-auth
│ ├── auth0
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── ng-package.json
│ ├── package.json
│ ├── src
│ │ ├── auth0-server.service.ts
│ │ ├── auth0.loader.ts
│ │ ├── auth0.module.ts
│ │ ├── auth0.service.ts
│ │ ├── index.ts
│ │ └── models
│ │ │ ├── auth0-backend.ts
│ │ │ └── auth0-settings.ts
│ └── tests
│ │ ├── __mocks__
│ │ └── auth0-js.ts
│ │ ├── auth0-server.service.spec.ts
│ │ ├── auth0.loader.spec.ts
│ │ ├── auth0.service.spec.ts
│ │ └── common.ts
│ └── core
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── ng-package.json
│ ├── package.json
│ ├── src
│ ├── auth-server.guard.ts
│ ├── auth-server.service.ts
│ ├── auth.guard.ts
│ ├── auth.loader.ts
│ ├── auth.module.ts
│ ├── auth.service.ts
│ ├── index.ts
│ └── models
│ │ ├── auth-settings.ts
│ │ └── backend.ts
│ ├── testing
│ ├── auth.testing.module.ts
│ └── mocks
│ │ ├── backend-interceptor.mock.ts
│ │ └── jwt-interceptor.mock.ts
│ └── tests
│ ├── auth-server.guard.spec.ts
│ ├── auth-server.service.spec.ts
│ ├── auth.guard.spec.ts
│ ├── auth.loader.spec.ts
│ ├── auth.service.spec.ts
│ └── common.ts
├── tools
├── build
│ ├── helpers.ts
│ ├── packager.ts
│ └── tsconfig.package.json
├── test
│ └── jest.setup.ts
└── tslint.json
├── tsconfig.json
├── tsconfig.lint.json
├── tslint.json
└── yarn.lock
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | jobs:
3 | build:
4 | docker:
5 | - image: circleci/node:10-browsers
6 | environment:
7 | JOBS: 1
8 | steps:
9 | - checkout
10 | - run: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
11 | - run: git config --global user.email ${GH_USER_EMAIL}
12 | - run: git config --global user.name ${GH_USER_NAME}
13 | - run: sudo yarn global add greenkeeper-lockfile@1
14 | - run: sudo yarn global add lerna@3
15 | - restore_cache:
16 | keys:
17 | - deps-{{ .Branch }}-{{ checksum "yarn.lock" }}
18 | - deps-
19 | - run: yarn
20 | - save_cache:
21 | key: deps-{{ .Branch }}-{{ checksum "yarn.lock" }}
22 | paths: 'node_modules'
23 | - run: yarn ci:before
24 | - run: yarn test:ci
25 | - run: if [ ${CIRCLE_BRANCH} == "master" ]; then lerna version --create-release github --yes; fi
26 | - run: yarn build
27 | - run: yarn ci:after
28 | - run: if [ ${CIRCLE_BRANCH} == "master" ]; then lerna publish from-package --yes; fi
29 | - run: bash <(curl -s https://codecov.io/bash)
30 | - store_artifacts:
31 | path: coverage
32 | prefix: coverage
33 | - store_artifacts:
34 | path: dist
35 | prefix: dist
36 | - store_test_results:
37 | path: test-report.xml
38 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | indent_style = space
8 | indent_size = 2
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | max_line_length = 140
14 | trim_trailing_whitespace = false
15 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # More about this https://help.github.com/articles/about-codeowners/
2 | * @fulls1z3
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
6 |
7 | **I'm submitting a ...** (check one with "x")
8 | ```
9 | [ ] Regression (a behavior that used to work and stopped working in a new release)
10 | [ ] Bug report
11 | [ ] Support request =>
12 | [ ] Feature request
13 | [ ] Documentation issue or request
14 | ```
15 |
16 | **Current behavior**
17 |
18 |
19 | **Expected/desired behavior**
20 |
21 |
22 | **Minimal reproduction of the problem with instructions**
23 |
27 |
28 | **What is the motivation / use case for changing the behavior?**
29 |
30 |
31 | **Environment**
32 | * **Angular version:** X.Y.Z
33 |
34 |
35 | * **Browser:**
36 | - [ ] Chrome (desktop) version XX
37 | - [ ] Chrome (Android) version XX
38 | - [ ] Chrome (iOS) version XX
39 | - [ ] Firefox version XX
40 | - [ ] Safari (desktop) version XX
41 | - [ ] Safari (iOS) version XX
42 | - [ ] IE version XX
43 | - [ ] Edge version XX
44 |
45 | * **For Tooling issues:**
46 | - Node version: XX
47 | - Platform:
48 |
49 | * Others:
50 |
51 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ** PR Checklist
2 | Please check if your PR fulfills the following requirements:
3 |
4 | - [ ] The commit message follows our guidelines: https://github.com/fulls1z3/ngx-auth/blob/master/CONTRIBUTING.md#commit
5 | - [ ] Tests for the changes have been added (for bug fixes / features)
6 | - [ ] Docs have been added / updated (for bug fixes / features)
7 |
8 | ** PR Type
9 | What kind of change does this PR introduce?
10 |
11 |
12 | ```
13 | [ ] Bugfix
14 | [ ] Feature
15 | [ ] Code style update (formatting, local variables)
16 | [ ] Refactoring (no functional changes, no api changes)
17 | [ ] Build related changes
18 | [ ] CI related changes
19 | [ ] Documentation content changes
20 | [ ] Other... Please describe:
21 | ```
22 |
23 | ** What is the current behavior?
24 |
25 |
26 | Issue Number: N/A
27 |
28 | ** What is the new behavior?
29 |
30 | ** Does this PR introduce a breaking change?
31 | ```
32 | [ ] Yes
33 | [ ] No
34 | ```
35 |
36 |
37 |
38 | ** Other information
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | /node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | .c9/
16 | *.launch
17 | .settings/
18 | *.sublime-workspace
19 |
20 | # IDE - VSCode
21 | .vscode/*
22 | !.vscode/settings.json
23 | !.vscode/tasks.json
24 | !.vscode/launch.json
25 | !.vscode/extensions.json
26 |
27 | # misc
28 | /.sass-cache
29 | /connect.lock
30 | /coverage
31 | /libpeerconnection.log
32 | npm-debug.log
33 | yarn-error.log
34 | testem.log
35 | test-report.xml
36 | /typings
37 |
38 | # System Files
39 | .DS_Store
40 | Thumbs.db
41 |
--------------------------------------------------------------------------------
/.lintstagedrc:
--------------------------------------------------------------------------------
1 | {
2 | "*.{json,css,scss,md,js}": ["prettier --write", "git add"],
3 | "*.(ts)": ["prettier-tslint fix", "git add"]
4 | }
5 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | # Add files here to ignore them from prettier formatting
2 |
3 | # compiled output
4 | /dist
5 | /docs
6 | /tmp
7 | /out-tsc
8 |
9 | # dependencies
10 | /node_modules
11 |
12 | # IDEs and editors
13 | /.idea
14 | .project
15 | .classpath
16 | .c9/
17 | *.launch
18 | .settings/
19 | *.sublime-workspace
20 |
21 | # IDE - VSCode
22 | .vscode/*
23 | !.vscode/settings.json
24 | !.vscode/tasks.json
25 | !.vscode/launch.json
26 | !.vscode/extensions.json
27 |
28 | # misc
29 | /.sass-cache
30 | /connect.lock
31 | /coverage
32 | /libpeerconnection.log
33 | npm-debug.log
34 | yarn-error.log
35 | testem.log
36 | test-report.xml
37 | /typings
38 |
39 | # System Files
40 | .DS_Store
41 | Thumbs.db
42 |
43 | # others
44 | /tools
45 | angular.json
46 | yarn.lock
47 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 140,
3 | "singleQuote": true
4 | }
5 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | # [9.0.0](https://github.com/fulls1z3/ngx-auth/compare/v8.1.0...v9.0.0) (2020-04-27)
7 |
8 |
9 | ### Features
10 |
11 | * **package:** migrate to ng9 ([0a1c4c1](https://github.com/fulls1z3/ngx-auth/commit/0a1c4c11d8cfa3e9649d713da0797b5cdd815d35))
12 | * **package:** migrate to ng9 ([b606776](https://github.com/fulls1z3/ngx-auth/commit/b606776586c2144c3f7594591e91d800d58d450f))
13 |
14 |
15 | ### BREAKING CHANGES
16 |
17 | * **package:** ng9
18 | * **package:** ng9
19 |
20 |
21 |
22 |
23 |
24 | # [8.1.0](https://github.com/fulls1z3/ngx-auth/compare/v8.0.1...v8.1.0) (2020-04-27)
25 |
26 |
27 | ### Bug Fixes
28 |
29 | * **packaging:** fix deployment ([#131](https://github.com/fulls1z3/ngx-auth/issues/131)) ([a43baf5](https://github.com/fulls1z3/ngx-auth/commit/a43baf5f48edf7cc200d06c08fbae005ee17e0cd))
30 | * **packaging:** fix deployment ([#132](https://github.com/fulls1z3/ngx-auth/issues/132)) ([a769718](https://github.com/fulls1z3/ngx-auth/commit/a769718c0a2ce3e0545a23aaa2a86ee4c6a0bc51))
31 |
32 |
33 | ### Features
34 |
35 | * **package:** migrate to ng9 ([#134](https://github.com/fulls1z3/ngx-auth/issues/134)) ([e37267e](https://github.com/fulls1z3/ngx-auth/commit/e37267ef3128ef8bb6eea38941c671e1a6010e51))
36 |
37 |
38 |
39 |
40 |
41 | ## [8.0.1](https://github.com/fulls1z3/ngx-auth/compare/v8.0.0...v8.0.1) (2019-11-21)
42 |
43 | **Note:** Version bump only for package ngx-auth
44 |
45 |
46 |
47 |
48 |
49 | # [8.0.0](https://github.com/fulls1z3/ngx-auth/compare/v6.0.0-rc.1...v8.0.0) (2019-11-21)
50 |
51 |
52 | ### Bug Fixes
53 |
54 | * **packaging:** fix publish ([b7fb206](https://github.com/fulls1z3/ngx-auth/commit/b7fb20686ca63859ec84e0b39ee60df71e733e9b))
55 |
56 |
57 | ### Features
58 |
59 | * **package:** upgrade to angular 8 ([5a973f6](https://github.com/fulls1z3/ngx-auth/commit/5a973f66e49aec265002f60b9cb6c39441d8884c))
60 |
61 |
62 | ### BREAKING CHANGES
63 |
64 | * **package:** ng8
65 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at mail@buraktasci.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to ngx-auth
2 |
3 | We would love for you to contribute to **`ngx-auth`** and help make it even better than it is today! As a contributor,
4 | here are the guidelines we would like you to follow:
5 |
6 | - [Code of Conduct](#coc)
7 | - [Issues and Bugs](#issue)
8 | - [Feature requests](#feature)
9 | - [Submission guidelines](#submit)
10 | - [Coding rules](#rules)
11 | - [Commit message guidelines](#commit)
12 |
13 | ## Code of Conduct
14 | Help us keep **`ngx-auth`** open and inclusive. Please read and follow our [Code of Conduct][coc].
15 |
16 | ## Found a Bug?
17 | If you find a bug in the source code, you can help us by [submitting an issue](#submit-issue) to our [GitHub Repository][github].
18 |
19 | Even better, you can [submit a Pull Request](#submit-pr) with a fix.
20 |
21 | ## Missing a Feature?
22 | You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub Repository.
23 |
24 | If you would like to *implement* a new feature, please submit an issue with a proposal for your work first, to be sure that
25 | we can use it.
26 |
27 | Please consider what kind of change it is:
28 | * For a **Major Feature**, first open an issue and outline your proposal so that it can be discussed.
29 | This will also allow us to better coordinate our efforts, prevent duplication of work, and help you to craft the change
30 | so that it is successfully accepted into the project.
31 | * **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
32 |
33 | ## Submission guidelines
34 | ### Submitting an Issue
35 | Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion
36 | might inform you of workarounds readily available.
37 |
38 | We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order
39 | to reproduce bugs we will systematically ask you to provide a minimal reproduction scenario using http://plnkr.co.
40 |
41 | Having a live, reproducible scenario gives us wealth of important information without going back & forth to you with additional
42 | questions like:
43 | - version used
44 | - 3rd-party libraries and their versions
45 | - and most importantly: a use-case that fails
46 |
47 | A minimal reproduce scenario using http://plnkr.co/ allows us to quickly confirm a bug (or point out coding problem) as
48 | well as confirm that we are fixing the right problem. If plunker is not a suitable way to demonstrate the problem (*ex:
49 | issues related to our npm packaging*), please create a standalone git repository demonstrating the problem.
50 |
51 | We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more
52 | bugs.
53 |
54 | Interestingly, from our experience users often find coding problems themselves while preparing a minimal plunk. We understand
55 | that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate
56 | the problem before we can fix it.
57 |
58 | Unfortunately we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you,
59 | we are going to close an issue that don't have enough info to be reproduced.
60 |
61 | You can file new issues by filling out our [new issue form](https://github.com/fulls1z3/ngx-auth/issues/new).
62 |
63 | ### Submitting a Pull Request (PR)
64 | Before you submit your Pull Request (PR) consider the following guidelines:
65 |
66 | * Search [GitHub](https://github.com/fulls1z3/ngx-auth/pulls) for an open or closed PR that relates to your submission.
67 | You don't want to duplicate effort.
68 | * Make your changes in a new git branch:
69 | ```shell
70 | git checkout -b my-fix-branch master
71 | ```
72 | * Create your patch, **including appropriate test cases**.
73 | * Follow our [Coding rules](#rules).
74 | * Run the full test suite and ensure that all tests pass.
75 | * Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit).
76 | Adherence to these conventions is necessary because release notes are automatically generated from these messages.
77 | ```shell
78 | git commit -a
79 | ```
80 | Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
81 | * Push your branch to GitHub:
82 | ```shell
83 | git push origin my-fix-branch
84 | ```
85 | * In GitHub, send a pull request to `ngx-auth:master`.
86 | * If we suggest changes then:
87 | * Make the required updates.
88 | * Re-run the test suites to ensure tests are still passing.
89 | * Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
90 | ```shell
91 | git rebase master -i
92 | git push -f
93 | ```
94 | That's it, thanks for your contribution!
95 |
96 | #### After your pull request is merged
97 | After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
98 | * Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
99 | ```shell
100 | git push origin --delete my-fix-branch
101 | ```
102 | * Check out the master branch:
103 | ```shell
104 | git checkout master -f
105 | ```
106 | * Delete the local branch:
107 | ```shell
108 | git branch -D my-fix-branch
109 | ```
110 | * Update your master with the latest upstream version:
111 | ```shell
112 | git pull --ff upstream master
113 | ```
114 |
115 | ## Coding rules
116 | To ensure consistency throughout the source code, keep these rules in mind as you are working:
117 | * All features or bug fixes **must be tested** by one or more specs (unit-tests).
118 | * All public API methods **must be documented**. (Details TBC).
119 | * We follow [fulls1z3's Angular TSLint rules][angular-tslint-rules].
120 |
121 | ## Commit message guidelines
122 | We have very precise rules over how our git commit messages can be formatted. This leads to **more readable messages** that
123 | are easy to follow when looking through the **project history**. But also, we use the git commit messages to **generate
124 | the `ngx-auth` change log**.
125 |
126 | ### Commit Message Format
127 | Each commit message consists of a **header**, a **body** and a **footer**. The header has a special format that includes
128 | a **type**, a **scope** (*when applicable*) and a **subject**:
129 | ```
130 | ():
131 |
132 |
133 |
134 |
135 | ```
136 |
137 | The **header** is mandatory and the **scope** of the header is optional.
138 |
139 | Any line of the commit message cannot be longer 100 characters. This allows the message to be easier to read on GitHub as
140 | well as in various git tools.
141 |
142 | Footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/)
143 | if any.
144 |
145 | Samples: (even more [samples](https://github.com/fulls1z3/ngx-auth/commits/master))
146 | ```
147 | docs(changelog): update change log to alpha.4
148 | ```
149 | ```
150 | fix(release): need to depend on latest rxjs and zone.js
151 |
152 | The version in our package.json gets copied to the one we publish, and users need the latest of these.
153 | ```
154 |
155 | ### Revert
156 | If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit.
157 | In the body it should say: `This reverts commit .`, where the hash is the SHA of the commit being reverted.
158 |
159 | ### Type
160 | Must be one of the following:
161 | * **build**: Changes that affect the build system or external dependencies (example scopes: gulp, npm, webpack)
162 | * **ci**: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, etc)
163 | * **docs**: Documentation only changes
164 | * **feat**: A new feature
165 | * **fix**: A bug fix
166 | * **perf**: A code change that improves performance
167 | * **refactor**: A code change that neither fixes a bug nor adds a feature
168 | * **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
169 | * **test**: Adding missing tests or correcting existing tests
170 |
171 | ### Scope
172 | The scope should be the name of the project affected.
173 |
174 | The following is the list of supported scopes:
175 | * **core**
176 | * **auth0**
177 |
178 | There are currently a few exceptions to the "use project name" rule:
179 |
180 | * **packaging**: used for changes that change the package layout (*e.g. package.json, bundles, path changes, etc.*)
181 | * **changelog**: used for updating the release notes in CHANGELOG.md
182 |
183 | ### Subject
184 | The subject contains succinct description of the change:
185 | * use the imperative, present tense: "change" not "changed" nor "changes"
186 | * don't capitalize first letter
187 | * no dot (.) at the end
188 |
189 | ### Body
190 | Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes". The body should include
191 | the motivation for the change and contrast this with previous behavior.
192 |
193 | ### Footer
194 | The footer should contain any information about **Breaking Changes** and is also the place to reference GitHub issues that
195 | this commit **Closes**.
196 |
197 | **Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit
198 | message is then used for this.
199 |
200 | [coc]: https://github.com/fulls1z3/ngx-auth/blob/master/CODE_OF_CONDUCT.md
201 | [github]: https://github.com/fulls1z3/ngx-auth
202 | [angular-tslint-rules]: https://github.com/fulls1z3/angular-tslint-rules
203 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Burak Tasci
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ngx-auth
2 |
3 | **[Auth0]** platform implementation and JWT authentication utility for **Angular** & **Angular Universal**
4 |
5 | [](https://circleci.com/gh/fulls1z3/ngx-auth)
6 | [](https://codecov.io/gh/fulls1z3/ngx-auth)
7 | [](https://github.com/facebook/jest)
8 | [](https://conventionalcommits.org)
9 | [](https://greenkeeper.io/)
10 | [](https://angular.io/styleguide)
11 |
12 | > Please support this project by simply putting a Github star. Share this library with friends on Twitter and everywhere else you can.
13 |
14 | **`@ngx-auth/core`** is a basic JWT-based authentication utility used for logging in and out of the **Angular** application
15 | and restrict unauthenticated access from accessing restricted routes.
16 |
17 | As of version **`5.1.0`**, the library contains **[Auth0]** implementation.
18 |
19 | ## Packages:
20 |
21 | | Name | Description | NPM |
22 | | -------------------------------------------------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
23 | | [@ngx-auth/core](https://github.com/fulls1z3/ngx-auth/tree/master/packages/@ngx-auth/core) | Authentication utility for **Angular** | [](https://www.npmjs.com/package/@ngx-auth/core) |
24 | | [@ngx-auth/auth0](https://github.com/fulls1z3/ngx-auth/tree/master/packages/@ngx-auth/auth0) | **[Auth0]** platform implementation of **[ngx-auth]** | [](https://www.npmjs.com/package/@ngx-auth/auth0) |
25 |
26 | ## Examples
27 |
28 | - [ng-seed/universal] and [fulls1z3/example-app] are officially maintained projects, showcasing common patterns and best
29 | practices for **`ngx-auth`**.
30 |
31 | ## Contributing
32 |
33 | If you want to file a bug, contribute some code, or improve documentation, please read up on the following contribution guidelines:
34 |
35 | - [Issue guidelines](CONTRIBUTING.md#submit)
36 | - [Contributing guidelines](CONTRIBUTING.md)
37 | - [Coding rules](CONTRIBUTING.md#rules)
38 | - [Change log](/releases)
39 |
40 | #### Thanks to
41 |
42 | - [JetBrains], for their support to this open source project with free [WebStorm] licenses.
43 |
44 | ## License
45 |
46 | The MIT License (MIT)
47 |
48 | Copyright (c) 2019 [Burak Tasci]
49 |
50 | [ngx-auth]: https://github.com/fulls1z3/ngx-auth
51 | [ng-seed/universal]: https://github.com/ng-seed/universal
52 | [fulls1z3/example-app]: https://github.com/fulls1z3/example-app
53 | [auth0]: https://auth0.com
54 | [jetbrains]: https://www.jetbrains.com/community/opensource
55 | [webstorm]: https://www.jetbrains.com/webstorm
56 | [burak tasci]: https://github.com/fulls1z3
57 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['@commitlint/config-conventional'],
3 | rules: {
4 | 'scope-enum': [2, 'always', ['core', 'auth0', 'package', 'npm', 'circle', 'lint', 'packaging', 'changelog']]
5 | }
6 | };
7 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "packages": [
3 | "packages/@ngx-auth/*"
4 | ],
5 | "version": "9.0.0",
6 | "npmClient": "yarn",
7 | "command": {
8 | "publish": {
9 | "allowBranch": "master",
10 | "conventionalCommits": true,
11 | "message": "chore(release): release %s"
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ngx-auth",
3 | "version": "0.0.0",
4 | "description": "JWT authentication utility for Angular & Angular Universal",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/fulls1z3/ngx-auth.git"
8 | },
9 | "keywords": [],
10 | "author": {
11 | "name": "Burak Tasci",
12 | "email": "mail@buraktasci.com"
13 | },
14 | "license": "MIT",
15 | "bugs": {
16 | "url": "https://github.com/fulls1z3/ngx-auth/issues"
17 | },
18 | "homepage": "https://github.com/fulls1z3/ngx-auth#readme",
19 | "scripts": {
20 | "clean": "rimraf dist",
21 | "build:core": "ts-node tools/build/packager.ts core",
22 | "build:auth0": "ts-node tools/build/packager.ts auth0",
23 | "build": "npm run build:core && npm run build:auth0",
24 | "lint": "tslint -p ./tsconfig.lint.json --force",
25 | "lint:check": "tslint-config-prettier-check ./tslint.lint.json",
26 | "rebuild": "npm run clean && npm run build",
27 | "ci:before": "greenkeeper-lockfile-update",
28 | "ci:after": "greenkeeper-lockfile-upload",
29 | "test": "jest --runInBand --colors",
30 | "test:ci": "jest --ci --updateSnapshot --colors",
31 | "release": "standard-version"
32 | },
33 | "devDependencies": {
34 | "@angular/common": "^9.1.0",
35 | "@angular/compiler": "^9.1.0",
36 | "@angular/compiler-cli": "^9.1.0",
37 | "@angular/core": "^9.1.0",
38 | "@angular/platform-browser": "^9.1.0",
39 | "@angular/platform-browser-dynamic": "^9.1.0",
40 | "@angular/router": "^9.1.0",
41 | "@commitlint/cli": "^8.3.5",
42 | "@commitlint/config-conventional": "^8.3.4",
43 | "@types/auth0-js": "^9.12.0",
44 | "@types/jest": "^23.3.14",
45 | "@types/node": "^10.0.0",
46 | "angular-tslint-rules": "^1.20.4",
47 | "auth0-js": "^9.13.0",
48 | "codelyzer": "^5.2.2",
49 | "cz-conventional-changelog": "^3.1.0",
50 | "husky": "^4.2.0",
51 | "jest": "^23.6.0",
52 | "jest-junit-reporter": "^1.1.0",
53 | "jest-preset-angular": "8.1.2",
54 | "lerna": "^3.20.2",
55 | "lint-staged": "^10.1.7",
56 | "ng-packagr": "^9.0.0",
57 | "prettier": "1.19.1",
58 | "prettier-tslint": "^0.4.2",
59 | "reflect-metadata": "^0.1.13",
60 | "request": "^2.88.2",
61 | "rimraf": "^3.0.2",
62 | "rxjs": "~6.5.4",
63 | "ts-node": "^8.9.0",
64 | "tsickle": "^0.38.0",
65 | "tslint": "5.20.1",
66 | "tslint-config-prettier": "^1.18.0",
67 | "typescript": "~3.8.3",
68 | "zone.js": "^0.10.2"
69 | },
70 | "husky": {
71 | "hooks": {
72 | "pre-commit": "lint-staged",
73 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
74 | }
75 | },
76 | "jest": {
77 | "preset": "jest-preset-angular",
78 | "setupTestFrameworkScriptFile": "./tools/test/jest.setup.ts",
79 | "testResultsProcessor": "./node_modules/jest-junit-reporter",
80 | "testMatch": [
81 | "**/+(*.)+(spec|test).+(ts|js)?(x)"
82 | ],
83 | "globals": {
84 | "ts-jest": {
85 | "tsConfigFile": "./tsconfig.json"
86 | },
87 | "__TRANSFORM_HTML__": true
88 | },
89 | "moduleDirectories": [
90 | "node_modules",
91 | "packages"
92 | ],
93 | "moduleNameMapper": {
94 | "^@ngx-auth/core": "/packages/@ngx-auth/core/src/index.ts",
95 | "^@ngx-auth/auth0": "/packages/@ngx-auth/auth0/src/index.ts"
96 | },
97 | "cache": false,
98 | "silent": true,
99 | "collectCoverage": true,
100 | "collectCoverageFrom": [
101 | "packages/@ngx-auth/core/src/**.ts",
102 | "packages/@ngx-auth/auth0/src/**.ts"
103 | ]
104 | },
105 | "config": {
106 | "commitizen": {
107 | "path": "./node_modules/cz-conventional-changelog"
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | # [9.0.0](https://github.com/fulls1z3/ngx-auth/compare/v8.1.0...v9.0.0) (2020-04-27)
7 |
8 |
9 | ### Features
10 |
11 | * **package:** migrate to ng9 ([0a1c4c1](https://github.com/fulls1z3/ngx-auth/commit/0a1c4c11d8cfa3e9649d713da0797b5cdd815d35))
12 |
13 |
14 | ### BREAKING CHANGES
15 |
16 | * **package:** ng9
17 |
18 |
19 |
20 |
21 |
22 | # [8.1.0](https://github.com/fulls1z3/ngx-auth/compare/v8.0.1...v8.1.0) (2020-04-27)
23 |
24 |
25 | ### Bug Fixes
26 |
27 | * **packaging:** fix deployment ([#131](https://github.com/fulls1z3/ngx-auth/issues/131)) ([a43baf5](https://github.com/fulls1z3/ngx-auth/commit/a43baf5f48edf7cc200d06c08fbae005ee17e0cd))
28 | * **packaging:** fix deployment ([#132](https://github.com/fulls1z3/ngx-auth/issues/132)) ([a769718](https://github.com/fulls1z3/ngx-auth/commit/a769718c0a2ce3e0545a23aaa2a86ee4c6a0bc51))
29 |
30 |
31 | ### Features
32 |
33 | * **package:** migrate to ng9 ([#134](https://github.com/fulls1z3/ngx-auth/issues/134)) ([e37267e](https://github.com/fulls1z3/ngx-auth/commit/e37267ef3128ef8bb6eea38941c671e1a6010e51))
34 |
35 |
36 |
37 |
38 |
39 | ## [8.0.1](https://github.com/fulls1z3/ngx-auth/compare/v8.0.0...v8.0.1) (2019-11-21)
40 |
41 | **Note:** Version bump only for package @ngx-auth/auth0
42 |
43 |
44 |
45 |
46 |
47 | # [8.0.0](https://github.com/fulls1z3/ngx-auth/compare/v6.0.0-rc.1...v8.0.0) (2019-11-21)
48 |
49 |
50 | ### Features
51 |
52 | * **package:** upgrade to angular 8 ([5a973f6](https://github.com/fulls1z3/ngx-auth/commit/5a973f66e49aec265002f60b9cb6c39441d8884c))
53 |
54 |
55 | ### BREAKING CHANGES
56 |
57 | * **package:** ng8
58 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/README.md:
--------------------------------------------------------------------------------
1 | # @ngx-auth/auth0 [](https://www.npmjs.com/package/@ngx-auth/auth0) [](https://www.npmjs.com/package/@ngx-auth/auth0)
2 |
3 | **[Auth0]** platform implementation of **[ngx-auth]**
4 |
5 | [](https://circleci.com/gh/fulls1z3/ngx-auth)
6 | [](https://codecov.io/gh/fulls1z3/ngx-auth)
7 | [](https://github.com/facebook/jest)
8 | [](https://conventionalcommits.org)
9 | [](https://angular.io/styleguide)
10 |
11 | > Please support this project by simply putting a Github star. Share this library with friends on Twitter and everywhere else you can.
12 |
13 | ## Table of contents:
14 |
15 | - [Getting started](#getting-started)
16 | - [Installation](#installation) - [Examples](#examples) - [Related packages](#related-packages) - [Adding `@ngx-auth/auth0` to your project (SystemJS)](#adding-systemjs) - [Route configuration](#route-config)
17 | - [app.module configuration](#appmodule-config)
18 | - [Settings](#settings) - [Setting up `Auth0Module` to use `Auth0StaticLoader`](#setting-up-staticloader)
19 | - [SPA/Browser platform implementation](#browser-platform-impl)
20 | - [Server platform implementation](#server-platform-impl)
21 | - [Usage](#usage)
22 | - [License](#license)
23 |
24 | ## Getting started
25 |
26 | ### Installation
27 |
28 | You can install **`@ngx-auth/auth0`** using `npm`
29 |
30 | ```
31 | npm install @ngx-auth/auth0 --save
32 | ```
33 |
34 | ### Examples
35 |
36 | - [ng-seed/universal] and [fulls1z3/example-app] are officially maintained projects, showcasing common patterns and best
37 | practices for **`@ngx-auth/auth0`**.
38 |
39 | ### Related packages
40 |
41 | The following packages may be used in conjunction with **`@ngx-auth/auth0`**:
42 |
43 | - [@ngx-auth/core]
44 |
45 | ### Adding `@ngx-auth/auth0` to your project (SystemJS)
46 |
47 | Add `map` for **`@ngx-auth/auth0`** in your `systemjs.config`
48 |
49 | ```javascript
50 | '@ngx-auth/auth0': 'node_modules/@ngx-auth/auth0/bundles/auth0.umd.min.js'
51 | ```
52 |
53 | ### Route configuration
54 |
55 | Import `AuthGuard` using the mapping `'@ngx-auth/core'` and append `canActivate: [AuthGuard]` or `canActivateChild: [AuthGuard]`
56 | properties to the route definitions at **app.routes** (_considering the app.routes is the route definitions in Angular application_).
57 |
58 | #### NOTICE
59 |
60 | > You should define a **callback url** (_here we use `auth-callback`_) handling the Auth0 callback process, and a
61 | > **public** url as a landing component (_to prevent infinite loop on routing where no public interfaces exist_).
62 |
63 | #### app.routes.ts
64 |
65 | ```TypeScript
66 | ...
67 | import { AuthGuard } from '@ngx-auth/core';
68 | ...
69 | export const routes: Routes = [
70 | {
71 | path: '',
72 | children: [
73 | {
74 | path: 'home',
75 | component: HomeComponent
76 | },
77 | {
78 | path: 'account',
79 | children: [
80 | {
81 | path: 'profile',
82 | component: ProfileComponent
83 | },
84 | {
85 | path: 'change-password',
86 | component: ChangePasswordComponent
87 | }
88 | ],
89 | canActivateChild: [AuthGuard]
90 | },
91 | {
92 | path: 'purchases',
93 | component: PurchasesComponent,
94 | canActivate: [AuthGuard]
95 | },
96 | {
97 | path: 'public',
98 | component: PublicComponent
99 | },
100 | {
101 | path: 'auth-callback',
102 | component: AuthCallbackComponent
103 | }
104 | ]
105 | },
106 | ...
107 | ];
108 | ```
109 |
110 | ### app.module configuration
111 |
112 | Import `Auth0Module` using the mapping `'@ngx-auth/auth0'` and append `Auth0Module.forRoot({...})` within the imports property
113 | of **app.module** (_considering the app.module is the core module in Angular application_).
114 |
115 | ## Settings
116 |
117 | You can call the [forRoot] static method using `Auth0StaticLoader`. By default, it is configured to have no settings.
118 |
119 | > You can customize this behavior (_and ofc other settings_) by supplying **auth0 settings** to `Auth0StaticLoader`.
120 |
121 | The following examples show the use of an exported function (_instead of an inline function_) for [AoT compilation].
122 |
123 | ### Setting up `Auth0Module` to use `Auth0StaticLoader`
124 |
125 | ```TypeScript
126 | ...
127 | import { AuthLoader, AuthModule } from '@ngx-auth/core';
128 | import { Auth0Module, Auth0StaticLoader } from '@ngx-auth/auth0';
129 | ...
130 |
131 | export function auth0Factory(): AuthLoader {
132 | return new Auth0StaticLoader({
133 | backend: {
134 | clientID: 'YOUR_AUTH0_CLIENT_ID',
135 | domain: 'YOUR_APP_NAME.us.auth0.com',
136 | redirectUri: 'http://YOUR_APP_URL/auth-callback',
137 | scope: 'openid',
138 | responseType: 'token id_token'
139 | },
140 | storage: localStorage,
141 | storageKey: 'currentUser',
142 | publicRoute: ['public'],
143 | defaultUrl: ''
144 | });
145 | }
146 |
147 | @NgModule({
148 | declarations: [
149 | AppComponent,
150 | ...
151 | ],
152 | ...
153 | imports: [
154 | AuthModule,
155 | Auth0Module.forRoot({
156 | provide: AuthLoader,
157 | useFactory: (auth0Factory)
158 | }),
159 | ...
160 | ],
161 | ...
162 | bootstrap: [AppComponent]
163 | })
164 | ```
165 |
166 | `Auth0StaticLoader` has one parameter:
167 |
168 | - **providedSettings**: `AuthSettings` : auth settings
169 | - **backend**: `Backend` : auth0 backend
170 | - **storage**: `any` : storage (_by default, localStorage_)
171 | - **storageKey**: `string` : storage key (_by default, `'currentUser'`_)
172 | - **loginRoute**: `Array` : public route, used as a landing component (_by default, `['public']`_)
173 | - **defaultUrl**: `string` : default URL, used as a fallback route after successful authentication (_by default, `''`_)
174 |
175 | > :+1: Hellcat! **`@ngx-auth/auth0`** is now ready to do some magic with [Auth0] using the configuration above.
176 |
177 | **Note**: If your **Angular** application is performing **server-side rendering** (_Angular Universal_), then you should
178 | follow the steps explained below.
179 |
180 | ## SPA/Browser platform implementation
181 |
182 | - Remove the implementation from **app.module** (_considering the app.module is the core module in Angular application_).
183 | - Import `Auth0Module` using the mapping `'@ngx-auth/auth0'` and append `Auth0Module.forRoot({...})` within the imports property
184 | of **app.browser.module** (_considering the app.browser.module is the browser module in Angular Universal application_).
185 |
186 | #### app.browser.module.ts
187 |
188 | ```TypeScript
189 | ...
190 | import { AuthLoader, AuthModule } from '@ngx-auth/core';
191 | import { Auth0Module, Auth0StaticLoader } from '@ngx-auth/auth0';
192 | ...
193 |
194 | export function auth0Factory(): AuthLoader {
195 | return new Auth0StaticLoader({
196 | backend: {
197 | clientID: 'YOUR_AUTH0_CLIENT_ID',
198 | domain: 'YOUR_APP_NAME.us.auth0.com',
199 | redirectUri: 'http://YOUR_APP_URL/auth-callback',
200 | scope: 'openid',
201 | responseType: 'token id_token'
202 | },
203 | storage: localStorage,
204 | storageKey: 'currentUser',
205 | publicRoute: ['public'],
206 | defaultUrl: ''
207 | });
208 | }
209 |
210 | @NgModule({
211 | declarations: [
212 | AppComponent,
213 | ...
214 | ],
215 | ...
216 | imports: [
217 | AuthModule,
218 | Auth0Module.forRoot({
219 | provide: AuthLoader,
220 | useFactory: (auth0Factory)
221 | }),
222 | ...
223 | ],
224 | ...
225 | bootstrap: [AppComponent]
226 | })
227 | ```
228 |
229 | ## Server platform implementation.
230 |
231 | - Import `Auth0Module` using the mapping `'@ngx-auth/auth0'` and append `Auth0Module.forServer()` within the imports property
232 | of **app.server.module** (_considering the app.server.module is the server module in Angular Universal application_).
233 |
234 | #### app.server.module.ts
235 |
236 | ```TypeScript
237 | ...
238 | import { AuthModule } from '@ngx-auth/core';
239 | import { Auth0Module } from '@ngx-auth/auth0';
240 | ...
241 |
242 | @NgModule({
243 | declarations: [
244 | AppComponent,
245 | ...
246 | ],
247 | ...
248 | imports: [
249 | AuthModule.forServer(),
250 | Auth0Module.forServer(),
251 | ...
252 | ],
253 | ...
254 | bootstrap: [AppComponent]
255 | })
256 | ```
257 |
258 | ## Usage
259 |
260 | `Auth0Service` has the `authorize`, `authenticate` and `invalidate` methods:
261 |
262 | The `authenticate` method invokes the `WebAuth.parseHash` method to build the **access_token**, **id_token** and **expiresAt**.
263 | If successful, then the **tokens** are added to the `storage` (_configured at the `AuthLoader`_) and the `accessToken`,
264 | `idToken` and `expiresAt` properties of `Auth0Service` are set.
265 |
266 | These _tokens_ might be used by other services in the application to set the **authorization header** of http requests made
267 | to **secure** endpoints.
268 |
269 | As the name says, the `invalidate` method clears the _tokens_, flushes the **authentication response** from the `storage`,
270 | and redirects to the `login` page.
271 |
272 | ## License
273 |
274 | The MIT License (MIT)
275 |
276 | Copyright (c) 2019 [Burak Tasci]
277 |
278 | [auth0]: https://auth0.com
279 | [ngx-auth]: https://github.com/fulls1z3/ngx-auth
280 | [ng-seed/universal]: https://github.com/ng-seed/universal
281 | [fulls1z3/example-app]: https://github.com/fulls1z3/example-app
282 | [@ngx-auth/core]: https://github.com/fulls1z3/ngx-auth/tree/master/packages/@ngx-auth/core
283 | [@ngx-config/core]: https://github.com/fulls1z3/ngx-config/tree/master/packages/@ngx-config/core
284 | [forroot]: https://angular.io/docs/ts/latest/guide/ngmodule.html#!#core-for-root
285 | [aot compilation]: https://angular.io/docs/ts/latest/cookbook/aot-compiler.html
286 | [burak tasci]: https://github.com/fulls1z3
287 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/ng-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "../../../dist/@ngx-auth/auth0",
4 | "lib": {
5 | "entryFile": "src/index.ts",
6 | "umdModuleIds": {
7 | "rxjs": "rxjs",
8 | "auth0-js": "auth0js",
9 | "@ngx-auth/core": "ngxAuth_core"
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@ngx-auth/auth0",
3 | "version": "9.0.0",
4 | "description": "Auth0 platform implementation of ngx-auth",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/fulls1z3/ngx-auth.git"
8 | },
9 | "keywords": [
10 | "security",
11 | "authentication",
12 | "server side rendering",
13 | "jwt",
14 | "auth0",
15 | "auth",
16 | "universal",
17 | "angular"
18 | ],
19 | "author": {
20 | "name": "Burak Tasci",
21 | "email": "mail@buraktasci.com"
22 | },
23 | "license": "MIT",
24 | "bugs": {
25 | "url": "https://github.com/fulls1z3/ngx-auth/issues"
26 | },
27 | "homepage": "https://github.com/fulls1z3/ngx-auth/tree/master/packages/@ngx-auth/auth0#readme",
28 | "peerDependencies": {
29 | "@angular/common": ">=9.0.0 <10.0.0",
30 | "@angular/core": ">=9.0.0 <10.0.0",
31 | "@angular/platform-browser-dynamic": ">=9.0.0 <10.0.0",
32 | "@angular/router": ">=9.0.0 <10.0.0",
33 | "@ngx-auth/core": ">=9.0.0 <10.0.0",
34 | "auth0-js": ">=9.0.0",
35 | "rxjs": ">=6.0.0"
36 | },
37 | "publishConfig": {
38 | "access": "public",
39 | "directory": "../../../dist/@ngx-auth/core"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/src/auth0-server.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { BehaviorSubject, Observable, of as observableOf } from 'rxjs';
3 |
4 | @Injectable()
5 | export class Auth0ServerService {
6 | get accessToken(): string {
7 | return undefined;
8 | }
9 |
10 | get idToken(): string {
11 | return undefined;
12 | }
13 |
14 | get expiresAt(): string {
15 | return undefined;
16 | }
17 |
18 | get defaultUrl(): string {
19 | return undefined;
20 | }
21 |
22 | get isAuthenticated(): boolean {
23 | return false;
24 | }
25 |
26 | get isAuthenticated$(): BehaviorSubject {
27 | return new BehaviorSubject(false);
28 | }
29 |
30 | authorize(): void {
31 | return;
32 | }
33 |
34 | authenticate(): Observable {
35 | return observableOf(false);
36 | }
37 |
38 | invalidate(): void {
39 | return;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/src/auth0.loader.ts:
--------------------------------------------------------------------------------
1 | import { AuthLoader } from '@ngx-auth/core';
2 |
3 | import { Auth0Backend } from './models/auth0-backend';
4 | import { Auth0Settings } from './models/auth0-settings';
5 |
6 | export class Auth0StaticLoader implements AuthLoader {
7 | get backend(): Auth0Backend {
8 | return this.providedSettings.backend;
9 | }
10 |
11 | get storage(): any {
12 | return this.providedSettings.storage;
13 | }
14 |
15 | get storageKey(): string {
16 | return this.providedSettings.storageKey;
17 | }
18 |
19 | get loginRoute(): Array {
20 | return this.providedSettings.publicRoute;
21 | }
22 |
23 | get publicRoute(): Array {
24 | return this.providedSettings.publicRoute;
25 | }
26 |
27 | get defaultUrl(): string {
28 | return this.providedSettings.defaultUrl;
29 | }
30 |
31 | constructor(
32 | private readonly providedSettings: Auth0Settings = {
33 | backend: {
34 | domain: '',
35 | clientID: '',
36 | scope: 'openid',
37 | responseType: 'token id_token'
38 | },
39 | storage: localStorage,
40 | storageKey: 'currentUser',
41 | publicRoute: ['public'],
42 | defaultUrl: ''
43 | }
44 | ) {}
45 | }
46 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/src/auth0.module.ts:
--------------------------------------------------------------------------------
1 | import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
2 | import { AuthGuard, AuthLoader, AuthServerGuard, AuthService } from '@ngx-auth/core';
3 |
4 | import { Auth0ServerService } from './auth0-server.service';
5 | import { Auth0StaticLoader } from './auth0.loader';
6 | import { Auth0Service } from './auth0.service';
7 |
8 | export const auth0Factory = () => new Auth0StaticLoader();
9 |
10 | @NgModule({
11 | providers: [
12 | Auth0Service,
13 | {
14 | provide: AuthService,
15 | useClass: Auth0Service
16 | },
17 | {
18 | provide: AuthLoader,
19 | useFactory: auth0Factory
20 | }
21 | ]
22 | })
23 | export class Auth0Module {
24 | static forRoot(
25 | configuredProvider: any = {
26 | provide: AuthLoader,
27 | useFactory: auth0Factory
28 | }
29 | ): ModuleWithProviders {
30 | return {
31 | ngModule: Auth0Module,
32 | providers: [configuredProvider]
33 | };
34 | }
35 |
36 | static forServer(): ModuleWithProviders {
37 | return {
38 | ngModule: Auth0Module,
39 | providers: [
40 | {
41 | provide: Auth0Service,
42 | useClass: Auth0ServerService
43 | },
44 | {
45 | provide: AuthGuard,
46 | useClass: AuthServerGuard
47 | }
48 | ]
49 | };
50 | }
51 |
52 | constructor(@Optional() @SkipSelf() parentModule?: Auth0Module) {
53 | if (parentModule) {
54 | throw new Error('Auth0Module already loaded; import in root module only.');
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/src/auth0.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { Router } from '@angular/router';
3 | import { AuthLoader } from '@ngx-auth/core';
4 | import * as auth0js from 'auth0-js';
5 | import { BehaviorSubject, from as observableFrom, Observable } from 'rxjs';
6 |
7 | @Injectable()
8 | export class Auth0Service {
9 | private readonly auth0: any;
10 | private _accessToken: string;
11 | private _idToken: string;
12 | private _expiresAt: string;
13 | private readonly _isAuthenticated$: BehaviorSubject;
14 |
15 | get accessToken(): string {
16 | return this._accessToken;
17 | }
18 |
19 | get idToken(): string {
20 | return this._idToken;
21 | }
22 |
23 | get expiresAt(): string {
24 | return this._expiresAt;
25 | }
26 |
27 | get defaultUrl(): string {
28 | return this.loader.defaultUrl;
29 | }
30 |
31 | get isAuthenticated(): boolean {
32 | const stored = this.loader.storage.getItem(this.loader.storageKey);
33 | const authContent = stored ? stored : '{}';
34 | const expiresAt = JSON.parse(authContent).expiresAt;
35 |
36 | return new Date().getTime() < expiresAt;
37 | }
38 |
39 | get isAuthenticated$(): BehaviorSubject {
40 | return this._isAuthenticated$;
41 | }
42 |
43 | constructor(readonly loader: AuthLoader, protected readonly router: Router) {
44 | this.auth0 = new auth0js.WebAuth(this.loader.backend);
45 |
46 | const stored = this.loader.storage.getItem(this.loader.storageKey);
47 | const authContent = stored ? stored : '{}';
48 | const current = JSON.parse(authContent);
49 |
50 | this._accessToken = current && current.accessToken;
51 | this._idToken = current && current.idToken;
52 | this._expiresAt = current && current.expiresAt;
53 |
54 | this._isAuthenticated$ = new BehaviorSubject(!!this._accessToken && !!this._idToken && !!this._expiresAt);
55 | }
56 |
57 | authorize(): void {
58 | this.auth0.authorize();
59 | }
60 |
61 | authenticate(): Observable {
62 | const res$ = new Promise((resolve: Function) => {
63 | this.auth0.parseHash((err: any, res: any) => {
64 | if (res && res.accessToken && res.idToken) {
65 | this._accessToken = res.accessToken;
66 | this._idToken = res.idToken;
67 | this._expiresAt = JSON.stringify(res.expiresIn * 1000 + new Date().getTime());
68 |
69 | this.loader.storage.setItem(
70 | this.loader.storageKey,
71 | JSON.stringify({
72 | accessToken: this._accessToken,
73 | idToken: this._idToken,
74 | expiresAt: this._expiresAt
75 | })
76 | );
77 |
78 | this.isAuthenticated$.next(true);
79 |
80 | return this.router.navigateByUrl(this.defaultUrl).then(() => {
81 | resolve(true);
82 | });
83 | }
84 |
85 | return resolve(false);
86 | });
87 | });
88 |
89 | return observableFrom(res$);
90 | }
91 |
92 | async invalidate(): Promise {
93 | this._accessToken = undefined;
94 | this._idToken = undefined;
95 | this._expiresAt = undefined;
96 |
97 | this.loader.storage.removeItem(this.loader.storageKey);
98 |
99 | this.isAuthenticated$.next(false);
100 |
101 | return this.router.navigateByUrl(this.defaultUrl);
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './models/auth0-backend';
2 | export * from './models/auth0-settings';
3 | export * from './auth0.loader';
4 | export * from './auth0.module';
5 | export * from './auth0.service';
6 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/src/models/auth0-backend.ts:
--------------------------------------------------------------------------------
1 | export interface Auth0Backend {
2 | domain: string;
3 | clientID: string;
4 | redirectUri?: string;
5 | scope?: string;
6 | audience?: string;
7 | responseType?: string;
8 | responseMode?: string;
9 | }
10 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/src/models/auth0-settings.ts:
--------------------------------------------------------------------------------
1 | import { Auth0Backend } from './auth0-backend';
2 |
3 | export interface Auth0Settings {
4 | backend: Auth0Backend;
5 | storage: any;
6 | storageKey: string;
7 | publicRoute: Array;
8 | defaultUrl: string;
9 | }
10 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/tests/__mocks__/auth0-js.ts:
--------------------------------------------------------------------------------
1 | let order = 0;
2 |
3 | export class WebAuth {
4 | authorize(): void {
5 | /**/
6 | }
7 |
8 | parseHash(callback: Function): void {
9 | order++;
10 |
11 | return callback(
12 | undefined,
13 | order !== 1
14 | ? {}
15 | : {
16 | accessToken: 'test',
17 | idToken: 'test',
18 | expiresIn: 7200
19 | }
20 | );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/tests/auth0-server.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, inject } from '@angular/core/testing';
2 |
3 | import { Auth0Service } from '../src';
4 | import { Auth0ServerService } from '../src/auth0-server.service';
5 |
6 | import { testServerModuleConfig } from './common';
7 |
8 | describe('@ngx-auth/auth0:', () => {
9 | beforeEach(testServerModuleConfig);
10 |
11 | describe('Auth0ServerService', () => {
12 | beforeEach(inject([Auth0Service], async (auth: Auth0Service) => auth.invalidate()));
13 |
14 | it('is defined', inject([Auth0Service], (auth: Auth0Service) => {
15 | auth.authorize();
16 |
17 | expect(Auth0Service).toBeDefined();
18 | expect(auth).toBeDefined();
19 | expect(auth instanceof Auth0ServerService).toBeTruthy();
20 | }));
21 |
22 | it('should be able to return an undefined `defaultUrl`', inject([Auth0Service], (auth: Auth0Service) => {
23 | const res = auth.defaultUrl;
24 | expect(res).toBeUndefined();
25 | }));
26 |
27 | it('should not authenticate', async(
28 | inject([Auth0Service], (auth: Auth0Service) => {
29 | auth.authenticate().subscribe(res => {
30 | expect(res).toEqual(false);
31 |
32 | const accessToken = auth.accessToken;
33 | expect(accessToken).toBeUndefined();
34 |
35 | const idToken = auth.idToken;
36 | expect(idToken).toBeUndefined();
37 |
38 | const expiresAt = auth.expiresAt;
39 | expect(expiresAt).toBeUndefined();
40 |
41 | const isAuthenticated = auth.isAuthenticated;
42 | expect(isAuthenticated).toEqual(false);
43 |
44 | const isAuthenticated$ = auth.isAuthenticated$;
45 | isAuthenticated$.subscribe(isAuth => {
46 | expect(isAuth).toEqual(false);
47 | });
48 | });
49 | })
50 | ));
51 | });
52 | });
53 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/tests/auth0.loader.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 | import { AuthLoader } from '@ngx-auth/core';
3 |
4 | import { Auth0Service, Auth0StaticLoader } from '../src';
5 |
6 | import { testModuleConfig, testSettings } from './common';
7 |
8 | describe('@ngx-auth/auth0:', () => {
9 | beforeEach(() => {
10 | const auth0Factory = () => new Auth0StaticLoader();
11 |
12 | testModuleConfig({
13 | provide: AuthLoader,
14 | useFactory: auth0Factory
15 | });
16 | });
17 |
18 | describe('Auth0StaticLoader', () => {
19 | it('should be able to provide `Auth0StaticLoader`', () => {
20 | const auth = TestBed.get(Auth0Service);
21 |
22 | expect(Auth0StaticLoader).toBeDefined();
23 | expect(auth.loader).toBeDefined();
24 | expect(auth.loader instanceof Auth0StaticLoader).toBeTruthy();
25 | });
26 |
27 | it('should be able to return the default auth0Settings', () => {
28 | const loader = new Auth0StaticLoader();
29 |
30 | expect(loader.backend.domain).toEqual('');
31 | expect(loader.backend.clientID).toEqual('');
32 | expect(loader.backend.scope).toEqual('openid');
33 | expect(loader.backend.responseType).toEqual('token id_token');
34 | expect(loader.storage).toEqual(testSettings.storage);
35 | expect(loader.storageKey).toEqual(testSettings.storageKey);
36 | expect(loader.loginRoute).toEqual(testSettings.publicRoute);
37 | expect(loader.publicRoute).toEqual(testSettings.publicRoute);
38 | expect(loader.defaultUrl).toEqual(testSettings.defaultUrl);
39 | });
40 |
41 | it('should be able to return custom auth0Settings', () => {
42 | const loader = new Auth0StaticLoader(testSettings);
43 |
44 | expect(loader.backend).toEqual(testSettings.backend);
45 | expect(loader.storage).toEqual(testSettings.storage);
46 | expect(loader.storageKey).toEqual(testSettings.storageKey);
47 | expect(loader.loginRoute).toEqual(testSettings.publicRoute);
48 | expect(loader.publicRoute).toEqual(testSettings.publicRoute);
49 | expect(loader.defaultUrl).toEqual(testSettings.defaultUrl);
50 | });
51 | });
52 | });
53 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/tests/auth0.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, inject, TestBed } from '@angular/core/testing';
2 | import { AuthLoader } from '@ngx-auth/core';
3 |
4 | import { Auth0Service, Auth0StaticLoader } from '../src';
5 |
6 | import { TestBootstrapComponent, testModuleConfig, testSettings } from './common';
7 |
8 | jest.mock('auth0-js');
9 |
10 | describe('@ngx-auth/auth0:', () => {
11 | beforeEach(() => {
12 | const auth0Factory = () => new Auth0StaticLoader(testSettings);
13 |
14 | testModuleConfig({
15 | provide: AuthLoader,
16 | useFactory: auth0Factory
17 | });
18 | });
19 |
20 | describe('Auth0Service', () => {
21 | beforeEach(inject([Auth0Service], async (auth: Auth0Service) => auth.invalidate()));
22 |
23 | it('is defined', inject([Auth0Service], (auth: Auth0Service) => {
24 | auth.authorize();
25 |
26 | expect(Auth0Service).toBeDefined();
27 | expect(auth).toBeDefined();
28 | expect(auth instanceof Auth0Service).toBeTruthy();
29 | }));
30 |
31 | it('should be able to return the `defaultUrl`', inject([Auth0Service], (auth: Auth0Service) => {
32 | const res = auth.defaultUrl;
33 | expect(res).toEqual('');
34 | }));
35 |
36 | it('should be able to authenticate w/valid combination', async(
37 | inject([Auth0Service], (auth: Auth0Service) => {
38 | const fixture = TestBed.createComponent(TestBootstrapComponent);
39 | fixture.detectChanges();
40 |
41 | auth.authenticate().subscribe(res => {
42 | expect(res).toEqual(true);
43 |
44 | const accessToken = auth.accessToken;
45 | expect(accessToken).toBeDefined();
46 |
47 | const idToken = auth.idToken;
48 | expect(idToken).toBeDefined();
49 |
50 | const expiresAt = auth.expiresAt;
51 | expect(expiresAt).toBeDefined();
52 |
53 | const isAuthenticated = auth.isAuthenticated;
54 | expect(isAuthenticated).toEqual(true);
55 | });
56 | })
57 | ));
58 |
59 | it('should not authenticate w/o valid combination', async(
60 | inject([Auth0Service], (auth: Auth0Service) => {
61 | const fixture = TestBed.createComponent(TestBootstrapComponent);
62 | fixture.detectChanges();
63 |
64 | auth.authenticate().subscribe(res => {
65 | expect(res).toEqual(false);
66 |
67 | const accessToken = auth.accessToken;
68 | expect(accessToken).toBeUndefined();
69 |
70 | const idToken = auth.idToken;
71 | expect(idToken).toBeUndefined();
72 |
73 | const expiresAt = auth.expiresAt;
74 | expect(expiresAt).toBeUndefined();
75 |
76 | const isAuthenticated = auth.isAuthenticated;
77 | expect(isAuthenticated).toEqual(false);
78 | });
79 | })
80 | ));
81 | });
82 | });
83 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/auth0/tests/common.ts:
--------------------------------------------------------------------------------
1 | import { Component, NgModule } from '@angular/core';
2 | import { TestBed } from '@angular/core/testing';
3 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
4 | import { Routes } from '@angular/router';
5 | import { RouterTestingModule } from '@angular/router/testing';
6 | import { AuthGuard } from '@ngx-auth/core';
7 |
8 | import { Auth0Module, Auth0Settings } from '../src';
9 |
10 | @Component({ template: ' ' })
11 | export class TestBootstrapComponent {}
12 |
13 | @Component({ template: '' })
14 | export class TestComponent {}
15 |
16 | @NgModule({
17 | imports: [RouterTestingModule],
18 | declarations: [TestBootstrapComponent, TestComponent]
19 | })
20 | class TestSharedModule {}
21 |
22 | const testLazyRoutes: Routes = [
23 | {
24 | path: '',
25 | component: TestComponent
26 | }
27 | ];
28 |
29 | @NgModule({
30 | imports: [RouterTestingModule.withRoutes(testLazyRoutes), TestSharedModule]
31 | })
32 | class TestLazyModule {}
33 |
34 | const testRoutes: Routes = [
35 | {
36 | path: '',
37 | component: TestBootstrapComponent,
38 | children: [
39 | {
40 | path: '',
41 | component: TestComponent
42 | },
43 | {
44 | path: 'activate-page',
45 | component: TestComponent,
46 | canActivate: [AuthGuard]
47 | },
48 | {
49 | path: 'load-page',
50 | loadChildren: () => TestLazyModule,
51 | canLoad: [AuthGuard]
52 | },
53 | {
54 | path: 'activate-feature',
55 | children: [
56 | {
57 | path: '',
58 | component: TestComponent,
59 | canActivate: [AuthGuard]
60 | }
61 | ],
62 | canActivateChild: [AuthGuard]
63 | },
64 | {
65 | path: 'auth-callback',
66 | component: TestComponent
67 | }
68 | ]
69 | }
70 | ];
71 |
72 | export const testSettings: Auth0Settings = {
73 | backend: {
74 | domain: 'test',
75 | clientID: 'test'
76 | },
77 | storage: localStorage,
78 | storageKey: 'currentUser',
79 | publicRoute: ['public'],
80 | defaultUrl: ''
81 | };
82 |
83 | export const testModuleConfig = (moduleOptions?: any) => {
84 | TestBed.resetTestEnvironment();
85 |
86 | TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()).configureTestingModule({
87 | imports: [RouterTestingModule.withRoutes(testRoutes), Auth0Module.forRoot(moduleOptions), TestSharedModule]
88 | });
89 | };
90 |
91 | export const testServerModuleConfig = () => {
92 | TestBed.resetTestEnvironment();
93 |
94 | TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()).configureTestingModule({
95 | imports: [RouterTestingModule.withRoutes(testRoutes), Auth0Module.forServer(), TestSharedModule]
96 | });
97 | };
98 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | # [9.0.0](https://github.com/fulls1z3/ngx-auth/compare/v8.1.0...v9.0.0) (2020-04-27)
7 |
8 |
9 | ### Features
10 |
11 | * **package:** migrate to ng9 ([0a1c4c1](https://github.com/fulls1z3/ngx-auth/commit/0a1c4c11d8cfa3e9649d713da0797b5cdd815d35))
12 |
13 |
14 | ### BREAKING CHANGES
15 |
16 | * **package:** ng9
17 |
18 |
19 |
20 |
21 |
22 | # [8.1.0](https://github.com/fulls1z3/ngx-auth/compare/v8.0.1...v8.1.0) (2020-04-27)
23 |
24 |
25 | ### Bug Fixes
26 |
27 | * **packaging:** fix deployment ([#131](https://github.com/fulls1z3/ngx-auth/issues/131)) ([a43baf5](https://github.com/fulls1z3/ngx-auth/commit/a43baf5f48edf7cc200d06c08fbae005ee17e0cd))
28 | * **packaging:** fix deployment ([#132](https://github.com/fulls1z3/ngx-auth/issues/132)) ([a769718](https://github.com/fulls1z3/ngx-auth/commit/a769718c0a2ce3e0545a23aaa2a86ee4c6a0bc51))
29 |
30 |
31 | ### Features
32 |
33 | * **package:** migrate to ng9 ([#134](https://github.com/fulls1z3/ngx-auth/issues/134)) ([e37267e](https://github.com/fulls1z3/ngx-auth/commit/e37267ef3128ef8bb6eea38941c671e1a6010e51))
34 |
35 |
36 |
37 |
38 |
39 | ## [8.0.1](https://github.com/fulls1z3/ngx-auth/compare/v8.0.0...v8.0.1) (2019-11-21)
40 |
41 | **Note:** Version bump only for package @ngx-auth/core
42 |
43 |
44 |
45 |
46 |
47 | # [8.0.0](https://github.com/fulls1z3/ngx-auth/compare/v6.0.0-rc.1...v8.0.0) (2019-11-21)
48 |
49 |
50 | ### Features
51 |
52 | * **package:** upgrade to angular 8 ([5a973f6](https://github.com/fulls1z3/ngx-auth/commit/5a973f66e49aec265002f60b9cb6c39441d8884c))
53 |
54 |
55 | ### BREAKING CHANGES
56 |
57 | * **package:** ng8
58 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/README.md:
--------------------------------------------------------------------------------
1 | # @ngx-auth/core [](https://www.npmjs.com/package/@ngx-auth/core) [](https://www.npmjs.com/package/@ngx-auth/core)
2 |
3 | JWT authentication utility for **Angular** & **Angular Universal**
4 |
5 | [](https://circleci.com/gh/fulls1z3/ngx-auth)
6 | [](https://codecov.io/gh/fulls1z3/ngx-auth)
7 | [](https://github.com/facebook/jest)
8 | [](https://conventionalcommits.org)
9 | [](https://angular.io/styleguide)
10 |
11 | > Please support this project by simply putting a Github star. Share this library with friends on Twitter and everywhere else you can.
12 |
13 | **`@ngx-auth/core`** is a basic JWT-based authentication utility used for logging in and out of the **Angular** application
14 | and restrict unauthenticated access from accessing restricted routes.
15 |
16 | ## Table of contents:
17 |
18 | - [Getting started](#getting-started)
19 | - [Installation](#installation) - [Examples](#examples) - [Recommended packages](#recommended-packages) - [Adding `@ngx-auth/core` to your project (SystemJS)](#adding-systemjs) - [Route configuration](#route-config)
20 | - [app.module configuration](#appmodule-config)
21 | - [Settings](#settings) - [Setting up `AuthModule` to use `AuthStaticLoader`](#setting-up-staticloader)
22 | - [SPA/Browser platform implementation](#browser-platform-impl)
23 | - [Server platform implementation](#server-platform-impl)
24 | - [Usage](#usage)
25 | - [License](#license)
26 |
27 | ## Getting started
28 |
29 | ### Installation
30 |
31 | You can install **`@ngx-auth/core`** using `npm`
32 |
33 | ```
34 | npm install @ngx-auth/core --save
35 | ```
36 |
37 | ### Examples
38 |
39 | - [ng-seed/universal] and [fulls1z3/example-app] are officially maintained projects, showcasing common patterns and best
40 | practices for **`@ngx-auth/core`**.
41 |
42 | ### Recommended packages
43 |
44 | The following package(s) have no dependency for **`@ngx-auth/core`**, however may provide supplementary/shorthand functionality:
45 |
46 | - [@ngx-config/core]: provides auth settings from the application settings loaded during application initialization
47 |
48 | ### Adding `@ngx-auth/core` to your project (SystemJS)
49 |
50 | Add `map` for **`@ngx-auth/core`** in your `systemjs.config`
51 |
52 | ```javascript
53 | '@ngx-auth/core': 'node_modules/@ngx-auth/core/bundles/core.umd.min.js'
54 | ```
55 |
56 | ### Route configuration
57 |
58 | Import `AuthGuard` using the mapping `'@ngx-auth/core'` and append `canActivate: [AuthGuard]` or `canActivateChild: [AuthGuard]`
59 | properties to the route definitions at **app.routes** (_considering the app.routes is the route definitions in Angular application_).
60 |
61 | #### app.routes.ts
62 |
63 | ```TypeScript
64 | ...
65 | import { AuthGuard } from '@ngx-auth/core';
66 | ...
67 | export const routes: Routes = [
68 | {
69 | path: '',
70 | children: [
71 | {
72 | path: 'home',
73 | component: HomeComponent
74 | },
75 | {
76 | path: 'account',
77 | children: [
78 | {
79 | path: 'profile',
80 | component: ProfileComponent
81 | },
82 | {
83 | path: 'change-password',
84 | component: ChangePasswordComponent
85 | }
86 | ],
87 | canActivateChild: [AuthGuard]
88 | },
89 | {
90 | path: 'purchases',
91 | component: PurchasesComponent,
92 | canActivate: [AuthGuard]
93 | },
94 | {
95 | path: 'login',
96 | component: LoginComponent
97 | }
98 | ]
99 | },
100 | ...
101 | ];
102 | ```
103 |
104 | ### app.module configuration
105 |
106 | Import `AuthModule` using the mapping `'@ngx-auth/core'` and append `AuthModule.forRoot({...})` within the imports property
107 | of **app.module** (_considering the app.module is the core module in Angular application_).
108 |
109 | ## Settings
110 |
111 | You can call the [forRoot] static method using `AuthStaticLoader`. By default, it is configured to have no settings.
112 |
113 | > You can customize this behavior (_and ofc other settings_) by supplying **auth settings** to `AuthStaticLoader`.
114 |
115 | The following examples show the use of an exported function (_instead of an inline function_) for [AoT compilation].
116 |
117 | ### Setting up `AuthModule` to use `AuthStaticLoader`
118 |
119 | ```TypeScript
120 | ...
121 | import { AuthModule, AuthLoader, AuthStaticLoader } from '@ngx-auth/core';
122 | ...
123 |
124 | export function authFactory(): AuthLoader {
125 | return new AuthStaticLoader({
126 | backend: {
127 | endpoint: '/api/authenticate',
128 | params: []
129 | },
130 | storage: localStorage,
131 | storageKey: 'currentUser',
132 | loginRoute: ['login'],
133 | defaultUrl: ''
134 | });
135 | }
136 |
137 | @NgModule({
138 | declarations: [
139 | AppComponent,
140 | ...
141 | ],
142 | ...
143 | imports: [
144 | AuthModule.forRoot({
145 | provide: AuthLoader,
146 | useFactory: (authFactory)
147 | }),
148 | ...
149 | ],
150 | ...
151 | bootstrap: [AppComponent]
152 | })
153 | ```
154 |
155 | `AuthStaticLoader` has one parameter:
156 |
157 | - **providedSettings**: `AuthSettings` : auth settings
158 | - **backend**: `Backend` : auth backend (_by default, using the endpoint `'/api/authenticate'`_)
159 | - **storage**: `any` : storage (_by default, localStorage_)
160 | - **storageKey**: `string` : storage key (_by default, `'currentUser'`_)
161 | - **loginRoute**: `Array` : login route, used to redirect guarded routes (_by default, `['login']`_)
162 | - **defaultUrl**: `string` : default URL, used as a fallback route after successful authentication (_by default, `''`_)
163 |
164 | > :+1: On it! **`@ngx-auth/core`** is now ready to perform JWT-based authentication regarding the configuration above.
165 |
166 | **Note**: If your **Angular** application is performing **server-side rendering** (_Angular Universal_), then you should
167 | follow the steps explained below.
168 |
169 | ## SPA/Browser platform implementation
170 |
171 | - Remove the implementation from **app.module** (_considering the app.module is the core module in Angular application_).
172 | - Import `AuthModule` using the mapping `'@ngx-auth/core'` and append `AuthModule.forRoot({...})` within the imports property
173 | of **app.browser.module** (_considering the app.browser.module is the browser module in Angular Universal application_).
174 |
175 | #### app.browser.module.ts
176 |
177 | ```TypeScript
178 | ...
179 | import { AuthModule, AuthLoader, AuthStaticLoader } from '@ngx-auth/core';
180 | ...
181 |
182 | export function authFactory(): AuthLoader {
183 | return new AuthStaticLoader({
184 | backend: {
185 | endpoint: '/api/authenticate',
186 | params: []
187 | },
188 | storage: localStorage,
189 | storageKey: 'currentUser',
190 | loginRoute: ['login'],
191 | defaultUrl: ''
192 | });
193 | }
194 |
195 | @NgModule({
196 | declarations: [
197 | AppComponent,
198 | ...
199 | ],
200 | ...
201 | imports: [
202 | AuthModule.forRoot({
203 | provide: AuthLoader,
204 | useFactory: (authFactory)
205 | }),
206 | ...
207 | ],
208 | ...
209 | bootstrap: [AppComponent]
210 | })
211 | ```
212 |
213 | ## Server platform implementation.
214 |
215 | - Import `AuthModule` using the mapping `'@ngx-auth/core'` and append `AuthModule.forServer()` within the imports property
216 | of **app.server.module** (_considering the app.server.module is the server module in Angular Universal application_).
217 |
218 | #### app.server.module.ts
219 |
220 | ```TypeScript
221 | ...
222 | import { AuthModule } from '@ngx-auth/core';
223 | ...
224 |
225 | @NgModule({
226 | declarations: [
227 | AppComponent,
228 | ...
229 | ],
230 | ...
231 | imports: [
232 | AuthModule.forServer(),
233 | ...
234 | ],
235 | ...
236 | bootstrap: [AppComponent]
237 | })
238 | ```
239 |
240 | ## Usage
241 |
242 | `AuthService` has the `authenticate` and `invalidate` methods:
243 |
244 | The `authenticate` method posts the **credentials** to the **API** (_configured at the `AuthLoader`_) using the parameters `username`
245 | and `password`, and checks the response for a **JWT token**. If successful, then the **authentication response** is added
246 | to the `storage` (_configured at the `AuthLoader`_) and the `token` property of `AuthService` is set.
247 |
248 | That `token` might be used by other services in the application to set the **authorization header** of http requests made to **secure** endpoints.
249 |
250 | As the name says, the `invalidate` method clears the **JWT token**, flushes the **authentication response** from the `storage`,
251 | and redirects to the `login` page.
252 |
253 | The following example shows how to log in and out of the **Angular** application.
254 |
255 | #### login.component.ts
256 |
257 | ```TypeScript
258 | ...
259 | import { AuthService } from '@ngx-auth/core';
260 |
261 | @Component({
262 | templateUrl: './login.component.html',
263 | styleUrls: ['./login.component.scss']
264 | })
265 | export class LoginComponent {
266 | ...
267 |
268 | username: string;
269 | password: string;
270 |
271 | constructor(private readonly auth: AuthService) {
272 | ...
273 | }
274 |
275 | login(): void {
276 | this.auth.authenticate(this.username, this.password)
277 | .subscribe(() => {
278 | if (!this.auth.isAuthenticated)
279 | // display warning
280 | });
281 | }
282 |
283 | logout(): void {
284 | this.auth.invalidate();
285 | }
286 | }
287 | ```
288 |
289 | ## License
290 |
291 | The MIT License (MIT)
292 |
293 | Copyright (c) 2019 [Burak Tasci]
294 |
295 | [ng-seed/universal]: https://github.com/ng-seed/universal
296 | [fulls1z3/example-app]: https://github.com/fulls1z3/example-app
297 | [@ngx-config/core]: https://github.com/fulls1z3/ngx-config/tree/master/packages/@ngx-config/core
298 | [forroot]: https://angular.io/docs/ts/latest/guide/ngmodule.html#!#core-for-root
299 | [aot compilation]: https://angular.io/docs/ts/latest/cookbook/aot-compiler.html
300 | [burak tasci]: https://github.com/fulls1z3
301 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/ng-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "../../../dist/@ngx-auth/core",
4 | "lib": {
5 | "entryFile": "src/index.ts",
6 | "umdModuleIds": {
7 | "rxjs": "rxjs"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@ngx-auth/core",
3 | "version": "9.0.0",
4 | "description": "JWT authentication utility for Angular & Angular Universal",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/fulls1z3/ngx-auth.git"
8 | },
9 | "keywords": [
10 | "security",
11 | "authentication",
12 | "server side rendering",
13 | "jwt",
14 | "auth",
15 | "universal",
16 | "angular"
17 | ],
18 | "author": {
19 | "name": "Burak Tasci",
20 | "email": "mail@buraktasci.com"
21 | },
22 | "license": "MIT",
23 | "bugs": {
24 | "url": "https://github.com/fulls1z3/ngx-auth/issues"
25 | },
26 | "homepage": "https://github.com/fulls1z3/ngx-auth/tree/master/packages/@ngx-auth/core#readme",
27 | "peerDependencies": {
28 | "@angular/common": ">=9.0.0 <10.0.0",
29 | "@angular/core": ">=9.0.0 <10.0.0",
30 | "@angular/platform-browser-dynamic": ">=9.0.0 <10.0.0",
31 | "@angular/router": ">=9.0.0 <10.0.0",
32 | "rxjs": ">=6.0.0"
33 | },
34 | "publishConfig": {
35 | "access": "public",
36 | "directory": "../../../dist/@ngx-auth/auth0"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/src/auth-server.guard.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, CanLoad, Route, RouterStateSnapshot } from '@angular/router';
3 |
4 | @Injectable()
5 | export class AuthServerGuard implements CanActivate, CanActivateChild, CanLoad {
6 | canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
7 | return false;
8 | }
9 |
10 | canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
11 | return false;
12 | }
13 |
14 | canLoad(route: Route): boolean {
15 | return false;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/src/auth-server.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { Observable, of as observableOf } from 'rxjs';
3 |
4 | @Injectable()
5 | export class AuthServerService {
6 | get token(): string {
7 | return undefined;
8 | }
9 |
10 | get redirectUrl(): string {
11 | return undefined;
12 | }
13 |
14 | set redirectUrl(value: string) {
15 | return;
16 | }
17 |
18 | get defaultUrl(): string {
19 | return undefined;
20 | }
21 |
22 | get isAuthenticated(): boolean {
23 | return false;
24 | }
25 |
26 | authenticate(username: string, password: string): Observable {
27 | return observableOf(false);
28 | }
29 |
30 | invalidate(): void {
31 | return;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/src/auth.guard.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, CanLoad, Route, Router, RouterStateSnapshot } from '@angular/router';
3 |
4 | import { AuthLoader } from './auth.loader';
5 | import { AuthService } from './auth.service';
6 |
7 | @Injectable()
8 | export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {
9 | constructor(private readonly loader: AuthLoader, private readonly auth: AuthService, private readonly router: Router) {}
10 |
11 | async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise {
12 | const url = state.url;
13 |
14 | return this.handleAuth(url);
15 | }
16 |
17 | async canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise {
18 | return this.canActivate(route, state);
19 | }
20 |
21 | async canLoad(route: Route): Promise {
22 | const url = `/${route.path}`;
23 |
24 | return this.handleAuth(url);
25 | }
26 |
27 | private async handleAuth(url: string): Promise {
28 | if (this.auth.isAuthenticated) {
29 | return Promise.resolve(true);
30 | }
31 |
32 | this.auth.redirectUrl = url;
33 |
34 | return this.router.navigate(this.loader.loginRoute).then(() => false);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/src/auth.loader.ts:
--------------------------------------------------------------------------------
1 | import { AuthSettings } from './models/auth-settings';
2 | import { Backend } from './models/backend';
3 |
4 | export abstract class AuthLoader {
5 | abstract get backend(): any;
6 |
7 | abstract get storage(): any;
8 |
9 | abstract get storageKey(): string;
10 |
11 | abstract get loginRoute(): Array;
12 |
13 | abstract get defaultUrl(): string;
14 | }
15 |
16 | export class AuthStaticLoader implements AuthLoader {
17 | get backend(): Backend {
18 | return this.providedSettings.backend;
19 | }
20 |
21 | get storage(): any {
22 | return this.providedSettings.storage;
23 | }
24 |
25 | get storageKey(): string {
26 | return this.providedSettings.storageKey;
27 | }
28 |
29 | get loginRoute(): Array {
30 | return this.providedSettings.loginRoute;
31 | }
32 |
33 | get defaultUrl(): string {
34 | return this.providedSettings.defaultUrl;
35 | }
36 |
37 | constructor(
38 | private readonly providedSettings: AuthSettings = {
39 | backend: {
40 | endpoint: '/api/authenticate',
41 | params: []
42 | },
43 | storage: localStorage,
44 | storageKey: 'currentUser',
45 | loginRoute: ['login'],
46 | defaultUrl: ''
47 | }
48 | ) {}
49 | }
50 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/src/auth.module.ts:
--------------------------------------------------------------------------------
1 | import { Inject, InjectionToken, ModuleWithProviders, NgModule, Optional } from '@angular/core';
2 |
3 | import { AuthServerGuard } from './auth-server.guard';
4 | import { AuthServerService } from './auth-server.service';
5 | import { AuthGuard } from './auth.guard';
6 | import { AuthLoader, AuthStaticLoader } from './auth.loader';
7 | import { AuthService } from './auth.service';
8 | import { AuthSettings } from './models/auth-settings';
9 |
10 | export const AUTH_FORROOT_GUARD = new InjectionToken('AUTH_FORROOT_GUARD');
11 |
12 | export const authFactory = () => new AuthStaticLoader();
13 |
14 | @NgModule({
15 | providers: [
16 | AuthGuard,
17 | AuthService,
18 | {
19 | provide: AuthLoader,
20 | useFactory: authFactory
21 | }
22 | ]
23 | })
24 | export class AuthModule {
25 | static forRoot(
26 | configuredProvider: any = {
27 | provide: AuthLoader,
28 | useFactory: authFactory
29 | }
30 | ): ModuleWithProviders {
31 | return {
32 | ngModule: AuthModule,
33 | providers: [configuredProvider]
34 | };
35 | }
36 |
37 | static forChild(): ModuleWithProviders {
38 | return {
39 | ngModule: AuthModule
40 | };
41 | }
42 |
43 | static forServer(): ModuleWithProviders {
44 | return {
45 | ngModule: AuthModule,
46 | providers: [
47 | {
48 | provide: AuthService,
49 | useClass: AuthServerService
50 | },
51 | {
52 | provide: AuthGuard,
53 | useClass: AuthServerGuard
54 | }
55 | ]
56 | };
57 | }
58 |
59 | // tslint:disable-next-line
60 | constructor(@Optional() @Inject(AUTH_FORROOT_GUARD) guard: any) {
61 | // NOTE: inject token
62 | }
63 | }
64 |
65 | export const provideForRootGuard = (settings?: AuthSettings) => {
66 | if (settings) {
67 | throw new Error('AuthModule.forRoot() already called. Child modules should use AuthModule.forChild() instead.');
68 | }
69 |
70 | return 'guarded';
71 | };
72 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/src/auth.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient, HttpParams } from '@angular/common/http';
2 | import { Inject, Injectable } from '@angular/core';
3 | import { Router } from '@angular/router';
4 | import { Observable } from 'rxjs';
5 | import { switchMap } from 'rxjs/operators';
6 |
7 | import { AuthLoader } from './auth.loader';
8 |
9 | @Injectable()
10 | export class AuthService {
11 | protected _token: string;
12 | private _redirectUrl: string;
13 |
14 | get token(): string {
15 | return this._token;
16 | }
17 |
18 | get redirectUrl(): string {
19 | return this._redirectUrl;
20 | }
21 |
22 | set redirectUrl(value: string) {
23 | this._redirectUrl = value;
24 | }
25 |
26 | get defaultUrl(): string {
27 | return this.loader.defaultUrl;
28 | }
29 |
30 | get isAuthenticated(): boolean {
31 | return !!this.loader.storage.getItem(this.loader.storageKey);
32 | }
33 |
34 | constructor(readonly loader: AuthLoader, protected readonly router: Router, @Inject(HttpClient) protected readonly http: HttpClient) {
35 | const stored = this.loader.storage.getItem(this.loader.storageKey);
36 | const authContent = stored ? stored : '{}';
37 | const currentUser = JSON.parse(authContent);
38 | this._token = currentUser && currentUser.token;
39 | }
40 |
41 | authenticate(username: string, password: string): Observable {
42 | const params = this.getHttpParams(this.loader.backend.params);
43 |
44 | return this.http
45 | .post(
46 | this.loader.backend.endpoint,
47 | JSON.stringify({
48 | username,
49 | password
50 | }),
51 | { params }
52 | )
53 | .pipe(
54 | switchMap(async res => {
55 | const token = res && res.token;
56 |
57 | if (token) {
58 | this._token = token;
59 |
60 | this.loader.storage.setItem(
61 | this.loader.storageKey,
62 | JSON.stringify({
63 | username,
64 | token
65 | })
66 | );
67 |
68 | return this.router.navigateByUrl(this._redirectUrl || this.loader.defaultUrl).then(() => true);
69 | }
70 |
71 | return Promise.resolve(false);
72 | })
73 | );
74 | }
75 |
76 | async invalidate(): Promise {
77 | this._token = undefined;
78 | this.loader.storage.removeItem(this.loader.storageKey);
79 |
80 | return this.router.navigate(this.loader.loginRoute);
81 | }
82 |
83 | protected getHttpParams = (query?: Array): HttpParams => {
84 | let res = new HttpParams();
85 |
86 | if (query) {
87 | for (const item of query) {
88 | res = res.append(item.key, item.value);
89 | }
90 | }
91 |
92 | return res;
93 | };
94 | }
95 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './models/auth-settings';
2 | export * from './models/backend';
3 | export * from './auth-server.guard';
4 | export * from './auth.guard';
5 | export * from './auth.loader';
6 | export * from './auth.module';
7 | export * from './auth.service';
8 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/src/models/auth-settings.ts:
--------------------------------------------------------------------------------
1 | import { Backend } from './backend';
2 |
3 | export interface AuthSettings {
4 | backend: Backend;
5 | storage: any;
6 | storageKey: string;
7 | loginRoute: Array;
8 | defaultUrl: string;
9 | }
10 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/src/models/backend.ts:
--------------------------------------------------------------------------------
1 | export interface Backend {
2 | endpoint: string;
3 | params: Array<{
4 | key: string;
5 | value: string;
6 | }>;
7 | }
8 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/testing/auth.testing.module.ts:
--------------------------------------------------------------------------------
1 | import { HTTP_INTERCEPTORS } from '@angular/common/http';
2 | import { HttpClientTestingModule } from '@angular/common/http/testing';
3 | import { InjectionToken, ModuleWithProviders, NgModule } from '@angular/core';
4 |
5 | import { authFactory, AuthModule } from '../src';
6 | import { AuthLoader } from '../src/auth.loader';
7 |
8 | import { MockBackendInterceptor } from './mocks/backend-interceptor.mock';
9 | import { MockJwtInterceptor } from './mocks/jwt-interceptor.mock';
10 |
11 | export * from './mocks/backend-interceptor.mock';
12 | export * from './mocks/jwt-interceptor.mock';
13 |
14 | export const MOCK_AUTH_PATH = new InjectionToken('MOCK_AUTH_PATH');
15 |
16 | @NgModule({
17 | imports: [HttpClientTestingModule],
18 | exports: [AuthModule],
19 | providers: [
20 | {
21 | provide: MOCK_AUTH_PATH,
22 | useValue: '/api/authenticate'
23 | },
24 | {
25 | provide: AuthLoader,
26 | useFactory: authFactory
27 | },
28 | {
29 | provide: HTTP_INTERCEPTORS,
30 | useClass: MockBackendInterceptor,
31 | deps: [MOCK_AUTH_PATH],
32 | multi: true
33 | },
34 | {
35 | provide: HTTP_INTERCEPTORS,
36 | useClass: MockJwtInterceptor,
37 | deps: [AuthLoader],
38 | multi: true
39 | }
40 | ]
41 | })
42 | export class AuthTestingModule {
43 | static withParams(
44 | configuredProvider: any = {
45 | provide: AuthLoader,
46 | useFactory: authFactory
47 | },
48 | path: string
49 | ): ModuleWithProviders {
50 | return {
51 | ngModule: AuthTestingModule,
52 | providers: [
53 | configuredProvider,
54 | {
55 | provide: MOCK_AUTH_PATH,
56 | useValue: path
57 | }
58 | ]
59 | };
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/testing/mocks/backend-interceptor.mock.ts:
--------------------------------------------------------------------------------
1 | import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Observable, of as observableOf } from 'rxjs';
4 |
5 | @Injectable()
6 | export class MockBackendInterceptor implements HttpInterceptor {
7 | constructor(private readonly path: string) {}
8 |
9 | intercept(request: HttpRequest, next: HttpHandler): Observable> {
10 | if (request.url.split('?')[0].endsWith(this.path) && request.method === 'POST') {
11 | const testUser: any = {
12 | username: 'valid',
13 | password: 'valid'
14 | };
15 |
16 | const body = JSON.parse(request.body);
17 |
18 | if (body.username === testUser.username && body.password === testUser.password) {
19 | return observableOf(
20 | new HttpResponse({
21 | status: 200,
22 | body: { token: 'fake-jwt-token' }
23 | })
24 | );
25 | }
26 |
27 | return observableOf(new HttpResponse({ status: 401 }));
28 | }
29 |
30 | return next.handle(request);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/testing/mocks/jwt-interceptor.mock.ts:
--------------------------------------------------------------------------------
1 | import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Observable } from 'rxjs';
4 |
5 | import { AuthLoader } from '../../src/auth.loader';
6 |
7 | @Injectable()
8 | export class MockJwtInterceptor implements HttpInterceptor {
9 | constructor(private readonly loader: AuthLoader) {}
10 |
11 | intercept(request: HttpRequest, next: HttpHandler): Observable> {
12 | const token = JSON.parse(this.loader.storage.getItem(this.loader.storageKey)).token;
13 | const intercepted = token
14 | ? request.clone({
15 | setHeaders: {
16 | Authorization: `Bearer ${token}`
17 | }
18 | })
19 | : request;
20 |
21 | return next.handle(intercepted);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/tests/auth-server.guard.spec.ts:
--------------------------------------------------------------------------------
1 | import { inject, TestBed } from '@angular/core/testing';
2 | import { Router } from '@angular/router';
3 |
4 | import { TestBootstrapComponent, testServerModuleConfig } from './common';
5 |
6 | describe('@ngx-auth/core:', () => {
7 | beforeEach(testServerModuleConfig);
8 |
9 | describe('AuthServerGuard', () => {
10 | it('should not `Activate`', inject([Router], async (router: Router) => {
11 | const fixture = TestBed.createComponent(TestBootstrapComponent);
12 | fixture.detectChanges();
13 |
14 | return router.navigate(['/']).then(async () => {
15 | expect(router.url).toEqual('/');
16 |
17 | return router.navigate(['/activate-page']).then(async () => {
18 | expect(router.url).toEqual('/');
19 |
20 | return router.navigate(['/activate-feature']).then(() => {
21 | expect(router.url).toEqual('/');
22 | });
23 | });
24 | });
25 | }));
26 |
27 | it('should not `Load`', inject([Router], async (router: Router) => {
28 | const fixture = TestBed.createComponent(TestBootstrapComponent);
29 | fixture.detectChanges();
30 |
31 | return router.navigate(['/']).then(async () => {
32 | expect(router.url).toEqual('/');
33 |
34 | return router.navigate(['/load-page']).then(() => {
35 | expect(router.url).toEqual('/');
36 | });
37 | });
38 | }));
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/tests/auth-server.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { inject } from '@angular/core/testing';
2 |
3 | import { AuthService } from '../src';
4 | import { AuthServerService } from '../src/auth-server.service';
5 |
6 | import { testServerModuleConfig } from './common';
7 |
8 | describe('@ngx-auth/core:', () => {
9 | beforeEach(testServerModuleConfig);
10 |
11 | describe('AuthServerService', () => {
12 | beforeEach(inject([AuthService], async (auth: AuthService) => auth.invalidate()));
13 |
14 | it('is defined', inject([AuthService], (auth: AuthService) => {
15 | expect(AuthService).toBeDefined();
16 | expect(auth).toBeDefined();
17 | expect(auth instanceof AuthServerService).toBeTruthy();
18 | }));
19 |
20 | it('should be able to return an undefined `defaultUrl`', inject([AuthService], (auth: AuthService) => {
21 | const res = auth.defaultUrl;
22 | expect(res).toBeUndefined();
23 | }));
24 |
25 | it('should not authenticate', inject([AuthService], (auth: AuthService) => {
26 | auth.authenticate('valid', 'valid').subscribe(res => {
27 | expect(res).toEqual(false);
28 |
29 | const token = auth.token;
30 | expect(token).toBeUndefined();
31 |
32 | auth.redirectUrl = 'testUrl';
33 | const redirectUrl = auth.redirectUrl;
34 | expect(redirectUrl).toBeUndefined();
35 |
36 | const isAuthenticated = auth.isAuthenticated;
37 | expect(isAuthenticated).toEqual(false);
38 | });
39 | }));
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/tests/auth.guard.spec.ts:
--------------------------------------------------------------------------------
1 | import { inject, TestBed } from '@angular/core/testing';
2 | import { Router } from '@angular/router';
3 |
4 | import { AuthLoader, AuthService, AuthStaticLoader } from '../src';
5 |
6 | import { mockAuthData, TestBootstrapComponent, testModuleConfig } from './common';
7 |
8 | describe('@ngx-auth/core:', () => {
9 | beforeEach(() => {
10 | const authFactory = () => new AuthStaticLoader();
11 |
12 | testModuleConfig({
13 | provide: AuthLoader,
14 | useFactory: authFactory
15 | });
16 | });
17 |
18 | describe('AuthGuard', () => {
19 | beforeEach(inject([AuthService], async (auth: AuthService) => auth.invalidate()));
20 |
21 | it('should be able to `Activate` w/authentication', inject([Router, AuthLoader], async (router: Router, loader: AuthLoader) => {
22 | const fixture = TestBed.createComponent(TestBootstrapComponent);
23 | fixture.detectChanges();
24 |
25 | loader.storage.setItem(loader.storageKey, mockAuthData);
26 |
27 | return router.navigate(['/']).then(async () => {
28 | expect(router.url).toEqual('/');
29 |
30 | return router.navigate(['/activate-page']).then(async () => {
31 | expect(router.url).toEqual('/activate-page');
32 |
33 | return router.navigate(['/activate-feature']).then(() => {
34 | expect(router.url).toEqual('/activate-feature');
35 | });
36 | });
37 | });
38 | }));
39 |
40 | it('should not `Activate` w/o authentication', inject([Router], async (router: Router) => {
41 | const fixture = TestBed.createComponent(TestBootstrapComponent);
42 | fixture.detectChanges();
43 |
44 | return router.navigate(['/']).then(async () => {
45 | expect(router.url).toEqual('/');
46 |
47 | return router.navigate(['/activate-page']).then(async () => {
48 | expect(router.url).toEqual('/login');
49 |
50 | return router.navigate(['/activate-feature']).then(() => {
51 | expect(router.url).toEqual('/login');
52 | });
53 | });
54 | });
55 | }));
56 |
57 | it('should be able to `Load` w/authentication', inject([Router, AuthLoader], async (router: Router, loader: AuthLoader) => {
58 | const fixture = TestBed.createComponent(TestBootstrapComponent);
59 | fixture.detectChanges();
60 |
61 | loader.storage.setItem(loader.storageKey, mockAuthData);
62 |
63 | return router.navigate(['/']).then(async () => {
64 | expect(router.url).toEqual('/');
65 |
66 | return router.navigate(['/load-page']).then(() => {
67 | expect(router.url).toEqual('/load-page');
68 | });
69 | });
70 | }));
71 |
72 | it('should not `Load` w/o authentication', inject([Router], async (router: Router) => {
73 | const fixture = TestBed.createComponent(TestBootstrapComponent);
74 | fixture.detectChanges();
75 |
76 | return router.navigate(['/']).then(async () => {
77 | expect(router.url).toEqual('/');
78 |
79 | return router.navigate(['/load-page']).then(() => {
80 | expect(router.url).toEqual('/login');
81 | });
82 | });
83 | }));
84 | });
85 | });
86 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/tests/auth.loader.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 |
3 | import { AuthLoader, AuthService, AuthStaticLoader, Backend } from '../src';
4 |
5 | import { testModuleConfig, testSettings } from './common';
6 |
7 | describe('@ngx-auth/core:', () => {
8 | beforeEach(() => {
9 | const authFactory = () => new AuthStaticLoader();
10 |
11 | testModuleConfig({
12 | provide: AuthLoader,
13 | useFactory: authFactory
14 | });
15 | });
16 |
17 | describe('AuthLoader', () => {
18 | it('should be able to return the default authSettings', () => {
19 | const loader = new AuthStaticLoader();
20 |
21 | expect(loader.backend.endpoint).toEqual(testSettings.backend.endpoint);
22 | expect(loader.backend.params).toEqual([]);
23 | expect(loader.storage).toEqual(testSettings.storage);
24 | expect(loader.storageKey).toEqual(testSettings.storageKey);
25 | expect(loader.loginRoute).toEqual(testSettings.loginRoute);
26 | expect(loader.defaultUrl).toEqual(testSettings.defaultUrl);
27 | });
28 |
29 | it('should be able to return custom authSettings', () => {
30 | const loader = new AuthStaticLoader(testSettings);
31 |
32 | expect(loader.backend).toEqual(testSettings.backend);
33 | expect(loader.storage).toEqual(testSettings.storage);
34 | expect(loader.storageKey).toEqual(testSettings.storageKey);
35 | expect(loader.loginRoute).toEqual(testSettings.loginRoute);
36 | expect(loader.defaultUrl).toEqual(testSettings.defaultUrl);
37 | });
38 |
39 | it('should be able to provide `AuthStaticLoader`', () => {
40 | const auth = TestBed.get(AuthService);
41 |
42 | expect(AuthStaticLoader).toBeDefined();
43 | expect(auth.loader).toBeDefined();
44 | expect(auth.loader instanceof AuthStaticLoader).toBeTruthy();
45 | });
46 |
47 | it('should be able to provide any `AuthLoader`', () => {
48 | class CustomLoader implements AuthLoader {
49 | get backend(): Backend {
50 | return testSettings.backend;
51 | }
52 |
53 | get storage(): any {
54 | return testSettings.storage;
55 | }
56 |
57 | get storageKey(): string {
58 | return testSettings.storageKey;
59 | }
60 |
61 | get loginRoute(): Array {
62 | return testSettings.loginRoute;
63 | }
64 |
65 | get defaultUrl(): string {
66 | return testSettings.defaultUrl;
67 | }
68 | }
69 |
70 | testModuleConfig({
71 | provide: AuthLoader,
72 | useClass: CustomLoader
73 | });
74 |
75 | const auth = TestBed.get(AuthService);
76 |
77 | expect(CustomLoader).toBeDefined();
78 | expect(auth.loader).toBeDefined();
79 | expect(auth.loader instanceof CustomLoader).toBeTruthy();
80 | });
81 | });
82 | });
83 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/tests/auth.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { inject, TestBed } from '@angular/core/testing';
2 |
3 | import { AuthLoader, AuthService, AuthStaticLoader } from '../src';
4 |
5 | import { TestBootstrapComponent, testModuleConfig, testSettings } from './common';
6 |
7 | describe('@ngx-auth/core:', () => {
8 | beforeEach(() => {
9 | const authFactory = () => new AuthStaticLoader(testSettings);
10 |
11 | testModuleConfig({
12 | provide: AuthLoader,
13 | useFactory: authFactory
14 | });
15 | });
16 |
17 | describe('AuthService', () => {
18 | beforeEach(inject([AuthService], async (auth: AuthService) => auth.invalidate()));
19 |
20 | it('is defined', inject([AuthService], (auth: AuthService) => {
21 | expect(AuthService).toBeDefined();
22 | expect(auth).toBeDefined();
23 | expect(auth instanceof AuthService).toBeTruthy();
24 | }));
25 |
26 | it('should be able to return the `defaultUrl`', inject([AuthService], (auth: AuthService) => {
27 | const res = auth.defaultUrl;
28 | expect(res).toEqual('');
29 | }));
30 |
31 | it('should be able to authenticate w/valid combination', inject([AuthService], (auth: AuthService) => {
32 | const fixture = TestBed.createComponent(TestBootstrapComponent);
33 | fixture.detectChanges();
34 |
35 | auth.authenticate('valid', 'valid').subscribe(res => {
36 | expect(res).toEqual(true);
37 |
38 | const token = auth.token;
39 | expect(token).toBeDefined();
40 |
41 | const redirectUrl = auth.redirectUrl;
42 | expect(redirectUrl).toBeUndefined();
43 |
44 | const isAuthenticated = auth.isAuthenticated;
45 | expect(isAuthenticated).toEqual(true);
46 | });
47 | }));
48 |
49 | it('should not authenticate w/o valid combination', inject([AuthService], (auth: AuthService) => {
50 | const fixture = TestBed.createComponent(TestBootstrapComponent);
51 | fixture.detectChanges();
52 |
53 | auth.authenticate('invalid', 'invalid').subscribe(res => {
54 | expect(res).toEqual(false);
55 |
56 | const token = auth.token;
57 | expect(token).toBeUndefined();
58 |
59 | const redirectUrl = auth.redirectUrl;
60 | expect(redirectUrl).toBeUndefined();
61 |
62 | const isAuthenticated = auth.isAuthenticated;
63 | expect(isAuthenticated).toEqual(false);
64 | });
65 | }));
66 | });
67 | });
68 |
--------------------------------------------------------------------------------
/packages/@ngx-auth/core/tests/common.ts:
--------------------------------------------------------------------------------
1 | import { Component, NgModule } from '@angular/core';
2 | import { TestBed } from '@angular/core/testing';
3 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
4 | import { Routes } from '@angular/router';
5 | import { RouterTestingModule } from '@angular/router/testing';
6 |
7 | import { AuthGuard, AuthModule, AuthSettings } from '../src';
8 | import { AuthTestingModule } from '../testing/auth.testing.module';
9 |
10 | @Component({ template: ' ' })
11 | export class TestBootstrapComponent {}
12 |
13 | @Component({ template: '' })
14 | export class TestComponent {}
15 |
16 | @NgModule({
17 | imports: [RouterTestingModule],
18 | declarations: [TestBootstrapComponent, TestComponent]
19 | })
20 | class TestSharedModule {}
21 |
22 | const testLazyRoutes: Routes = [
23 | {
24 | path: '',
25 | component: TestComponent
26 | }
27 | ];
28 |
29 | @NgModule({
30 | imports: [RouterTestingModule.withRoutes(testLazyRoutes), TestSharedModule]
31 | })
32 | class TestLazyModule {}
33 |
34 | const testRoutes: Routes = [
35 | {
36 | path: '',
37 | component: TestBootstrapComponent,
38 | children: [
39 | {
40 | path: '',
41 | component: TestComponent
42 | },
43 | {
44 | path: 'activate-page',
45 | component: TestComponent,
46 | canActivate: [AuthGuard]
47 | },
48 | {
49 | path: 'load-page',
50 | loadChildren: () => TestLazyModule,
51 | canLoad: [AuthGuard]
52 | },
53 | {
54 | path: 'activate-feature',
55 | children: [
56 | {
57 | path: '',
58 | component: TestComponent,
59 | canActivate: [AuthGuard]
60 | }
61 | ],
62 | canActivateChild: [AuthGuard]
63 | },
64 | {
65 | path: 'login',
66 | component: TestComponent
67 | }
68 | ]
69 | }
70 | ];
71 |
72 | export const testSettings: AuthSettings = {
73 | backend: {
74 | endpoint: '/api/authenticate',
75 | params: [
76 | {
77 | key: 'test',
78 | value: 'test'
79 | }
80 | ]
81 | },
82 | storage: localStorage,
83 | storageKey: 'currentUser',
84 | loginRoute: ['login'],
85 | defaultUrl: ''
86 | };
87 |
88 | export const mockAuthData = JSON.stringify({
89 | username: 'username',
90 | token: 'token'
91 | });
92 |
93 | export const testModuleConfig = (moduleOptions?: any) => {
94 | TestBed.resetTestEnvironment();
95 |
96 | TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()).configureTestingModule({
97 | imports: [
98 | RouterTestingModule.withRoutes(testRoutes),
99 | AuthModule.forRoot(moduleOptions),
100 | AuthTestingModule.withParams(moduleOptions, '/api/authenticate'),
101 | TestSharedModule
102 | ]
103 | });
104 | };
105 |
106 | export const testServerModuleConfig = () => {
107 | TestBed.resetTestEnvironment();
108 |
109 | TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()).configureTestingModule({
110 | imports: [RouterTestingModule.withRoutes(testRoutes), AuthModule.forServer(), TestSharedModule]
111 | });
112 | };
113 |
--------------------------------------------------------------------------------
/tools/build/helpers.ts:
--------------------------------------------------------------------------------
1 | // tslint:disable
2 | import * as path from 'path';
3 |
4 | export function root(args: any = ''): string {
5 | const ROOT = path.resolve(__dirname, '../..');
6 | args = [].slice.call(arguments, 0);
7 |
8 | return path.join.apply(path, [ROOT].concat(args));
9 | }
10 |
--------------------------------------------------------------------------------
/tools/build/packager.ts:
--------------------------------------------------------------------------------
1 | import { ngPackagr } from 'ng-packagr';
2 |
3 | import { root } from './helpers';
4 |
5 | ngPackagr()
6 | .forProject(root(`./packages/@ngx-auth/${process.argv[2]}/ng-package.json`))
7 | .withTsConfig(root('./tools/build/tsconfig.package.json'))
8 | .build()
9 | .catch(() => (process.exitCode = 1));
10 |
--------------------------------------------------------------------------------
/tools/build/tsconfig.package.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "target": "es2015",
5 | "module": "es2015",
6 | "noImplicitAny": true,
7 | "suppressImplicitAnyIndexErrors": true,
8 | "importHelpers": true,
9 | "sourceMap": true,
10 | "inlineSources": true,
11 | "declaration": true,
12 | "removeComments": true,
13 | "stripInternal": true,
14 | "rootDir": "./",
15 | "baseUrl": "",
16 | "paths": {
17 | "@ngx-auth/*": ["../../dist/@ngx-auth/*"]
18 | },
19 | "typeRoots": ["../../node_modules/@types"],
20 | "lib": [
21 | "es2015",
22 | "dom"
23 | ]
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/tools/test/jest.setup.ts:
--------------------------------------------------------------------------------
1 | // tslint:disable
2 | import 'jest-preset-angular';
3 |
4 | const mock = () => {
5 | let storage = {};
6 |
7 | return {
8 | getItem: (key: string) => (key in storage ? (storage as any)[key] : undefined),
9 | setItem: (key: string, value: any) => ((storage as any)[key] = value || ''),
10 | removeItem: (key: string) => delete (storage as any)[key],
11 | clear: () => (storage = {})
12 | };
13 | };
14 |
15 | Object.defineProperty(window, 'CSS', { value: mock() });
16 | Object.defineProperty(window, 'localStorage', { value: mock() });
17 | Object.defineProperty(window, 'sessionStorage', { value: mock() });
18 |
19 | Object.defineProperty(document, 'doctype', {
20 | value: ''
21 | });
22 |
23 | Object.defineProperty(window, 'getComputedStyle', {
24 | value: () => {
25 | return {
26 | display: 'none',
27 | appearance: ['-webkit-appearance']
28 | };
29 | }
30 | });
31 |
--------------------------------------------------------------------------------
/tools/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "../tslint.json"
4 | ],
5 | "rules": {
6 | "no-implicit-dependencies": [
7 | true,
8 | "dev"
9 | ],
10 | "no-dynamic-delete": false
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "rootDir": ".",
4 | "sourceMap": true,
5 | "declaration": false,
6 | "moduleResolution": "node",
7 | "emitDecoratorMetadata": true,
8 | "experimentalDecorators": true,
9 | "importHelpers": true,
10 | "target": "es2015",
11 | "module": "commonjs",
12 | "typeRoots": ["node_modules/@types"],
13 | "lib": ["es2017", "dom"],
14 | "skipLibCheck": true,
15 | "skipDefaultLibCheck": true,
16 | "baseUrl": ".",
17 | "paths": {
18 | "@ngx-auth/core": ["packages/@ngx-auth/core/src/index.ts"],
19 | "@ngx-auth/auth0": ["packages/@ngx-auth/auth0/src/index.ts"]
20 | },
21 | "noImplicitAny": true,
22 | "suppressImplicitAnyIndexErrors": true
23 | },
24 | "include": ["tools/**/*.ts", "packages/**/*.ts"]
25 | }
26 |
--------------------------------------------------------------------------------
/tsconfig.lint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "target": "es2015",
5 | "strictNullChecks": true
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": ["node_modules/codelyzer"],
3 | "extends": ["angular-tslint-rules", "tslint-config-prettier"],
4 | "rules": {
5 | "ordered-imports": [
6 | true,
7 | {
8 | "import-sources-order": "case-insensitive",
9 | "named-imports-order": "case-insensitive",
10 | "grouped-imports": true
11 | }
12 | ]
13 | }
14 | }
15 |
--------------------------------------------------------------------------------