├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config,yml │ └── feature_request.md ├── SUPPORT.md ├── dependabot.yml ├── pull_request_template.md ├── stale.yml └── workflows │ ├── codeql-analysis.yml │ └── release.yml ├── .gitignore ├── .husky ├── .gitignore ├── commit-msg └── pre-commit ├── .idea ├── .gitignore ├── copyright │ ├── arkadip_apache2.xml │ └── profiles_settings.xml ├── jsLibraryMappings.xml ├── jsonSchemas.xml ├── misc.xml ├── modules.xml ├── react-auth-kit.iml ├── runConfigurations.xml └── vcs.xml ├── CHANGELOG-OLD.md ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── commitlint.config.js ├── docs ├── CNAME ├── authdata.md ├── authheader.md ├── checkauth.md ├── contributing.md ├── docs_overrides │ └── main.html ├── img │ ├── banner.svg │ ├── favicon.png │ ├── image.png │ └── logo.svg ├── index.md ├── installation.md ├── integration.md ├── privateroute.md ├── refreshtoken.md ├── robots.txt ├── signin.md └── signout.md ├── examples ├── cdn │ ├── index.html │ └── package.json ├── create-react-app-refresh-token │ ├── .env │ ├── .gitignore │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ └── src │ │ ├── App.js │ │ ├── Routes.js │ │ ├── components │ │ ├── Home.js │ │ ├── Login.js │ │ └── SecureComponent.js │ │ ├── index.js │ │ ├── refreshApi.js │ │ ├── serviceWorker.js │ │ └── setupTests.js └── create-react-app │ ├── .env │ ├── .gitignore │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ └── src │ ├── App.js │ ├── Routes.js │ ├── components │ ├── Home.js │ ├── Login.js │ └── SecureComponent.js │ ├── index.js │ ├── serviceWorker.js │ └── setupTests.js ├── jest.config.js ├── mkdocs.yml ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── .eslintrc ├── AuthContext.ts ├── AuthProvider.tsx ├── PrivateRoute.tsx ├── TokenObject.ts ├── __tests__ │ ├── AuthProvider.test.tsx │ ├── PrivateRoute.test.tsx │ ├── TokenObject.test.ts │ ├── hooks │ │ ├── useAuthHeader.test.tsx │ │ ├── useAuthUser.test.tsx │ │ ├── useIsAuthenticated.test.tsx │ │ ├── useSignIn.test.tsx │ │ └── useSignOut.test.tsx │ ├── index.test.tsx │ └── utils │ │ ├── hooks.test.ts │ │ └── reducers.test.ts ├── createRefresh.ts ├── higherOrderComponents │ ├── withAuthHeader.tsx │ ├── withAuthUser.tsx │ ├── withIsAuthenticated.tsx │ ├── withSignIn.tsx │ └── withSignOut.tsx ├── hooks │ ├── useAuthHeader.ts │ ├── useAuthUser.ts │ ├── useIsAuthenticated.ts │ ├── useSignIn.ts │ └── useSignOut.ts ├── index.tsx ├── types.ts └── utils │ ├── actions.ts │ ├── hooks.ts │ └── reducers.ts └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | types 2 | dist 3 | node_modules 4 | .idea 5 | env 6 | docs 7 | docs_overrides -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'env': { 3 | 'browser': true, 4 | 'es2021': true, 5 | }, 6 | 'extends': [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/eslint-recommended", 9 | "plugin:@typescript-eslint/recommended", 10 | 'plugin:react/recommended', 11 | 'google', 12 | ], 13 | 'parser': '@typescript-eslint/parser', 14 | 'parserOptions': { 15 | 'ecmaFeatures': { 16 | 'jsx': true, 17 | }, 18 | 'ecmaVersion': 12, 19 | 'sourceType': 'module', 20 | }, 21 | 'plugins': [ 22 | 'react', 23 | '@typescript-eslint', 24 | ], 25 | 'settings': { 26 | 'react': { 27 | 'version': 'detect', 28 | } 29 | }, 30 | 'rules': { 31 | 'react/prop-types': 0, 32 | 'react/display-name': 0, 33 | 'valid-jsdoc': 0, 34 | "no-unused-vars": "off", 35 | "@typescript-eslint/no-unused-vars": ["error"], 36 | "@typescript-eslint/no-explicit-any": "off" 37 | }, 38 | }; 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config,yml: -------------------------------------------------------------------------------- 1 | 2 | blank_issues_enabled: false 3 | contact_links: 4 | - name: Arkadip Bhattacharya 5 | url: https://arkadip.co/ 6 | about: Please ask and answer questions here. 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | > This project has a [Code of Conduct](https://github.com/react-auth-kit/react-auth-kit/blob/master/CODE_OF_CONDUCT.md). 4 | > By interacting with this repository, organisation, or community you agree to 5 | > abide by its terms. 6 | 7 | Hi! 👋 8 | We’re excited that you’re using **remark** and we’d love to help. 9 | To help us help you, please read through the following guidelines. 10 | 11 | Please understand that people involved with this project often do so for fun, 12 | next to their day job; you are not entitled to free customer service. 13 | 14 | ## Contributions 15 | 16 | See [`contributing.md`](https://github.com/react-auth-kit/react-auth-kit/blob/master/CONTRIBUTING.md) on how to contribute. 17 | 18 | ## License 19 | 20 | [Apache-2.0](https://github.com/react-auth-kit/react-auth-kit/blob/master/LICENSE) © [React Auth Kit](https://github.com/react-auth-kit/react-auth-kit) 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | versioning-strategy: increase 9 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Related Issues 2 | 6 | 7 | ## Types of changes 8 | 9 | - [ ] Bug fix (non-breaking change which fixes an issue) 10 | - [ ] New feature (non-breaking change which adds functionality) 11 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 12 | - [ ] I have read the **CONTRIBUTING** document. 13 | - [ ] My code follows the code style of this project. 14 | - [ ] My change requires a change to the documentation. 15 | - [ ] I have updated the documentation accordingly. 16 | - [ ] I have added tests to cover my changes. 17 | - [ ] All new and existing tests passed. 18 | 19 | ## Description 20 | 21 | 22 | 23 | ## Screenshots/Recordings 24 | 25 | 26 | 27 | ## Added tests? 28 | 29 | - [ ] Yes 30 | - [ ] No, because they aren't needed 31 | 32 | ## Added to documentation? 33 | 34 | - [ ] README 35 | - [ ] Documentation 36 | - [ ] No Documentation Needed 37 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '45 19 * * 4' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | language: [ 'javascript' ] 32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 33 | # Learn more: 34 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 35 | 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@v2 39 | 40 | # Initializes the CodeQL tools for scanning. 41 | - name: Initialize CodeQL 42 | uses: github/codeql-action/init@v1 43 | with: 44 | languages: ${{ matrix.language }} 45 | # If you wish to specify custom queries, you can do so here or in a config file. 46 | # By default, queries listed here will override any specified in a config file. 47 | # Prefix the list here with "+" to use these queries and those in the config file. 48 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 49 | 50 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 51 | # If this step fails, then you should remove it and run the build manually (see below) 52 | - name: Autobuild 53 | uses: github/codeql-action/autobuild@v1 54 | 55 | # ℹ️ Command-line programs to run using the OS shell. 56 | # 📚 https://git.io/JvXDl 57 | 58 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 59 | # and modify them (or add more) to build your code if your project 60 | # uses a compiled language 61 | 62 | #- run: | 63 | # make bootstrap 64 | # make release 65 | 66 | - name: Perform CodeQL Analysis 67 | uses: github/codeql-action/analyze@v1 68 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Test and Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - next 8 | - beta 9 | pull_request: 10 | branches: 11 | - master 12 | - next 13 | - beta 14 | 15 | jobs: 16 | check-commit: 17 | name: Check Commit Messages 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v2 23 | with: 24 | fetch-depth: 0 25 | 26 | - name: Check Commit Messages 27 | uses: wagoid/commitlint-github-action@v4 28 | 29 | test-node: 30 | name: Test on Node.js v${{ matrix.node-version }} 31 | runs-on: ubuntu-latest 32 | needs: 33 | - check-commit 34 | 35 | strategy: 36 | matrix: 37 | node-version: [12.x, 14.x, 16.x] 38 | 39 | steps: 40 | - name: Checkout 41 | uses: actions/checkout@v2 42 | 43 | - name: Use Node.js ${{ matrix.node-version }} 44 | uses: actions/setup-node@v2 45 | with: 46 | node-version: ${{ matrix.node-version }} 47 | 48 | - name: NPM Install 49 | run: npm ci 50 | 51 | - name: NPM Test 52 | run: npm test 53 | 54 | - name: Generate Codecov Report 55 | uses: codecov/codecov-action@v2 56 | 57 | test-os: 58 | name: Test on ${{ matrix.os }} using Node.js LTS 59 | needs: 60 | - check-commit 61 | strategy: 62 | matrix: 63 | os: [ ubuntu-latest, windows-latest, macOS-latest ] 64 | runs-on: ${{ matrix.os }} 65 | 66 | steps: 67 | - name: Checkout 68 | uses: actions/checkout@v2 69 | 70 | - name: Setting Up Node 14.x 71 | uses: actions/setup-node@v2 72 | with: 73 | node-version: 14.x 74 | 75 | - name: NPM Install 76 | run: npm ci 77 | 78 | - name: NPM Test 79 | run: npm test 80 | 81 | - name: Generate Codecov Report 82 | uses: codecov/codecov-action@v2 83 | 84 | release: 85 | name: Release 86 | runs-on: ubuntu-latest 87 | needs: 88 | - check-commit 89 | - test-node 90 | - test-os 91 | 92 | outputs: 93 | tag: ${{ steps.tag.outputs.tag }} 94 | steps: 95 | - name: Checkout 96 | uses: actions/checkout@v2 97 | with: 98 | fetch-depth: 0 99 | - name: Setup Node.js 100 | uses: actions/setup-node@v2 101 | with: 102 | node-version: 'lts/*' 103 | - name: Install dependencies 104 | run: npm ci 105 | - name: Release 106 | env: 107 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 108 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 109 | run: npx semantic-release 110 | 111 | - name: Get latest Tag 112 | id: tag 113 | run: | 114 | echo "::set-output name=tag::$(git describe --tags --abbrev=0)" 115 | 116 | release-docs: 117 | name: Release Docs 118 | runs-on: ubuntu-latest 119 | if: ${{ github.event_name == 'push' }} 120 | needs: 121 | - release 122 | 123 | steps: 124 | - name: Checkout 125 | uses: actions/checkout@v2 126 | 127 | - name: Config the Action user 128 | run: | 129 | git fetch origin gh-pages --depth=1 130 | git config user.name github-actions 131 | git config user.email github-actions@github.com 132 | 133 | - name: Setup Python 134 | uses: actions/setup-python@v2 135 | with: 136 | python-version: 3.x 137 | 138 | - name: Install dependency 139 | run: | 140 | pip install mkdocs-material 141 | pip install mike 142 | 143 | - name: Deploying docs in Master 144 | run: | 145 | mike deploy --push --update-aliases ${{needs.release.outputs.tag}} latest 146 | mike set-default --push latest 147 | if: ${{ github.ref == 'refs/heads/master' }} 148 | 149 | - name: Deploying docs in Beta or Next 150 | run: mike deploy --push ${{needs.release.outputs.tag}} 151 | if: ${{ github.ref != 'refs/heads/master' }} 152 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | types 4 | /env/ 5 | coverage 6 | .eslintcache 7 | -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit "$1" 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /../../../../:\Projects\react-auth-kit\.idea/dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /.idea/copyright/arkadip_apache2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/jsonSchemas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/react-auth-kit.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CHANGELOG-OLD.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [1.5.5] - 2021-10-19 8 | ## Fix 9 | - Docs releasing fixed by fetching the branch (#639) 10 | 11 | ## [1.5.4] - 2021-10-19 12 | ## Fix 13 | - Docs releasing fixed by adding the action user (#638) 14 | 15 | ## [1.5.3] - 2021-10-19 16 | ## Fix 17 | - Releasing docs my mike (#637) 18 | 19 | ## [1.5.2] - 2021-10-19 20 | ## Updated 21 | - Docs are now using versioning (#636) 22 | 23 | ## [1.5.1] - 2021-10-19 24 | ## Updated 25 | - Docs are made smooth (#635) 26 | 27 | ## [1.5.0] - 2021-10-18 28 | ## Added: 29 | - Refresh Token feature (#603) 30 | - Added Documentation for Refresh Token (#629) 31 | - Unit test for actions/reducers.ts (#587) 32 | - Unit test for TokenObject.ts (#592) 33 | - Unit test for PrivateRoute.tsx (#606) 34 | - Unit test for utils/hooks.ts (#618) 35 | - Unit test for AuthProvider.tsx(#617) 36 | 37 | ## Thanks to 38 | 39 | - [@atrievel](https://github.com/atrievel) 40 | - [@tumit](https://github.com/tumit) 41 | - [@sitek94](https://github.com/sitek94) 42 | - [@DarrylBrooks97](https://github.com/DarrylBrooks97) 43 | - [@jason1985](https://github.com/jason1985) 44 | - [@katieraby](https://github.com/katieraby) 45 | - [@ok524](https://github.com/ok524) 46 | 47 | 48 | ## [1.4.18] - 2021-09-10 49 | ## Changed: 50 | - Updated the internal state for better performance, and reliability 51 | 52 | ## [1.4.16] - 2021-08-03 53 | ### Fix: 54 | - On page refresh, the cookies are removed automatically ([#473](#473))([676f68b](676f68bc68de07e078b4e1ea6a28040abc2989dc)) 55 | - Auth Type cookie and Localstorage are failed to get removed ([cbfdc4e](cbfdc4eeac997e018b3faa8f8390a3f7c5d0b449)) 56 | 57 | ### Changed: 58 | - Minimum React Version from `16.0` to `16.8.0`, so that the hooks gets properly supported ([bad136e](bad136ea89c22b9600c72310d0d734a0b836d2c8)) 59 | - Sign In Hook and HOC is now better to accommodate the dynamic refresh token to give better error and type support ([17b2eb8](17b2eb813de0cb46a68ce43050b8f31ee5fbf458)) 60 | - Updated the `SignInActionPayload` in action and sign in reducer to accommodate the dynamic refresh token feature ([41be555](41be55524b76f9452ca61a603c744c6b27fc9e6a)) ([57c819f](57c819f56f85df9cef5d826d0064c3769cbfc110)) 61 | 62 | ### Removed: 63 | - [`useDebugValue`](https://reactjs.org/docs/hooks-reference.html#usedebugvalue) from 64 | `useAuthenticated` and `useAuthHeader` ([3d2966d](3d2966d5aafea95c930d957ff04bf1a15c5e01d0)) 65 | 66 | ## [1.4.14] - 2021-07-31 67 | ### Added: 68 | - [`useDebugValue`](https://reactjs.org/docs/hooks-reference.html#usedebugvalue) added in 69 | `useAuthenticated` and `useAuthHeader` 70 | 71 | ### Changed: 72 | - `ESM` and `CJS` builds are not going through the `terser` anymore 73 | 74 | ## [1.4.13] - 2021-07-30 75 | ### Changed: 76 | - Auth state now uses `useReducer` instead of `useState` 77 | 78 | ## [1.4.12] - 2021-07-25 79 | ### Changed: 80 | - PrivateRouteProps is updated to give more type checking 81 | 82 | ## [1.4.11] - 2021-06-19 83 | ### Changed: 84 | - Updated dependencies 85 | 86 | ### Fixed: 87 | - Deployment of docs 88 | 89 | ## [1.4.10] - 2021-06-08 90 | ### Added: 91 | - Sourcemaps added for each files 92 | 93 | ### Fixed: 94 | - Type declaration files are missing, so added them 95 | 96 | ## [1.4.9] - 2021-05-21 97 | ### Changed: 98 | - Migrated to @rollup/plugin-typescript 99 | - Terser added for Minified codebase 100 | 101 | ## [1.4.8] - 2021-05-07 102 | ### Fixed: 103 | - `authdata.md` wrong doc of useAuthUser (70e8d8839bb50e0f524815c16827efe9dd8da615) 104 | - Property 'user' does not exist on type 'object' (#343) 105 | 106 | ## [1.4.7] - 2021-04-11 107 | ### Changed: 108 | - `AuthProvider` props. AuthProvider is now only using 4 props. 109 | - Docs `/usage` is now `/integration` 110 | - Docs updated Intro and installation page 111 | - Better documentations added. 112 | 113 | ⚠️This release will break your code, as the AuthProvider props are changed. [Please refer to the docs](https://authkit.arkadip.me/integration) 114 | 115 | 116 | ## [1.4.6] - 2021-04-09 117 | ### Changed: 118 | - Docs updated 119 | 120 | ## [1.4.5] - 2021-02-10 121 | ### Fixed: 122 | - Potential risk of duplicate tokens 123 | 124 | ## [1.4.4] - 2021-01-15 125 | ### Fixed: 126 | - `authToken` and `authTokenType` key value pair swapped at `getCurrentAuthState()` in `RefreshToken` ([#197](https://github.com/react-auth-kit/react-auth-kit/issues/197)) ([8fc03f5](https://github.com/react-auth-kit/react-auth-kit/commit/8fc03f5cf90fb9372137fa85def7e3194196a1d7)) 127 | 128 | ### Thanks: 129 | - [**@philbert440**](https://github.com/philbert440) 130 | 131 | ## [1.4.3] - 2021-01-05 132 | ### Added: 133 | - Store Refresh Token for refreshing JWT 134 | 135 | ### Thanks: 136 | - [**@shackra**](https://github.com/shackra) 137 | 138 | ## [1.4.0] - 2020-12-20 139 | ### Added: 140 | - Added Refresh Token feature 141 | 142 | ## [1.3.4] - 2020-12-18 143 | ### Added: 144 | - Support for React 17 145 | 146 | ## [1.3.2] - 2020-12-17 147 | ### Fixed: 148 | - AuthProvider children type changed to `React.ReactNode` 149 | 150 | ## [1.3.1] - 2020-12-17 151 | ### Added: 152 | - Types added in npm release for better code completion. 153 | 154 | ## [1.3.0] - 2020-12-17 155 | ### Added: 156 | - Code base documentation. ([Hardik0307](https://github.com/Hardik0307)) 157 | - Guideline for Contribution added on project website ([dotslash21](https://github.com/dotslash21)) 158 | 159 | ### Fixed: 160 | - Eslint Linting issue 161 | - Contributing.md typo fix. ([dotslash21](https://github.com/dotslash21)) 162 | 163 | ## [1.2.2] - 2020-09-21 164 | ### Fixed 165 | - DOCS SEO 166 | 167 | ## [1.2.1] - 2020-09-16 168 | ### Fixed 169 | - `TS Function declararation` 170 | 171 | ## [1.2.0] - 2020-09-15 172 | ### Added 173 | - `useAuth` function added. Now use all hooks in 1 function. 174 | 175 | ### Fixed 176 | - Docs: Deprecated AuthProvider params names 177 | - `AuthProvider` pushing error for cookieSecure set as false 178 | - `useSignIn` function parameter 179 | - `withSignIn` function param 180 | 181 | ## [1.1.7] - 2020-09-14 182 | ### Added 183 | - `useIsAuthenticated` and `withIsAuthenticated` added. Now check if your user is logged in or not. 184 | 185 | ### Changed 186 | - ⚠ `useAuth` is changed to `useAuthUser` 187 | - ⚠ `withAuth` is changed to `withAuthUser` 188 | 189 | ## [1.1.6] - 2020-09-12 190 | ### Fixed 191 | - Linting the Codes 192 | 193 | ### Changed 194 | - Docs Override dir to `docs` dir 195 | 196 | ## [1.1.5] - 2020-09-12 197 | ### Fixed 198 | - Docs Meta Tags Fixed 199 | - Docs Site Map Fixed 200 | 201 | ## [1.1.4] - 2020-09-12 202 | ### Added 203 | - SEO added in docs 204 | 205 | ## [1.1.3] - 2020-09-10 206 | ### Fixed 207 | - Type Definition 208 | 209 | ### Changed 210 | - Size decreased from 2.12 KB to 1.81 KB 211 | 212 | ## [1.1.2] - 2020-09-10 213 | ### Changed 214 | - AuthContext is merged with AuthProvider 215 | 216 | ## [1.1.1] - 2020-09-08 217 | ### Added 218 | - Documentation [https://authkit.arkadip.co](https://authkit.arkadip.co) 219 | - Default props for `AuthProvider` 220 | 221 | ## [1.1.0] - 2020-09-08 222 | ### Added 223 | - Local Storage Added (Cookie and LocalStorage can be chosen by AuthProvider Prop `authStorageType`) 224 | - Documentation [https://authkit.arkadip.co](https://authkit.arkadip.co) 225 | - PrivateRoute now supports render and component props 226 | - Auth Token Type added on Sign In. Default `Bearer` 227 | 228 | ### Changed 229 | - `Sign In` function Arguments is now an object 230 | 231 | ## [1.0.2] - 2020-08-29 232 | ### Added 233 | - UMD module 234 | - Testing Added 235 | 236 | ### Removed 237 | - JS Map files 238 | 239 | ## [1.0.1] - 2020-08-28 240 | ### Added 241 | - Code Base Added 242 | - Bundling with Rollup 243 | 244 | ## [1.0.0] - 2020-08-27 245 | ### Added 246 | - Package Established 247 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.6.4](https://github.com/react-auth-kit/react-auth-kit/compare/v1.6.3...v1.6.4) (2021-12-07) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * signing param authState is now optional ([4c0dc4e](https://github.com/react-auth-kit/react-auth-kit/commit/4c0dc4e5eeabbbf011194ed0d3a6c34695169046)) 7 | 8 | ## [1.6.3](https://github.com/react-auth-kit/react-auth-kit/compare/v1.6.2...v1.6.3) (2021-12-07) 9 | 10 | 11 | ### Bug Fixes 12 | 13 | * **logic:** fixed refresh callback execution waiting ([fbfe38b](https://github.com/react-auth-kit/react-auth-kit/commit/fbfe38b28532589dfdcb090fe2149e3fbefb4ddd)) 14 | 15 | ## [1.6.3-beta.1](https://github.com/react-auth-kit/react-auth-kit/compare/v1.6.2...v1.6.3-beta.1) (2021-12-06) 16 | 17 | 18 | ### Bug Fixes 19 | 20 | * **logic:** fixed refresh callback execution waiting ([fbfe38b](https://github.com/react-auth-kit/react-auth-kit/commit/fbfe38b28532589dfdcb090fe2149e3fbefb4ddd)) 21 | 22 | ## [1.6.2](https://github.com/react-auth-kit/react-auth-kit/compare/v1.6.1...v1.6.2) (2021-11-13) 23 | 24 | 25 | ### Bug Fixes 26 | 27 | * **package.json:** updated linting package ([fad4305](https://github.com/react-auth-kit/react-auth-kit/commit/fad4305a275b3a1b7da450442b0e9d82ca31164d)) 28 | 29 | ## [1.6.1](https://github.com/react-auth-kit/react-auth-kit/compare/v1.6.0...v1.6.1) (2021-11-09) 30 | 31 | 32 | ### Bug Fixes 33 | 34 | * **lockfile:** updated the lockfile version to 2 ([e2f51ff](https://github.com/react-auth-kit/react-auth-kit/commit/e2f51fff847fb0cdc7bb5bf26b1b2a7b184a6729)) 35 | 36 | # [1.6.0](https://github.com/react-auth-kit/react-auth-kit/compare/v1.5.5...v1.6.0) (2021-10-23) 37 | 38 | 39 | ### Bug Fixes 40 | 41 | * old action is deleted ([feada70](https://github.com/react-auth-kit/react-auth-kit/commit/feada705dcde4cb817980ecac3da1f94a1bd21ad)) 42 | 43 | 44 | ### Features 45 | 46 | * added semantic release plugins ([405a240](https://github.com/react-auth-kit/react-auth-kit/commit/405a2402458d8bb8dc2989e21a56f9385f733be3)) 47 | * **package.json:** added @semantic-release/git @semantic-release/changelog ([45302ea](https://github.com/react-auth-kit/react-auth-kit/commit/45302ead09051b55b4dcdd6a5ea67a350c57900d)) 48 | * semantic-release ci cd is created ([581dcd7](https://github.com/react-auth-kit/react-auth-kit/commit/581dcd71ffb3dcee405dfadec2000d3b322ee0f2)) 49 | -------------------------------------------------------------------------------- /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 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at in2arkadipb13@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to _React Auth Kit_ 2 | 3 | :+1::tada: First off, thanks for taking the time to contribute! :tada::+1: 4 | 5 | We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: 6 | 7 | - [Discussing the current state of the code](https://github.com/react-auth-kit/react-auth-kit/issues) 8 | - [Reporting a bug](https://github.com/react-auth-kit/react-auth-kit/blob/master/.github/ISSUE_TEMPLATE/bug_report.md) 9 | - [Submitting a fix](https://github.com/react-auth-kit/react-auth-kit/blob/master/.github/pull_request_template.md) 10 | - [Proposing new features](https://github.com/react-auth-kit/react-auth-kit/blob/master/.github/ISSUE_TEMPLATE/feature_request.md) 11 | - [Contributing to documentation](https://authkit.arkadip.co/contributing/) 12 | 13 | ## Steps to follow :scroll: 14 | 15 | We use [Github Flow](https://guides.github.com/introduction/flow/index.html), all code changes happen through [Pull Requests](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/about-pull-requests). We actively welcome your pull requests. So here are the steps to get started. 16 | 17 | ### 1. Fork it :fork_and_knife: 18 | 19 | You can get your own fork/copy of [React Auth Kit](https://github.com/react-auth-kit/react-auth-kit) by using the Fork button. 20 | 21 | [![Fork Button](https://help.github.com/assets/images/help/repository/fork_button.jpg)](https://github.com/react-auth-kit/react-auth-kit) 22 | 23 | ### 2. Clone it :busts_in_silhouette: 24 | 25 | You need to clone (download) it to local machine using 26 | 27 | ```sh 28 | git clone https://github.com/Your_Username/react-auth-kit.git 29 | ``` 30 | 31 | > This makes a local copy of the repository in your machine. 32 | 33 | Once you have cloned the ` React-Auth-Kit ` repository from GitHub, move to that folder first using change directory command. 34 | 35 | ```sh 36 | # This will change directory to a folder Plant_Disease_Detection 37 | cd react-auth-kit 38 | ``` 39 | 40 | Move to this folder for all other commands. 41 | 42 | ### 3. Ready Steady Go... :turtle: :rabbit2: 43 | 44 | Once you have completed these steps, you are ready to start contributing by checking our `Help Wanted` Issues and creating [pull requests](https://github.com/react-auth-kit/react-auth-kit/pulls). 45 | 46 | ### 4. Create a new branch :bangbang: 47 | 48 | Whenever you are going to make a contribution. Please create a separate branch using command and keep your `master` branch clean (i.e. synced with remote branch). 49 | 50 | ```sh 51 | # It will create a new branch with the name Branch_Name and will switch to that branch. 52 | git checkout -b Branch_Name 53 | ``` 54 | 55 | ### 5. Install all dependencies :turtle: 56 | 57 | Install project dependencies 58 | 59 | ```sh 60 | # It will install all necessary dependencies 61 | npm install 62 | ``` 63 | 64 | :tada: **_Now comes coding time_** :tada: 65 | 66 | To add the changes to the branch. Use, 67 | 68 | ```sh 69 | # To add all files to branch Branch_Name 70 | git add . 71 | ``` 72 | 73 | Type in a message relevant for the code reviewer using 74 | 75 | ### Conventional Commit 76 | 77 | ``` 78 | [optional scope]: 79 | 80 | [optional body] 81 | 82 | [optional footer(s)] 83 | ``` 84 | 85 | Types: 86 | 87 | - **fix**: a commit of the type fix patches a bug in your codebase (this correlates with PATCH in Semantic Versioning). 88 | 89 | - **feat**: a commit of the type feat introduces a new feature to the codebase (this correlates with MINOR in Semantic Versioning). 90 | 91 | - **refactor**: a commit of the type refactor is a change that neither fixes a bug nor adds a feature. 92 | 93 | - **build**: a commit of the type build are changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm). 94 | 95 | - **chore**: a commit of the type chore are other changes that don't modify src or test files. 96 | 97 | - **ci**: a commit of the type ci are changes to our CI configuration files and scripts. 98 | 99 | - **style**: a commit of the type style are changes that do not affect the meaning of the code (white-space, formatting, missing semi-colon, etc). 100 | 101 | - **docs**: a commit of the type docs are documentation changes only. 102 | 103 | - **perf**: a commit of the type perf is a code change that improves performance. 104 | 105 | - **test**: a commit of the type test introduces missing tests or correcting existing tests 106 | 107 | - **BREAKING CHANGE**: a commit that has a footer BREAKING CHANGE:, or appends a ! after the type/scope, introduces a breaking API change (correlating with MAJOR in Semantic Versioning). A BREAKING CHANGE can be part of commits of any type. 108 | 109 | Ex. 110 | 111 | ```sh 112 | # This message gets associated with all files you have changed 113 | git commit -m 'docs: edited the CONTRIBUTING.md' 114 | ``` 115 | 116 | Now, Push your awesome work to your remote repository using 117 | 118 | ```sh 119 | # To push your work to your remote repository 120 | git push -u origin Branch_Name 121 | ``` 122 | 123 | Finally, go to your forked repository in your browser and click on `Compare & pull request`. 124 | Use our [pull request template format](https://github.com/react-auth-kit/react-auth-kit/blob/master/.github/pull_request_template.md). 125 | Then add a title and description to your pull request that explains your precious effort. 126 | 127 | Now, sit back and relax till we review your PR, you've made your contribution to our project. 128 | 129 | ## License 130 | 131 | By contributing, you agree that your contributions will be licensed under [Apache License 2.0](LICENSE). 132 | 133 | :tada: :confetti_ball: :smiley: _**Happy Contributing**_ :smiley: :confetti_ball: :tada: 134 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | React Auth Kit Banner 3 |

4 | 5 |

6 | 🔑 Authentication Library for React Js for Token Based Auth with Json Web Token(JWT) 🔑 7 |

8 | 9 |

10 | 11 | 12 | 13 | 14 | 15 | 16 | NPM Deploy 17 | 18 | 19 | Test Suites 20 | 21 | 22 | Test Suites 23 | 24 | 25 | Test Suites 26 | 27 |

28 | 29 | --- 30 | 31 | # Introduction 32 | 33 | **React Auth Kit** is a lightweight JavaScript library for React JS, which makes the implementation of `Token based` 34 | authentication very easy 35 | 36 | It is production-ready, and gives you the following: 37 | 38 | * 📦 Very lightweight 39 | * ⚛️ Build for React Js 40 | * 🚀 Fast and easy to Implement 41 | * 🛡️ Supports Json Web Token (JWT) 42 | * 🔒 Secure Client Side Authentication 43 | * ⌨️ Highly typed and written in TypeScript 44 | 45 | ## Documentation 46 | 47 | Visit [Auth Kit](https://authkit.arkadip.me) for the offical documentation. 48 | 49 | 50 | 51 | 52 | ## HALL OF FAME ✨ 53 | We love our contributors! If you'd like to contribute anything from a bug-fix to a feature update, you can read our [CONTRIBUTING GUIDE](https://github.com/react-auth-kit/react-auth-kit/blob/master/CONTRIBUTING.md) 54 | 55 | 56 | 57 | [![Contributors](https://contrib.rocks/image?repo=react-auth-kit/react-auth-kit)](https://github.com/react-auth-kit/react-auth-kit/graphs/contributors) 58 | 59 | 60 |

— 🔑 —

61 |

React Auth Kit is Apache 2.0 License code

62 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | 4 | ## Reporting a Vulnerability 5 | 6 | Use this section to tell people how to report a vulnerability. 7 | 8 | Tell them where to go, how often they can expect to get an update on a 9 | reported vulnerability, what to expect if the vulnerability is accepted or 10 | declined, etc. 11 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | rules: { 4 | 'body-max-line-length': [1, 'always', 150] 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | authkit.arkadip.me 2 | -------------------------------------------------------------------------------- /docs/authdata.md: -------------------------------------------------------------------------------- 1 | # Auth User Data 2 | 3 | Get the Authorized user's state from any Component simply by using `HOC` or `Hooks` 4 | 5 | - To get the Authorized user's state from _Higher Order Components_, use `withAuthUser` 6 | - To get the Authorized user's state using _React Hooks_, use `useAuthUser` 7 | 8 | ## Using Hooks 9 | 10 | ```js 11 | import {useAuthUser} from 'react-auth-kit' 12 | ``` 13 | 14 | ### Demo 15 | ```jsx 16 | import React from 'react' 17 | import {useAuthUser} from 'react-auth-kit' 18 | 19 | const SomeComponent = () => { 20 | const auth = useAuthUser() 21 | 22 | return( 23 |
24 | Hello {auth().user} 25 |
26 | ) 27 | } 28 | ``` 29 | 30 | ## Using Higher Order Component 31 | 32 | ```jsx 33 | import {withAuthUser} from 'react-auth-kit' 34 | ``` 35 | 36 | ### Demo 37 | ```jsx 38 | import React from 'react' 39 | import {withAuthUser} from 'react-auth-kit' 40 | 41 | class SomeComponent extends React.Component { 42 | render(){ 43 | return ( 44 |
45 | Hello {this.props.authState.user} 46 |
47 | ) 48 | } 49 | } 50 | 51 | export default withAuthUser(SomeComponent) 52 | ``` 53 | 54 |
55 | 56 |

— 🔑 —

57 |

React Auth Kit is Apache 2.0 License code

58 | -------------------------------------------------------------------------------- /docs/authheader.md: -------------------------------------------------------------------------------- 1 | # Auth Header 2 | 3 | Get the Auth Header for future request from any Component simply by using `HOC` or `Hooks` 4 | 5 | - To get the Auth Header from _Higher Order Components_, use `withAuthHeader` 6 | - To get the Auth Header using _React Hooks_, use `useAuthHeader` 7 | 8 | ## Using Hooks 9 | 10 | ```js 11 | import {useAuthHeader} from 'react-auth-kit' 12 | ``` 13 | 14 | ### Demo 15 | ```jsx 16 | import React from 'react' 17 | import {useAuthHeader} from 'react-auth-kit' 18 | 19 | const SomeComponent = () => { 20 | const authHeader = useAuthHeader() 21 | 22 | return( 23 |
24 | {authHeader} 25 |
26 | ) 27 | } 28 | ``` 29 | 30 | ## Using Higher Order Component 31 | 32 | ```jsx 33 | import {withAuthHeader} from 'react-auth-kit' 34 | ``` 35 | 36 | ### Demo 37 | ```jsx 38 | import React from 'react' 39 | import {withAuthHeader} from 'react-auth-kit' 40 | 41 | class SomeComponent extends React.Component { 42 | render(){ 43 | return ( 44 |
45 | {this.props.authHeader} 46 |
47 | ) 48 | } 49 | } 50 | 51 | export default withAuthHeader(SomeComponent) 52 | ``` 53 | 54 | 55 |
56 | 57 | 58 |

— 🔑 —

59 |

React Auth Kit is Apache 2.0 License code

60 | -------------------------------------------------------------------------------- /docs/checkauth.md: -------------------------------------------------------------------------------- 1 | # Check Authentication 2 | 3 | > Check if any user is authenticated or not 4 | 5 | ## Introduction 6 | 7 | There are many times, when you have to understand if any user is authenticated 8 | (especially in `login` pages, where you have to redirect your user to its dashboard or allow to login) 9 | 10 | For this reason, `React Auth Kit` comes with `isAuth` functions 11 | 12 | --- 13 | 14 | `IsAuth` functionality available in both `hook` and `Higher Order Component` 15 | 16 | - For Functional Components, you can use `useIsAuthenticated` function inside any components 17 | - For class based components, you can wrap the component inside `withIsAuthenticated` function 18 | 19 |
20 | 21 | --- 22 | 23 | ## Usage 24 | ### Functional Component 25 | 26 | Check the `authentication status` in React Functional Components(FC) by adding the `useIsAuthenticated` hook inside it. 27 | 28 | #### Import 29 | 30 | ```jsx 31 | import {useIsAuthenticated} from 'react-auth-kit'; 32 | ``` 33 | 34 | #### Demo 35 | 36 | ```jsx 37 | import {useIsAuthenticated} from 'react-auth-kit'; 38 | 39 | const AnyComponent = () => { 40 | const isAuthenticated = useIsAuthenticated() 41 | 42 | if(isAuthenticated()){ 43 | // Redirect to Dashboard 44 | } 45 | else { 46 | // Redirect to Login 47 | } 48 | } 49 | ``` 50 | 51 | #### API 52 | 53 | `useIsAuthenticated()` 54 | 55 | _**Returns**_ `() => boolean` 56 | 57 | --- 58 | 59 | ### Class Based Component 60 | 61 | #### Import 62 | 63 | ```javascript 64 | import {withIsAuthenticated} from 'react-auth-kit'; 65 | ``` 66 | 67 | #### Demo 68 | ```javascript 69 | import React from "react"; 70 | import {withIsAuthenticated} from 'react-auth-kit'; 71 | 72 | class SomeComponent extends React.Component { 73 | 74 | render(){ 75 | if(this.props.isAuthenticated()){ 76 | // Redirect to Dashboard 77 | } 78 | else { 79 | // Redirect to Login 80 | } 81 | } 82 | } 83 | 84 | export default withIsAuthenticated(SomeComponent) 85 | ``` 86 | 87 | #### API 88 | `#!ts withIsAuthenticated

(Component: React.ComponentType

): React.FC

` 89 | 90 | _**Parameters**_ 91 | 92 | - Component: `#!ts React.ComponentType

` 93 | 94 | _**Returns**_ `#!ts React.FC

` (Functional Component with `isAuthenticated()` prop) 95 | 96 | --- 97 | 98 |

— 🔑 —

99 |

React Auth Kit is Apache 2.0 License code

100 | -------------------------------------------------------------------------------- /docs/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Notice something that needs fixing? Or something that could be improved? Awesome! Here are some guidelines below that'll help you to do just that. 4 | 5 | In general, there are two main types of contribution, 6 | 7 | - **General improvements:** 8 | - Typo corrections. 9 | - Fixing broken refs and links. 10 | - Correcting inaccurate or out of date info. 11 | - Offering better explanations through clear writings and examples. 12 | 13 | - **New Pages or features** 14 | - Adding a page of documentation that we haven't covered yet. 15 | - Documenting a new feature that had been added to this project since its last release. 16 | 17 | 18 | ## Before contributing 19 | 20 | 1. Read the [CONTRIBUTING.md](https://github.com/react-auth-kit/react-auth-kit/blob/master/CONTRIBUTING.md) first if you haven't yet. 21 | 22 | 2. Familiarize yourself with [Mkdocs](https://www.mkdocs.org/) and [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) with which we created the documentation. 23 | 24 | 3. Read through some of our existing documents and get a feel about the overall structure and style. 25 | 26 | 4. Read our ['Best practices'](#best-practices) section and please ensure your PR meets those. 27 | 28 | 29 | ## Steps for local setup 30 | 31 | 1. We use [Github Flow](https://guides.github.com/introduction/flow/index.html), all code changes happen through [Pull Requests](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/about-pull-requests). Follow the steps specified at [CONTRIBUTING.md](https://github.com/react-auth-kit/react-auth-kit/blob/master/CONTRIBUTING.md) to set up a local repo of the project. 32 | 33 | 2. Install Material for MkDocs. 34 | 35 | === "Pip" 36 | 37 | ``` sh 38 | pip install mkdocs-material 39 | ``` 40 | 41 | This will automatically install compatible versions of all dependencies: [MkDocs](https://www.mkdocs.org/), [Markdown](https://python-markdown.github.io/), [Pygments](https://pygments.org/) and [Python Markdown Extensions](https://facelessuser.github.io/pymdown-extensions/). 42 | 43 | === "Docker" 44 | 45 | The official [Docker image](https://hub.docker.com/r/squidfunk/mkdocs-material/) is a great way to get up and running in a few minutes, as it comes with all dependencies pre-installed. Pull the image for the `latest` version with: 46 | 47 | ``` sh 48 | docker pull squidfunk/mkdocs-materiall 49 | ``` 50 | 51 | The mkdocs executable is provided as an entry point and serve is the default command. 52 | 53 | === "Git" 54 | 55 | Material for MkDocs can be directly used from [GitHub](https://www.github.com/) by cloning the repository into a subfolder of your project root which might be useful if you want to use the very latest version: 56 | 57 | ``` sh 58 | git clone https://github.com/squidfunk/mkdocs-material.git 59 | ``` 60 | 61 | The theme will reside in the folder mkdocs-material/material. When cloning from git, you must install all required dependencies yourself: 62 | 63 | ``` sh 64 | pip install -r mkdocs-material/requirements.txt 65 | ``` 66 | 67 | 3. All the contents are in the `docs` folder and the mkdocs config in `mkdocs.yml` relative to the project root directory. 68 | 69 | 4. MkDocs includes a live preview server, so you can preview your changes as you modify the documentation. The server will automatically rebuild the site upon saving. Start it with: 70 | 71 | ``` sh 72 | mkdocs serve 73 | ``` 74 | 75 | 5. You are now all set up and ready to contribute! 76 | 77 | 78 | ## Best practices 79 | 80 | 1. All pages must include a proper title and an introduction. 81 | 82 | 2. If the document contains a technical term, it must be highlighted using \*term\* markdown syntax. 83 | 84 | 3. If the document contains an acronym or initialism, it should be first introduced highlighted in its expanded form followed by the commonly-accepted abbreviation in brackets (like Free and open-source software (FOSS)). 85 | 86 | 4. Use paragraphs to introduce a single concept and move on to a new paragraph before introducing another or expanding upon the first concept. Keep the size of those paragraphs to no more than four to five lines. 87 | 88 | 5. If you find you're putting commas in a sentence consider splitting it into two or more sentences for improved clarity. 89 | 90 | 6. Split the document up into as many sub-sections as makes sense. This is especially helpful for the readers who want to skip ahead for reference, as we can also use subheads as navigational anchors. 91 | 92 | 93 |
94 | 95 |

— 🔑 —

96 |

React Auth Kit is Apache 2.0 License code

97 | -------------------------------------------------------------------------------- /docs/docs_overrides/main.html: -------------------------------------------------------------------------------- 1 | 16 | {% extends "base.html" %} 17 | 18 | {% block outdated %} 19 | You're not viewing the latest version. 20 | 21 | 22 | Click here to go to latest. 23 | 24 | {% endblock %} 25 | 26 | {% block extrahead %} 27 | {% set title = config.site_name %} 28 | {% if page and page.meta and page.meta.title %} 29 | {% set title = title ~ " - " ~ page.meta.title %} 30 | {% elif page and page.title and not page.is_homepage %} 31 | {% set title = title ~ " - " ~ page.title | striptags %} 32 | {% endif %} 33 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | {% endblock %} 49 | -------------------------------------------------------------------------------- /docs/img/banner.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3solution/react-auth-kit-master/c04e7ab2f91ad7da165402d2163b4e7d0c66f265/docs/img/favicon.png -------------------------------------------------------------------------------- /docs/img/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3solution/react-auth-kit-master/c04e7ab2f91ad7da165402d2163b4e7d0c66f265/docs/img/image.png -------------------------------------------------------------------------------- /docs/img/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 |

2 | React Auth Kit Banner 3 |

4 | 5 |

6 | 🔑 Authentication Library for React Js for Token Based Auth with Json Web Token(JWT) 🔑 7 |

8 | 9 |

10 | 11 | NPM Deploy 12 | 13 | 14 | Test Suites 15 | 16 | 17 | Test Suites 18 | 19 | 20 | Test Suites 21 | 22 | 23 | Codacy Badge 24 | 25 |

26 | 27 | --- 28 | 29 | **React Auth Kit** is a lightweight `auth management` library for React JS. 30 | 31 | 32 | It is production-ready, and gives you the following: 33 | 34 | * 📦 Very lightweight 35 | * ⚛️Build for React Js 36 | * 🚀 Fast and easy to Implement 37 | * 🛡️ Supports Json Web Token (JWT) 38 | * 🔒 Secure Client Side Authentication 39 | * ⌨️Highly typed and written in TypeScript 40 | 41 |
42 | 43 |

— 🔑 —

44 |

React Auth Kit is Apache 2.0 License code

45 | -------------------------------------------------------------------------------- /docs/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | React-Auth-Kit is available as a [npm package](https://www.npmjs.com/package/react-auth-kit) 4 | 5 |
6 | 7 | ## npm :fontawesome-brands-npm: 8 | To install and save in your `package.json` dependencies, run: 9 | ```bash 10 | //with npm 11 | npm install --save react-auth-kit 12 | 13 | //with yarn 14 | yarn add react-auth-kit 15 | ``` 16 | Please note that [react](https://www.npmjs.com/package/react) >= 16, 17 | [js-cookie](https://www.npmjs.com/package/js-cookie) = 2.2.1 and 18 | [react-router-dom](https://www.npmjs.com/package/react-router-dom) = 5.2.0 are peer dependencies. 19 | 20 | ##CDN 21 | 22 | You can start using React-Auth-Kit with minimal infrastructure, which is great for prototyping. 23 | 24 | Two Universal Module Definition (**UMD**) files are provided: 25 | 26 | - **unpkg**: [https://unpkg.com/react-auth-kit/dist/index.umd.js](https://unpkg.com/react-auth-kit/dist/index.umd.js) 27 | - **jsdelivr**: [https://cdn.jsdelivr.net/npm/react-auth-kit/dist/index.umd.js](https://cdn.jsdelivr.net/npm/react-auth-kit/dist/index.umd.js) 28 | 29 | [![](https://data.jsdelivr.com/v1/package/npm/react-auth-kit/badge)](https://www.jsdelivr.com/package/npm/react-auth-kit) 30 | 31 | You can follow [this CDN example](https://github.com/react-auth-kit/react-auth-kit/tree/master/examples/cdn) 32 | to quickly get started. 33 | 34 | !!! warning "" 35 | 36 | Using this approach in `production` is `discouraged` though - the client has to download the entire library, 37 | regardless of which components are actually used, affecting performance and bandwidth utilization. 38 | 39 | !!! danger "" 40 | 41 | The UMD links are using the `latest` tag to point to the latest version of the library. This pointer is `unstable`, 42 | it shifts as we release new versions. You should consider pointing to a specific version, 43 | such as [v1.4.6](https://unpkg.com/react-auth-kit@1.4.6/dist/index.umd.js). 44 | 45 |

— 🔑 —

46 |

React Auth Kit is 47 | Apache 2.0 License code

48 | -------------------------------------------------------------------------------- /docs/integration.md: -------------------------------------------------------------------------------- 1 | # Integration 2 | React Auth Kit uses a Context Provider to maintain it's internal state in the application. 3 | So to use auth kit, you must have to add the `AuthProvider` on the very top level of your application. 4 | Without the provider the application will fail to work and will throw errors. 5 | 6 |
9 | 10 | --- 11 | ## AuthProvider 12 | 13 | AuthProvider is the top level [context](https://reactjs.org/docs/context.html) provider for React Auth Kit. 14 | By passing various props in the AuthProvider, you can configure the behaviour of React Auth Kit. 15 | 16 | ### Import 17 | ```javascript 18 | import { AuthProvider } from 'react-auth-kit' 19 | ``` 20 | 21 | ### Example 22 | 23 | Integrate `AuthProvider` before Routes. The best place is `app.js`. 24 | 25 | 26 | ```javascript 27 | //app.js 28 | 29 | import React from 'react'; 30 | import { AuthProvider } from 'react-auth-kit' 31 | import RouteComponent from './routes'; 32 | 33 | const App = () => ( 34 | 38 | 39 | 40 | ); 41 | 42 | export default App; 43 | ``` 44 | 45 | !!! warning 46 | 47 | `AuthProvider` should wrap the **BrowserRouter or HashRouter**, 48 | otherwise `PrivateRoute` will not work and throw an error. 49 | 50 | !!! warning 51 | 52 | If you are using the Refresh Token feature, then you must have to add the `refresh` prop with proper value, 53 | otherwise refresh token will throw a not implemented error. If you are not using the Refresh Token feature, 54 | then don't add it 55 | 56 | ### Props 57 | 58 | | Name | Type | Default | Description | 59 | |--------------|----------------------------|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 60 | | children | node | | The content of the component | 61 | | authType | 'localstorage' \| 'cookie' | 'cookie' | The type of the auth storage. In localstorage, the tokens store in localStorage. In cookie, the tokens store in cookies. | 62 | | authName | string | '_auth' | The prefix for the name of the storage, which stores the auth token. **Applicable for both cookies and localStorage**. | 63 | | refresh | createRefreshParamInterface (`optional`) || If you are using refresh token, then add this prop. The value of the props must be the return value of `createRefresh` ([See Here](/refreshtoken/#integration-in-auth-provider). If you are not using refresh token, then leave the prop)| 64 | | cookieDomain | string (`optional`) | __ | The Domain name for cookie. ⚠ If **authType** is `cookie`, then you must put a value. [More Info about Cookie Domain](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) | 65 | | cookieSecure | boolean (`optional`) | __ | The cookie secure flag. ⚠ If **authType** is `cookie`, then you must put a value. [More Info about Cookie Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) | 66 | 67 |

— 🔑 —

68 |

React Auth Kit is Apache 2.0 License code

69 | -------------------------------------------------------------------------------- /docs/privateroute.md: -------------------------------------------------------------------------------- 1 | # Private Route 2 | 3 | > Implement Private Route on your React App 4 | 5 | React Auth Kit has a `PrivateRoute` functionality Based on [React Router](https://reactrouter.com/) 6 | 7 | ## Import 8 | 9 | ```js 10 | import {PrivateRoute} from 'react-auth-kit' 11 | ``` 12 | 13 | ## Implementation 14 | 15 | Add `PrivateRoute` in your Routes Files inside `BrowserRouter` or `HashRouter` 16 | 17 | ### Demo 18 | 19 | ```jsx 20 | 21 | 22 | 23 | ``` 24 | 25 |
26 | Full Code 27 |
28 | 29 | 30 | ```jsx 31 | import React from "react" 32 | import {BrowserRouter, Route} from "react-router-dom" 33 | import { PrivateRoute } from 'react-auth-kit' 34 | 35 | const Routes = () => { 36 | return ( 37 | 38 | 39 | 40 | 41 | ) 42 | } 43 | ``` 44 |
45 | 46 | ## Props 47 | 48 | As PrivateRoute is a derived version of [Route](https://reactrouter.com/web/api/Route) from `React-Router`, 49 | that's why the props are same as Route props. Check [this link](https://reactrouter.com/web/api/Route). 50 | 51 | ***Added Prop***: `loginPath` (_Require_): The fallback path, if the user is unauthorized. 52 | 53 |
54 | 55 |

— 🔑 —

56 |

React Auth Kit is Apache 2.0 License code

57 | -------------------------------------------------------------------------------- /docs/refreshtoken.md: -------------------------------------------------------------------------------- 1 | # Refresh Tokens 2 | 3 | Often JWT comes with a new challenge. 4 | You have to `refresh` the JWT token periodically using a token, named Refresh token. 5 | 6 | > A refresh token is a special kind of token used to obtain a renewed access token. 7 | You can request new access tokens until the refresh token is on the DenyList. 8 | Applications must store refresh tokens securely because they essentially allow a user to remain authenticated forever. 9 | 10 | React Auth Kit implements an easy approach to integrate the refresh token. 11 | 12 | You can either use the refresh token in your application or you can leave it. 13 | 14 | --- 15 | 16 | ## API Builder 17 | To build the refresh token API, you have to use `createRefresh` function. 18 | It is an identity function. It is mainly used for typechecking and mobility. 19 | 20 | ### createRefresh 21 | 22 | `#!js createRefresh(options) => refreshApi` 23 | 24 | Generate a refreshApi based on the options received 25 | 26 | #### Arguments 27 | 28 | `options` (object): Takes a refresh object. It has 2 parameters 29 | 30 | 1. `refreshApiCallback` (function): This is an API function. Inside this function, you have to add a network request API. See the [details](#refreshapicallback) 31 | 2. `interval` (number): The time interval in minutes, by which the `refreshApiCallback` is called and the state is updated 32 | 33 | #### Returns 34 | A complete object of refresh token API. Add this object in the `AuthProvider` as a prop to implement the feature. 35 | 36 | ```js 37 | import {createRefresh} from 'react-auth-kit' 38 | 39 | const refreshApi = createRefresh({ 40 | interval: 10, // Refreshs the token in every 10 minutes 41 | refreshApiCallback: param => { // API container function 42 | return { 43 | isSuccess: true, 44 | } 45 | } 46 | }) 47 | 48 | export default refreshApi 49 | ``` 50 | 51 | --- 52 | ### refreshApiCallback 53 | The container for refresh API 54 | 55 | #### Arguments 56 | The function has only one argument, which is the `object` of the latest state. 57 | 58 | The object contains: 59 | 60 | 1. `authToken` (string): The Auth token 61 | 2. `authTokenExpireAt` (Date) : Expiring time of the Auth token 62 | 3. `refreshToken` (string): The Refresh token 63 | 4. `refreshTokenExpiresAt` (Date): Expiring time of the refresh token 64 | 5. `authUserState` (object): The current User state 65 | 66 | #### Returns 67 | In side the function you have to return an `object` of new auth state fetched by the API. 68 | 69 | The return object must contain: 70 | 71 | 1. `isSuccess` (boolean): If the network request is successful, then make it `true`, otherwise make it false. 72 | If the value of this variable is false then the state will not changed, and it'll wait for the next time 73 | 2. `newAuthToken` (string): The value of this variable will be the new auth token. So pass the new auth token here. 74 | 3. `newAuthTokenExpireIn` (number)(optional): New time limit in minutes, after which the auth token will expire. 75 | If you leave it, the old time limit will not be changed. So if you want to add more 10 minutes, then pass 10 here. 76 | 4. `newRefreshToken` (string)(optional): Pass the new refresh token here, if you want to refresh the refresh token itself. 77 | 5. `newRefreshTokenExpiresIn` (number)(optional): New time limit in minutes, after which the refresh token will expire. Works same as `newAuthTokenExpireIn` 78 | 6. `newAuthUserState` (object)(optional): Pass the new user state. If your API updates the user state, then use this, else leave it. 79 | 80 | #### refreshApiCallback Example 81 | ```js 82 | {refreshApiCallback: ( 83 | { // arguments 84 | authToken, 85 | authTokenExpireAt, 86 | refreshToken, 87 | refreshTokenExpiresAt, 88 | authUserState 89 | }) => { 90 | axios.post('/api/refresh', 91 | { 92 | refreshToken: refreshToken, 93 | oldAuthToken: authToken 94 | } 95 | ).then(({data})=>{ 96 | return { 97 | // As the request is successful, we are passing new tokens. 98 | isSuccess: true, // For successful network request isSuccess is true 99 | newAuthToken: data.newAuthToken, 100 | newAuthTokenExpireIn: data.newAuthTokenExpireIn 101 | // You can also add new refresh token ad new user state 102 | } 103 | }).catch((e)=>{ 104 | console.error(e) 105 | return{ 106 | // As the request is unsuccessful, we are just passing the isSuccess. 107 | isSuccess:false // For unsuccessful network request isSuccess is false 108 | } 109 | }) 110 | } 111 | } 112 | ``` 113 | 114 | --- 115 | 116 | ### API Builder Example 117 | This is the overall example of how to use `createRefresh`. The example uses axios to make network request. 118 | ```js 119 | import axios from 'axios' 120 | import {useAuthHeader, createRefresh} from 'react-auth-kit' 121 | 122 | const refreshApi = createRefresh({ 123 | interval: 10, // Refreshs the token in every 10 minutes 124 | refreshApiCallback: ( 125 | { 126 | authToken, 127 | authTokenExpireAt, 128 | refreshToken, 129 | refreshTokenExpiresAt, 130 | authUserState 131 | }) => { 132 | axios.post('/api/refresh', 133 | { 134 | refreshToken: refreshToken, 135 | oldAuthToken: authToken 136 | } 137 | ).then(({data})=>{ 138 | return { 139 | isSuccess: true, // For successful network request isSuccess is true 140 | newAuthToken: data.newAuthToken, 141 | newAuthTokenExpireIn: data.newAuthTokenExpireIn 142 | // You can also add new refresh token ad new user state 143 | } 144 | }).catch((e)=>{ 145 | console.error(e) 146 | return{ 147 | isSuccess:false // For unsuccessful network request isSuccess is false 148 | } 149 | }) 150 | } 151 | }) 152 | 153 | export default refreshApi 154 | ``` 155 | 156 | ## Integration in Auth Provider. 157 | To add the refresh token feature, simply add the return value of `createRefresh` function in the `AuthProvider` as a prop. 158 | 159 | ```js 160 | import {AuthProvider} from 'react-auth-kit' 161 | import refreshApi from "./refreshApi"; 162 | 163 | function App() { 164 | return ( 165 | 170 | 171 | 172 | ); 173 | } 174 | ``` 175 | 176 | !!! warning "Only use the return from createRefresh as the prop value" 177 | 178 | Using values other than the return of `createRefresh` will cause the application to break. 179 | So only use the return of `createRefresh` as the prop value. 180 | 181 |

— 🔑 —

182 |

React Auth Kit is Apache 2.0 License code

183 | -------------------------------------------------------------------------------- /docs/robots.txt: -------------------------------------------------------------------------------- 1 | Sitemap: https://authkit.arkadip.me/sitemap.xml.gz 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /docs/signout.md: -------------------------------------------------------------------------------- 1 | # Sign Out 2 | 3 | > Implement Sign Out on your React App 4 | 5 | React Auth Kit has easy to implement Sign In procedures. 6 | 7 | It supports both [`Hooks`](https://reactjs.org/docs/hooks-intro.html) and 8 | [`Higher Order Component`](https://reactjs.org/docs/higher-order-components.html) 9 | for both Functional Components and Class-based Components 10 | 11 |
12 | 13 | ## Sign Out using Hooks 14 | 15 | Sign In using Hooks need `useSignOut` hook 16 | 17 | Add the `useSignOut` hook in the component then call the `signOut` inside the component 18 | 19 | ```js 20 | import { useSignOut } from 'react-auth-kit' 21 | ``` 22 | ### Demo 23 | ```jsx 24 | import React from "react" 25 | import { useSignOut } from 'react-auth-kit' 26 | 27 | const SignInComponent = () => { 28 | const signOut = useSignOut() 29 | 30 | return ( 31 | 32 | ) 33 | } 34 | ``` 35 | 36 | 37 | ## Sign Out using Higher Order Component 38 | 39 | Sign In using Higher Order Component using `withSignOut`. 40 | 41 | Add the `withSignOut` HOC and call the `this.props.signOut` function inside the component 42 | 43 | ```js 44 | import { withSignOut } from 'react-auth-kit' 45 | ``` 46 | 47 | ### Demo 48 | ```jsx 49 | import React from "react" 50 | import { withSignOut } from 'react-auth-kit' 51 | 52 | class signOutComponent extends React.Component { 53 | 54 | render(){ 55 | return ( 56 | 57 | ) 58 | } 59 | } 60 | 61 | export default withSignIn(signInComponent) 62 | ``` 63 | 64 |

— 🔑 —

65 |

React Auth Kit is Apache 2.0 License code

66 | -------------------------------------------------------------------------------- /examples/cdn/index.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | My page 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /examples/cdn/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cdn", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC" 12 | } 13 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `yarn start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `yarn test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `yarn build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `yarn eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `yarn build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-react-app-refresh-token", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "react": "^17.0.2", 10 | "react-auth-kit": "github:react-auth-kit/react-auth-kit#refresh-token", 11 | "react-dom": "^17.0.2", 12 | "react-scripts": "4.0.3", 13 | "web-vitals": "^1.0.1" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": [ 23 | "react-app", 24 | "react-app/jest" 25 | ] 26 | }, 27 | "browserslist": { 28 | "production": [ 29 | ">0.2%", 30 | "not dead", 31 | "not op_mini all" 32 | ], 33 | "development": [ 34 | "last 1 chrome version", 35 | "last 1 firefox version", 36 | "last 1 safari version" 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3solution/react-auth-kit-master/c04e7ab2f91ad7da165402d2163b4e7d0c66f265/examples/create-react-app-refresh-token/public/favicon.ico -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/public/index.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 28 | 29 | 33 | 34 | 43 | React App 44 | 45 | 46 | 47 |
48 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3solution/react-auth-kit-master/c04e7ab2f91ad7da165402d2163b4e7d0c66f265/examples/create-react-app-refresh-token/public/logo192.png -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3solution/react-auth-kit-master/c04e7ab2f91ad7da165402d2163b4e7d0c66f265/examples/create-react-app-refresh-token/public/logo512.png -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/src/App.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import React from 'react'; 18 | import {AuthProvider} from 'react-auth-kit' 19 | import Routes from './Routes'; 20 | import refreshApi from "./refreshApi"; 21 | 22 | function App() { 23 | return ( 24 | 28 | 29 | 30 | ); 31 | } 32 | 33 | export default App; 34 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/src/Routes.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import React from 'react' 18 | import { PrivateRoute } from 'react-auth-kit' 19 | import { BrowserRouter, Route, Switch } from 'react-router-dom' 20 | import Home from './components/Home' 21 | import Login from './components/Login' 22 | import SecureComponent from './components/SecureComponent' 23 | 24 | const Routes = () => { 25 | return ( 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ) 34 | } 35 | 36 | export default Routes 37 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/src/components/Home.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import React from 'react' 18 | import { useHistory } from 'react-router-dom' 19 | 20 | const Home = () => { 21 | const history = useHistory() 22 | 23 | return ( 24 |
25 | 26 | 27 |
28 | ) 29 | } 30 | 31 | export default Home 32 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/src/components/Login.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import React from 'react' 18 | import {useIsAuthenticated, useSignIn} from 'react-auth-kit' 19 | import {Redirect, useHistory} from 'react-router-dom' 20 | 21 | const Login = () => { 22 | const isAuthenticated = useIsAuthenticated() 23 | const signIn = useSignIn() 24 | const history = useHistory() 25 | 26 | /** 27 | * Login Handle, the callback function onClick from the "Login" button 28 | * 29 | * This function demostrate a dummy authentication, using useSignIn function 30 | */ 31 | const loginHandler = () => { 32 | // Assuming that, all network Request is successfull, and the user is authenticated 33 | 34 | if (signIn({ 35 | token: '35v3443bn368367n306306wbn407qn420b436b4', //Just a random token 36 | tokenType: 'Bearer', // Token type set as Bearer 37 | authState: {name: 'React User', uid: 123456}, // Dummy auth user state 38 | expiresIn: 10, // Token Expriration time, in minutes 39 | refreshToken: '23mv86n790g4vm2706c2m38v6n790', 40 | refreshTokenExpireIn: 60 41 | })) { 42 | // If Login Successfull, then Redirect the user to secure route 43 | history.push('/secure') 44 | } else { 45 | // Else, there must be some error. So, throw an error 46 | alert("Error Occoured. Try Again") 47 | } 48 | } 49 | console.log(isAuthenticated()) 50 | if (isAuthenticated()) { 51 | // If authenticated user, then redirect to secure dashboard 52 | 53 | return ( 54 | 55 | ) 56 | } else { 57 | // If not authenticated, use the login flow 58 | // For Demostration, I'm using just a button to login. 59 | // In reality, there should be a form, validation, nwetowrk request and other things 60 | return ( 61 | 62 | ) 63 | } 64 | } 65 | 66 | export default Login 67 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/src/components/SecureComponent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import React from 'react' 18 | import { useAuthUser, useSignOut } from 'react-auth-kit' 19 | 20 | const SecureComponent = () => { 21 | const signOut = useSignOut() 22 | const authUser = useAuthUser() 23 | 24 | return ( 25 |
26 |

{`Hello ${authUser().name}, your U-ID is: ${authUser().uid}`}

27 | 28 |
29 | ) 30 | } 31 | 32 | export default SecureComponent 33 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/src/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import React from 'react'; 18 | import ReactDOM from 'react-dom'; 19 | import App from './App'; 20 | import * as serviceWorker from './serviceWorker'; 21 | 22 | ReactDOM.render( 23 | 24 | 25 | , 26 | document.getElementById('root') 27 | ); 28 | 29 | // If you want your app to work offline and load faster, you can change 30 | // unregister() to register() below. Note this comes with some pitfalls. 31 | // Learn more about service workers: https://bit.ly/CRA-PWA 32 | serviceWorker.unregister(); 33 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/src/refreshApi.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import {createRefresh} from 'react-auth-kit' 18 | 19 | const refreshApi = createRefresh({ 20 | interval: 1, 21 | refreshApiCallback: param => { 22 | console.log(param) 23 | return { 24 | isSuccess: true, 25 | newAuthToken: 'fsdgedgd', 26 | newAuthTokenExpireIn: 10, 27 | newRefreshTokenExpiresIn: 60 28 | } 29 | } 30 | }) 31 | 32 | export default refreshApi 33 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // This optional code is used to register a service worker. 18 | // register() is not called by default. 19 | 20 | // This lets the app load faster on subsequent visits in production, and gives 21 | // it offline capabilities. However, it also means that developers (and users) 22 | // will only see deployed updates on subsequent visits to a page, after all the 23 | // existing tabs open on the page have been closed, since previously cached 24 | // resources are updated in the background. 25 | 26 | // To learn more about the benefits of this model and instructions on how to 27 | // opt-in, read https://bit.ly/CRA-PWA 28 | 29 | const isLocalhost = Boolean( 30 | window.location.hostname === 'localhost' || 31 | // [::1] is the IPv6 localhost address. 32 | window.location.hostname === '[::1]' || 33 | // 127.0.0.0/8 are considered localhost for IPv4. 34 | window.location.hostname.match( 35 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 36 | ) 37 | ); 38 | 39 | export function register(config) { 40 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 41 | // The URL constructor is available in all browsers that support SW. 42 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 43 | if (publicUrl.origin !== window.location.origin) { 44 | // Our service worker won't work if PUBLIC_URL is on a different origin 45 | // from what our page is served on. This might happen if a CDN is used to 46 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 47 | return; 48 | } 49 | 50 | window.addEventListener('load', () => { 51 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 52 | 53 | if (isLocalhost) { 54 | // This is running on localhost. Let's check if a service worker still exists or not. 55 | checkValidServiceWorker(swUrl, config); 56 | 57 | // Add some additional logging to localhost, pointing developers to the 58 | // service worker/PWA documentation. 59 | navigator.serviceWorker.ready.then(() => { 60 | console.log( 61 | 'This web app is being served cache-first by a service ' + 62 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 63 | ); 64 | }); 65 | } else { 66 | // Is not localhost. Just register service worker 67 | registerValidSW(swUrl, config); 68 | } 69 | }); 70 | } 71 | } 72 | 73 | function registerValidSW(swUrl, config) { 74 | navigator.serviceWorker 75 | .register(swUrl) 76 | .then(registration => { 77 | registration.onupdatefound = () => { 78 | const installingWorker = registration.installing; 79 | if (installingWorker == null) { 80 | return; 81 | } 82 | installingWorker.onstatechange = () => { 83 | if (installingWorker.state === 'installed') { 84 | if (navigator.serviceWorker.controller) { 85 | // At this point, the updated precached content has been fetched, 86 | // but the previous service worker will still serve the older 87 | // content until all client tabs are closed. 88 | console.log( 89 | 'New content is available and will be used when all ' + 90 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 91 | ); 92 | 93 | // Execute callback 94 | if (config && config.onUpdate) { 95 | config.onUpdate(registration); 96 | } 97 | } else { 98 | // At this point, everything has been precached. 99 | // It's the perfect time to display a 100 | // "Content is cached for offline use." message. 101 | console.log('Content is cached for offline use.'); 102 | 103 | // Execute callback 104 | if (config && config.onSuccess) { 105 | config.onSuccess(registration); 106 | } 107 | } 108 | } 109 | }; 110 | }; 111 | }) 112 | .catch(error => { 113 | console.error('Error during service worker registration:', error); 114 | }); 115 | } 116 | 117 | function checkValidServiceWorker(swUrl, config) { 118 | // Check if the service worker can be found. If it can't reload the page. 119 | fetch(swUrl, { 120 | headers: { 'Service-Worker': 'script' }, 121 | }) 122 | .then(response => { 123 | // Ensure service worker exists, and that we really are getting a JS file. 124 | const contentType = response.headers.get('content-type'); 125 | if ( 126 | response.status === 404 || 127 | (contentType != null && contentType.indexOf('javascript') === -1) 128 | ) { 129 | // No service worker found. Probably a different app. Reload the page. 130 | navigator.serviceWorker.ready.then(registration => { 131 | registration.unregister().then(() => { 132 | window.location.reload(); 133 | }); 134 | }); 135 | } else { 136 | // Service worker found. Proceed as normal. 137 | registerValidSW(swUrl, config); 138 | } 139 | }) 140 | .catch(() => { 141 | console.log( 142 | 'No internet connection found. App is running in offline mode.' 143 | ); 144 | }); 145 | } 146 | 147 | export function unregister() { 148 | if ('serviceWorker' in navigator) { 149 | navigator.serviceWorker.ready 150 | .then(registration => { 151 | registration.unregister(); 152 | }) 153 | .catch(error => { 154 | console.error(error.message); 155 | }); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /examples/create-react-app-refresh-token/src/setupTests.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 18 | // allows you to do things like: 19 | // expect(element).toHaveTextContent(/react/i) 20 | // learn more: https://github.com/testing-library/jest-dom 21 | import '@testing-library/jest-dom/extend-expect'; 22 | -------------------------------------------------------------------------------- /examples/create-react-app/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | -------------------------------------------------------------------------------- /examples/create-react-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /examples/create-react-app/README.md: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 2 | 3 | ## Available Scripts 4 | 5 | In the project directory, you can run: 6 | 7 | ### `yarn start` 8 | 9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 11 | 12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console. 14 | 15 | ### `yarn test` 16 | 17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 19 | 20 | ### `yarn build` 21 | 22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance. 24 | 25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed! 27 | 28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 29 | 30 | ### `yarn eject` 31 | 32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 33 | 34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 35 | 36 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 37 | 38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 39 | 40 | ## Learn More 41 | 42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 43 | 44 | To learn React, check out the [React documentation](https://reactjs.org/). 45 | 46 | ### Code Splitting 47 | 48 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting 49 | 50 | ### Analyzing the Bundle Size 51 | 52 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size 53 | 54 | ### Making a Progressive Web App 55 | 56 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app 57 | 58 | ### Advanced Configuration 59 | 60 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration 61 | 62 | ### Deployment 63 | 64 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment 65 | 66 | ### `yarn build` fails to minify 67 | 68 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify 69 | -------------------------------------------------------------------------------- /examples/create-react-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-with-cookie", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "react": "latest", 10 | "react-auth-kit": "^1.4.18-0", 11 | "react-dom": "latest", 12 | "react-router-dom": "latest", 13 | "react-scripts": "^2.1.8" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": "react-app" 23 | }, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/create-react-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3solution/react-auth-kit-master/c04e7ab2f91ad7da165402d2163b4e7d0c66f265/examples/create-react-app/public/favicon.ico -------------------------------------------------------------------------------- /examples/create-react-app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/create-react-app/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3solution/react-auth-kit-master/c04e7ab2f91ad7da165402d2163b4e7d0c66f265/examples/create-react-app/public/logo192.png -------------------------------------------------------------------------------- /examples/create-react-app/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3solution/react-auth-kit-master/c04e7ab2f91ad7da165402d2163b4e7d0c66f265/examples/create-react-app/public/logo512.png -------------------------------------------------------------------------------- /examples/create-react-app/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/create-react-app/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/create-react-app/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {AuthProvider} from 'react-auth-kit' 3 | import Routes from './Routes'; 4 | 5 | function App() { 6 | return ( 7 | 10 | 11 | 12 | ); 13 | } 14 | 15 | export default App; 16 | -------------------------------------------------------------------------------- /examples/create-react-app/src/Routes.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { PrivateRoute } from 'react-auth-kit' 3 | import { BrowserRouter, Route, Switch } from 'react-router-dom' 4 | import Home from './components/Home' 5 | import Login from './components/Login' 6 | import SecureComponent from './components/SecureComponent' 7 | 8 | const Routes = () => { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ) 18 | } 19 | 20 | export default Routes -------------------------------------------------------------------------------- /examples/create-react-app/src/components/Home.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { useHistory } from 'react-router-dom' 3 | 4 | const Home = () => { 5 | const history = useHistory() 6 | 7 | return ( 8 |
9 | 10 | 11 |
12 | ) 13 | } 14 | 15 | export default Home -------------------------------------------------------------------------------- /examples/create-react-app/src/components/Login.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {useIsAuthenticated, useSignIn} from 'react-auth-kit' 3 | import {Redirect, useHistory} from 'react-router-dom' 4 | 5 | const Login = () => { 6 | const isAuthenticated = useIsAuthenticated() 7 | const signIn = useSignIn() 8 | const history = useHistory() 9 | 10 | /** 11 | * Login Handle, the callback function onClick from the "Login" button 12 | * 13 | * This function demostrate a dummy authentication, using useSignIn function 14 | */ 15 | const loginHandler = () => { 16 | // Assuming that, all network Request is successfull, and the user is authenticated 17 | 18 | if (signIn({ 19 | token: '35v3443bn368367n306306wbn407qn420b436b4', //Just a random token 20 | tokenType: 'Bearer', // Token type set as Bearer 21 | authState: {name: 'React User', uid: 123456}, // Dummy auth user state 22 | expiresIn: 120 // Token Expriration time, in minutes 23 | })) { 24 | // If Login Successfull, then Redirect the user to secure route 25 | history.push('/secure') 26 | } else { 27 | // Else, there must be some error. So, throw an error 28 | alert("Error Occoured. Try Again") 29 | } 30 | } 31 | console.log(isAuthenticated()) 32 | if (isAuthenticated()) { 33 | // If authenticated user, then redirect to secure dashboard 34 | 35 | return ( 36 | 37 | ) 38 | } else { 39 | // If not authenticated, use the login flow 40 | // For Demostration, I'm using just a button to login. 41 | // In reality, there should be a form, validation, nwetowrk request and other things 42 | return ( 43 | 44 | ) 45 | } 46 | } 47 | 48 | export default Login 49 | -------------------------------------------------------------------------------- /examples/create-react-app/src/components/SecureComponent.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { useAuthUser, useSignOut } from 'react-auth-kit' 3 | 4 | const SecureComponent = () => { 5 | const signOut = useSignOut() 6 | const authUser = useAuthUser() 7 | 8 | return ( 9 |
10 |

{`Hello ${authUser().name}, your U-ID is: ${authUser().uid}`}

11 | 12 |
13 | ) 14 | } 15 | 16 | export default SecureComponent -------------------------------------------------------------------------------- /examples/create-react-app/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import * as serviceWorker from './serviceWorker'; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root') 11 | ); 12 | 13 | // If you want your app to work offline and load faster, you can change 14 | // unregister() to register() below. Note this comes with some pitfalls. 15 | // Learn more about service workers: https://bit.ly/CRA-PWA 16 | serviceWorker.unregister(); 17 | -------------------------------------------------------------------------------- /examples/create-react-app/src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.0/8 are considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl, { 104 | headers: { 'Service-Worker': 'script' }, 105 | }) 106 | .then(response => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 || 111 | (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then(registration => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready 134 | .then(registration => { 135 | registration.unregister(); 136 | }) 137 | .catch(error => { 138 | console.error(error.message); 139 | }); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /examples/create-react-app/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: ['/src'], 3 | transform: { 4 | '^.+\\.tsx?$': 'ts-jest', 5 | }, 6 | preset: 'ts-jest', 7 | testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$', 8 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], 9 | testEnvironment: "jsdom", 10 | verbose: true, 11 | collectCoverage:true 12 | }; 13 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: React Auth Kit 2 | site_description: Authentication Library for React Js for Token Based Auth using Json Web Token(JWT) 3 | site_author: Arkadip Bhattacharya 4 | site_url: https://authkit.arkadip.me 5 | 6 | repo_url: https://github.com/react-auth-kit/react-auth-kit 7 | repo_name: react-auth-kit/react-auth-kit 8 | 9 | copyright: Copyright © 2020 - 2021 React Auth Kit 10 | 11 | theme: 12 | name: 'material' 13 | custom_dir: docs/docs_overrides/ 14 | icon: 15 | repo: fontawesome/brands/github 16 | logo: img/logo.svg 17 | favicon: img/favicon.png 18 | palette: 19 | scheme: default 20 | primary: blue 21 | 22 | nav: 23 | - Introduction: 'index.md' 24 | - Installation: 'installation.md' 25 | - Integrate in your project: 'integration.md' 26 | - Sign In: 'signin.md' 27 | - Private Route: 'privateroute.md' 28 | - Sign Out: 'signout.md' 29 | - Auth User Data: 'authdata.md' 30 | - Auth Header: 'authheader.md' 31 | - Check Authentication: 'checkauth.md' 32 | - Refresh Token: 'refreshtoken.md' 33 | - Contributing: 'contributing.md' 34 | 35 | extra: 36 | analytics: 37 | provider: google 38 | property: G-G1WZBFV5R2 39 | version: 40 | provider: mike 41 | 42 | extra_javascript: 43 | - https://media.ethicalads.io/media/client/ethicalads.min.js 44 | 45 | markdown_extensions: 46 | - admonition 47 | - tables 48 | - pymdownx.details 49 | - pymdownx.inlinehilite 50 | - pymdownx.tabbed 51 | - pymdownx.superfences 52 | - toc: 53 | permalink: true 54 | - pymdownx.emoji: 55 | emoji_index: !!python/name:materialx.emoji.twemoji 56 | emoji_generator: !!python/name:materialx.emoji.to_svg 57 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-auth-kit", 3 | "version": "1.6.4", 4 | "description": "Authentication Library for React, which makes Token based auth very easy", 5 | "source": "src/index.tsx", 6 | "main": "dist/index.js", 7 | "module": "dist/index.modern.js", 8 | "unpkg": "dist/index.umd.js", 9 | "types": "dist/index.d.ts", 10 | "files": [ 11 | "dist" 12 | ], 13 | "engines": { 14 | "node": ">=8" 15 | }, 16 | "scripts": { 17 | "start": "rollup -cw", 18 | "build": "run-s build:*", 19 | "build:clean": "rimraf ./dist", 20 | "build:dir": "mkdirp ./dist", 21 | "build:build": "rollup -c", 22 | "prepare": "run-s build && husky install", 23 | "preversion": "run-s test", 24 | "test": "run-s test:*", 25 | "test:build": "run-s build", 26 | "test:unit": "jest", 27 | "test:lint": "eslint src/**/*.ts src/**/*.tsx --fix", 28 | "test:unit:watch": "jest --watch" 29 | }, 30 | "keywords": [ 31 | "react", 32 | "auth", 33 | "authentication", 34 | "jwt", 35 | "jsonwebtoken", 36 | "token" 37 | ], 38 | "author": { 39 | "name": "Arkadip Bhattacharya", 40 | "email": "in2arkadipb13@gmail.com", 41 | "url": "https://www.arkadip.me" 42 | }, 43 | "repository": { 44 | "type": "git", 45 | "url": "https://github.com/react-auth-kit/react-auth-kit" 46 | }, 47 | "license": "Apache-2.0", 48 | "devDependencies": { 49 | "@commitlint/cli": "^15.0.0", 50 | "@commitlint/config-conventional": "^15.0.0", 51 | "@rollup/plugin-node-resolve": "^13.0.6", 52 | "@semantic-release/changelog": "^6.0.1", 53 | "@semantic-release/git": "^10.0.1", 54 | "@testing-library/react": "^12.1.2", 55 | "@testing-library/react-hooks": "^7.0.2", 56 | "@types/jest": "^27.0.3", 57 | "@types/js-cookie": "^3.0.1", 58 | "@types/node": "^16.11.11", 59 | "@types/react": "^17.0.37", 60 | "@types/react-dom": "^17.0.11", 61 | "@types/react-router-dom": "^5.3.2", 62 | "@typescript-eslint/eslint-plugin": "^5.6.0", 63 | "@typescript-eslint/parser": "^5.5.0", 64 | "codecov": "^3.8.3", 65 | "eslint": "^8.4.1", 66 | "eslint-config-google": "^0.14.0", 67 | "eslint-plugin-jest": "^25.3.0", 68 | "eslint-plugin-react": "^7.27.1", 69 | "husky": "^7.0.4", 70 | "jest": "^27.4.3", 71 | "lint-staged": "^12.1.2", 72 | "mkdirp": "^1.0.4", 73 | "npm-run-all": "^4.1.5", 74 | "react-dom": "^17.0.1", 75 | "rimraf": "^3.0.2", 76 | "rollup": "^2.60.2", 77 | "rollup-plugin-filesize": "^9.0.2", 78 | "rollup-plugin-license": "^2.6.0", 79 | "rollup-plugin-peer-deps-external": "^2.2.3", 80 | "rollup-plugin-terser": "^7.0.0", 81 | "rollup-plugin-typescript2": "^0.31.1", 82 | "ts-jest": "^27.1.0", 83 | "tslib": "^2.3.1", 84 | "typedoc": "^0.22.10", 85 | "typescript": "^4.5.2", 86 | "utility-types": "^3.10.0" 87 | }, 88 | "dependencies": { 89 | "js-cookie": "^3.0.1", 90 | "react": ">=16.8.0", 91 | "react-router-dom": "^5.3.0" 92 | }, 93 | "peerDependencies": { 94 | "js-cookie": "^3.0.1", 95 | "react": ">=16.8.0", 96 | "react-dom": ">=16.8.0", 97 | "react-router-dom": "^5.3.0" 98 | }, 99 | "lint-staged": { 100 | "src/**/*.{ts,tsx,json,js}": "eslint --cache --fix" 101 | }, 102 | "release": { 103 | "plugins": [ 104 | "@semantic-release/commit-analyzer", 105 | "@semantic-release/release-notes-generator", 106 | "@semantic-release/changelog", 107 | "@semantic-release/npm", 108 | "@semantic-release/git", 109 | "@semantic-release/github" 110 | ] 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | 19 | import license from 'rollup-plugin-license'; 20 | import {terser} from 'rollup-plugin-terser'; 21 | import filesize from 'rollup-plugin-filesize'; 22 | import peerDepsExternal from 'rollup-plugin-peer-deps-external'; 23 | import resolve from '@rollup/plugin-node-resolve'; 24 | import typescript from 'rollup-plugin-typescript2'; 25 | 26 | import pkg from './package.json'; 27 | 28 | const licenseBanner = license({ 29 | banner: { 30 | content: '/*! <%= pkg.name %> v<%= pkg.version %> | <%= pkg.license %> */', 31 | commentStyle: 'none', 32 | }, 33 | }); 34 | 35 | export default [ 36 | { 37 | input: 'src/index.tsx', 38 | output: [ 39 | { 40 | file: pkg.main, 41 | format: 'cjs', 42 | sourcemap: true 43 | }, 44 | { 45 | file: pkg.module, 46 | format: 'esm', 47 | sourcemap: true 48 | }, 49 | ], 50 | plugins: [ 51 | peerDepsExternal(), 52 | resolve(), 53 | typescript(), 54 | filesize(), 55 | ], 56 | }, 57 | { 58 | input: 'src/index.tsx', 59 | output: [ 60 | { 61 | file: pkg.main.replace('.js', '.umd.js'), 62 | format: 'umd', 63 | name: 'ReactAuthKit', 64 | globals: { 65 | "react": "React", 66 | "js-cookie": "Cookies", 67 | "react-router-dom":"ReactRouterDOM" 68 | }, 69 | sourcemap: true 70 | }, 71 | ], 72 | plugins: [ 73 | peerDepsExternal(), 74 | resolve(), 75 | typescript(), 76 | terser(), 77 | licenseBanner, 78 | filesize(), 79 | ], 80 | }, 81 | ]; 82 | -------------------------------------------------------------------------------- /src/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jest": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/AuthContext.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Arkadip Bhattacharya 3 | * @fileoverview Auth Context 4 | * @copyright Arkadip Bhattacharya 2020 5 | * 6 | * Copyright 2020 Arkadip Bhattacharya 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | import * as React from 'react'; 22 | import {AuthContextInterface} from './types'; 23 | 24 | const AuthContext = React.createContext(null); 25 | 26 | const AuthContextConsumer = AuthContext.Consumer; 27 | export {AuthContextConsumer}; 28 | export default AuthContext; 29 | -------------------------------------------------------------------------------- /src/AuthProvider.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import AuthContext from './AuthContext'; 3 | import TokenObject from './TokenObject'; 4 | import {AuthProviderProps} from './types'; 5 | import {authReducer, doRefresh} from './utils/reducers'; 6 | import {useInterval} from './utils/hooks'; 7 | 8 | 9 | /** 10 | * AuthProvider - The Authentication Context Provider 11 | * 12 | * @param children 13 | * @param authStorageName 14 | * @param cookieDomain 15 | * @param cookieSecure 16 | * 17 | * @return Functional Component 18 | */ 19 | const AuthProvider: React.FunctionComponent = 20 | ({ 21 | children, 22 | authType, 23 | authName, 24 | cookieDomain, 25 | cookieSecure, 26 | refresh, 27 | }) => { 28 | if (authType === 'cookie') { 29 | if (!cookieDomain) { 30 | throw new 31 | Error('authType \'cookie\' ' + 32 | 'requires \'cookieDomain\' and \'cookieSecure\' ' + 33 | 'props in AuthProvider'); 34 | } 35 | } 36 | 37 | const refreshTokenName = refresh ? `${authName}_refresh` : null; 38 | 39 | const tokenObject = new TokenObject(authName, authType, 40 | refreshTokenName, cookieDomain, cookieSecure); 41 | 42 | const [authState, dispatch] = 43 | React.useReducer(authReducer, tokenObject.initialToken()); 44 | 45 | if (refresh) { 46 | useInterval( 47 | () => { 48 | refresh 49 | .refreshApiCallback({ 50 | authToken: authState.auth?.token, 51 | authTokenExpireAt: authState.auth?.expiresAt, 52 | authUserState: authState.userState, 53 | refreshToken: authState.refresh?.token, 54 | refreshTokenExpiresAt: authState.refresh?.expiresAt, 55 | }) 56 | .then((result) => { 57 | // IF the API call is successful then refresh the AUTH state 58 | if (result.isSuccess) { 59 | // store the new value using the state update 60 | dispatch(doRefresh(result)); 61 | } 62 | }); 63 | }, 64 | authState.isSignIn ? refresh.interval : null 65 | ); 66 | } 67 | 68 | React.useEffect(() => { 69 | tokenObject.syncTokens(authState); 70 | }, [authState]); 71 | 72 | return ( 73 | 74 | {children} 75 | 76 | ); 77 | }; 78 | 79 | export default AuthProvider; 80 | -------------------------------------------------------------------------------- /src/PrivateRoute.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Arkadip Bhattacharya 3 | * @fileoverview PrivateRoute component 4 | * @copyright Arkadip Bhattacharya 2020 5 | * 6 | * Copyright 2020 Arkadip Bhattacharya 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | import * as React from 'react'; 21 | import {Redirect, Route} from 'react-router-dom'; 22 | import AuthContext from './AuthContext'; 23 | import * as H from 'history'; 24 | import {RouteChildrenProps, RouteComponentProps} from 'react-router'; 25 | import {doSignOut} from './utils/reducers'; 26 | 27 | interface PrivateRouteProps { 28 | loginPath: string 29 | location?: H.Location; 30 | component?: React.ComponentType> | 31 | React.ComponentType; 32 | render?: (props: RouteComponentProps) => React.ReactNode; 33 | children?: ((props: RouteChildrenProps) => React.ReactNode) | 34 | React.ReactNode; 35 | path?: string | string[]; 36 | exact?: boolean; 37 | sensitive?: boolean; 38 | strict?: boolean; 39 | } 40 | 41 | /** 42 | * Private Route for Components 43 | * 44 | * @remarks 45 | * This Component is based on {@link https://reactrouter.com/web/api/Route | reactrouter.Route}. 46 | * So you need to install react-route-dom before use it 47 | * 48 | * @param props 49 | */ 50 | const PrivateRoute: React.FunctionComponent = (props) => { 51 | const context = React.useContext(AuthContext); 52 | if (context === null) { 53 | throw new 54 | Error('Auth Provider is missing. ' + 55 | 'Please add the AuthProvider before Router'); 56 | } 57 | 58 | const isAuth = () => { 59 | if (context.authState.auth) { 60 | if (new Date(context.authState.auth.expiresAt) > new Date()) { 61 | return true; 62 | } else { 63 | context.dispatch(doSignOut()); 64 | return false; 65 | } 66 | } else { 67 | return false; 68 | } 69 | }; 70 | 71 | const { 72 | component, 73 | loginPath, 74 | strict, 75 | sensitive, 76 | exact, 77 | path, 78 | location, 79 | render, 80 | } = props; 81 | 82 | return ( 83 | 90 | isAuth() ? 91 | component ? 92 | React.createElement(component, renderProps) : 93 | render ? 94 | render(renderProps) : 95 | null : 96 | 97 | } 98 | /> 99 | ); 100 | }; 101 | 102 | export default PrivateRoute; 103 | -------------------------------------------------------------------------------- /src/__tests__/AuthProvider.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import {render, screen} from '@testing-library/react'; 18 | import {AuthContextConsumer} from '../AuthContext'; 19 | import AuthProvider from '../AuthProvider'; 20 | import {BrowserRouter, Route} from 'react-router-dom'; 21 | import React from 'react'; 22 | import createRefresh from '../createRefresh'; 23 | import {AuthStateUserObject} from '../types'; 24 | import Cookies from 'js-cookie'; 25 | 26 | describe('AuthProvider renders successfully', ()=>{ 27 | it('With localStorage', ()=>{ 28 | render( 29 | 30 | 31 | 32 | 33 | , 34 | ); 35 | }); 36 | describe('With cookie', ()=>{ 37 | it('renders with all props given', ()=>{ 38 | render( 39 | 45 | 46 | 47 | 48 | , 49 | ); 50 | }); 51 | 52 | it('Throws an error, then props are missing', ()=>{ 53 | jest.spyOn(console, 'error').mockImplementation(jest.fn()); 54 | 55 | expect(() => render( 56 | 60 | 61 | 62 | 63 | , 64 | )).toThrow(); 65 | }); 66 | }); 67 | }); 68 | describe('Authprovider with refresh Token', ()=> { 69 | afterEach(() => { 70 | jest.useRealTimers(); 71 | }); 72 | const refreshApi = createRefresh({ 73 | interval: 1/60, 74 | refreshApiCallback: (param): any => { 75 | console.log(param); 76 | const result = new Promise((resolve) => { 77 | return resolve({ 78 | isSuccess: true, 79 | newAuthToken: "fsdgedgd", 80 | newAuthTokenExpireIn: 10, 81 | newRefreshTokenExpiresIn: 60, 82 | }); 83 | }); 84 | return result; 85 | }, 86 | }); 87 | 88 | it('renders successfully', ()=>{ 89 | const {container} = render( 90 | 95 | 96 | 97 | 98 | , 99 | ); 100 | expect(container.nodeName).toMatch('DIV'); 101 | }); 102 | 103 | it('Initially signed in', ()=>{ 104 | jest.useFakeTimers(); 105 | const spyRefreshApi = jest.spyOn(refreshApi, 'refreshApiCallback'); 106 | 107 | const authToken = '__authToken'; 108 | const authType = '__authType'; 109 | const authTime = new Date(2021, 10, 5); 110 | const refreshToken = '__refreshToken'; 111 | const refreshTime = new Date(2021, 10, 6); 112 | const userState = {key: 'val'} as AuthStateUserObject; 113 | 114 | Cookies.get = jest 115 | .fn() 116 | .mockImplementationOnce(() => authToken) 117 | .mockImplementationOnce(() => authType) 118 | .mockImplementationOnce(() => authTime) 119 | .mockImplementationOnce(() => JSON.stringify(userState)) 120 | .mockImplementationOnce(() => refreshToken) 121 | .mockImplementationOnce(() => refreshTime); 122 | 123 | const TestConsumer = () => { 124 | (value) => ( 125 | 126 | isSignIn: {value?.authState.isSignIn ? 'true' : 'false'} 127 | 128 | ) 129 | }; 130 | 131 | render( 132 | 139 | 140 | 141 | 142 | 143 | , 144 | ); 145 | 146 | // Check if refreshApiCallback is called 147 | expect(spyRefreshApi).not.toBeCalled(); 148 | jest.advanceTimersByTime(1000); 149 | 150 | // TODO: assertion statements needed 151 | expect(screen.getByText(/^isSignIn:/).textContent).toBe('isSignIn: true'); 152 | 153 | // Check if refreshApiCallback is called 154 | expect(spyRefreshApi).toHaveBeenCalled(); 155 | 156 | // Check again if refreshApiCallback is called 157 | jest.advanceTimersByTime(1000); 158 | expect(spyRefreshApi).toHaveBeenCalledTimes(2); 159 | 160 | jest.useRealTimers(); 161 | }); 162 | }); 163 | 164 | export {}; 165 | -------------------------------------------------------------------------------- /src/__tests__/PrivateRoute.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import {render, screen} from '@testing-library/react'; 17 | import React from 'react'; 18 | import PrivateRoute from '../PrivateRoute'; 19 | import {BrowserRouter} from 'react-router-dom'; 20 | import AuthProvider from '../AuthProvider'; 21 | import AuthContext from '../AuthContext'; 22 | import {AuthKitStateInterface} from '../types'; 23 | import {doSignOut} from '../utils/reducers'; 24 | 25 | // Helpers 26 | const getPastDate = () => new Date(new Date().getTime() - 1000); 27 | const getFutureDate = () => new Date(new Date().getTime() + 1000); 28 | const getFakeContextValue = (expiresAt: Date, dispatch = jest.fn()) => { 29 | const authState: AuthKitStateInterface = { 30 | auth: { 31 | token: 'fake-token', 32 | type: 'cookie', 33 | expiresAt, 34 | }, 35 | refresh: null, 36 | userState: null, 37 | isSignIn: false, 38 | isUsingRefreshToken: false, 39 | }; 40 | 41 | return { 42 | authState, 43 | dispatch, 44 | }; 45 | }; 46 | 47 | describe('PrivateRoute component', () => { 48 | it('renders successfully with AuthProvider', () => { 49 | const {container} = render( 50 | 52 | 53 | 54 | 55 | , 56 | ); 57 | expect(container.nodeName).toMatch('DIV'); 58 | }); 59 | 60 | it('throws, when used outside AuthProvider', () => { 61 | jest.spyOn(console, 'error').mockImplementation(jest.fn()); 62 | 63 | expect(() => render( 64 | 65 | 66 | , 67 | )).toThrow(); 68 | }); 69 | 70 | it('renders component, when the token has not yet expired', () => { 71 | const TestComponent = () =>

Test Component

; 72 | const fakeContextValue = getFakeContextValue(getFutureDate()); 73 | 74 | render( 75 | 76 | 77 | 78 | 79 | , 80 | ); 81 | 82 | expect(screen.getByText(/test component/i)).toBeTruthy(); 83 | }); 84 | 85 | it('dispatches "doSignOut" action, when the token has expired', () => { 86 | const TestComponent = () =>

Test Component

; 87 | const fakeDispatch = jest.fn(); 88 | const fakeContextValue = getFakeContextValue(getPastDate(), fakeDispatch); 89 | 90 | render( 91 | 92 | 93 | 94 | 95 | , 96 | ); 97 | 98 | expect(fakeDispatch).toHaveBeenCalled(); 99 | expect(fakeDispatch).toHaveBeenCalledWith(doSignOut()); 100 | }); 101 | 102 | it('renders component using render prop', () => { 103 | const TestComponent = () =>

Test Component

; 104 | const fakeContextValue = getFakeContextValue(getFutureDate()); 105 | 106 | render( 107 | 108 | 109 | }/> 110 | 111 | , 112 | ); 113 | 114 | expect(screen.getByText(/test component/i)).toBeTruthy(); 115 | }); 116 | 117 | it('renders nothing, missing both "component" and "render" props', () => { 118 | const fakeDispatch = jest.fn(); 119 | const fakeContextValue = getFakeContextValue(getFutureDate(), fakeDispatch); 120 | 121 | render( 122 | 123 | 124 | 125 |
126 | 127 |
128 |
129 |
, 130 | ); 131 | 132 | expect(fakeDispatch).not.toHaveBeenCalled(); 133 | expect(screen.getByTestId('parent').hasChildNodes()).toBe(false); 134 | }); 135 | }); 136 | 137 | export {}; 138 | -------------------------------------------------------------------------------- /src/__tests__/hooks/useAuthHeader.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import React from 'react'; 18 | import {renderHook} from '@testing-library/react-hooks'; 19 | import useAuthHeader from '../../hooks/useAuthHeader'; 20 | import AuthContext from '../../AuthContext'; 21 | 22 | describe('useAuthHeader', () => { 23 | it('should thrown an error if the AuthContext is not available', () => { 24 | expect(useAuthHeader).toThrow(Error); 25 | }); 26 | 27 | it('should return an empty string if the user is not in the context', () => { 28 | const fakeAuthState = { 29 | authState: { 30 | auth: null, 31 | refresh: null, 32 | userState: null, 33 | isSignIn: false, 34 | isUsingRefreshToken: false, 35 | }, 36 | dispatch: () => null, 37 | }; 38 | const wrapper = ({children}: {children: React.ReactNode}) => ( 39 | 40 | {children} 41 | 42 | ); 43 | 44 | const {result} = renderHook(() => useAuthHeader(), {wrapper}); 45 | expect(result.current()).toBe(''); 46 | }); 47 | 48 | it('should return the auth header if it is available in the context', () => { 49 | const fakeAuthState = { 50 | authState: { 51 | auth: { 52 | type: 'Bearer', 53 | token: 'xxxxxxxxx', 54 | expiresAt: new Date(), 55 | }, 56 | refresh: null, 57 | userState: null, 58 | isSignIn: false, 59 | isUsingRefreshToken: false, 60 | }, 61 | dispatch: () => null, 62 | }; 63 | const wrapper = ({children}: {children: React.ReactNode}) => ( 64 | 65 | {children} 66 | 67 | ); 68 | 69 | const {result} = renderHook(() => useAuthHeader(), {wrapper}); 70 | expect(result.current()).toBe('Bearer xxxxxxxxx'); 71 | }); 72 | }); 73 | 74 | export {}; 75 | -------------------------------------------------------------------------------- /src/__tests__/hooks/useAuthUser.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import React from 'react'; 18 | import {renderHook} from '@testing-library/react-hooks'; 19 | import useAuthUser from '../../hooks/useAuthUser'; 20 | import AuthContext from '../../AuthContext'; 21 | 22 | describe('useAuthUser', () => { 23 | it('should thrown an error if the AuthContext is not available', () => { 24 | expect(useAuthUser).toThrow(Error); 25 | }); 26 | 27 | it('should return null if the user is not in authenticated', () => { 28 | const fakeAuthState = { 29 | authState: { 30 | auth: null, 31 | refresh: null, 32 | userState: { 33 | id: 'user-id', 34 | }, 35 | isSignIn: false, 36 | isUsingRefreshToken: false, 37 | }, 38 | dispatch: () => null, 39 | }; 40 | const wrapper = ({children}: {children: React.ReactNode}) => ( 41 | 42 | {children} 43 | 44 | ); 45 | 46 | const {result} = renderHook(() => useAuthUser(), {wrapper}); 47 | expect(result.current()).toBe(null); 48 | }); 49 | 50 | it('should return the user state if the user is authenticated', () => { 51 | const fakeAuthState = { 52 | authState: { 53 | auth: { 54 | type: 'Bearer', 55 | token: 'xxxxxxxxx', 56 | expiresAt: new Date(), 57 | }, 58 | refresh: null, 59 | userState: { 60 | id: 'user-id', 61 | }, 62 | isSignIn: false, 63 | isUsingRefreshToken: false, 64 | }, 65 | dispatch: () => null, 66 | }; 67 | const wrapper = ({children}: {children: React.ReactNode}) => ( 68 | 69 | {children} 70 | 71 | ); 72 | 73 | const {result} = renderHook(() => useAuthUser(), {wrapper}); 74 | expect(result.current()).toStrictEqual({id: 'user-id'}); 75 | }); 76 | }); 77 | 78 | export {}; 79 | -------------------------------------------------------------------------------- /src/__tests__/hooks/useIsAuthenticated.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import React from 'react'; 18 | import {renderHook} from '@testing-library/react-hooks'; 19 | import useIsAuthenticated from '../../hooks/useIsAuthenticated'; 20 | import AuthContext from '../../AuthContext'; 21 | import {ActionType} from '../../utils/actions'; 22 | 23 | describe('useIsAuthenticated', () => { 24 | it('should thrown an error if the AuthContext is not available', () => { 25 | expect(useIsAuthenticated).toThrow(Error); 26 | }); 27 | 28 | it('should return false if the auth data is not in the context', () => { 29 | const fakeAuthState = { 30 | authState: { 31 | auth: null, 32 | refresh: null, 33 | userState: null, 34 | isSignIn: false, 35 | isUsingRefreshToken: false, 36 | }, 37 | dispatch: jest.fn(), 38 | }; 39 | const wrapper = ({children}: {children: React.ReactNode}) => ( 40 | 41 | {children} 42 | 43 | ); 44 | 45 | const {result} = renderHook(() => useIsAuthenticated(), {wrapper}); 46 | expect(result.current()).toBe(false); 47 | expect(fakeAuthState.dispatch).not.toBeCalled(); 48 | }); 49 | 50 | it('should return false and signout if the auth is expired', () => { 51 | const fakeAuthState = { 52 | authState: { 53 | auth: { 54 | type: 'Bearer', 55 | token: 'xxxxxxxxx', 56 | expiresAt: new Date((new Date()).getTime() - 10000), 57 | }, 58 | refresh: null, 59 | userState: null, 60 | isSignIn: false, 61 | isUsingRefreshToken: false, 62 | }, 63 | dispatch: jest.fn(), 64 | }; 65 | const wrapper = ({children}: {children: React.ReactNode}) => ( 66 | 67 | {children} 68 | 69 | ); 70 | 71 | const {result} = renderHook(() => useIsAuthenticated(), {wrapper}); 72 | expect(result.current()).toBe(false); 73 | expect(fakeAuthState.dispatch).toBeCalledWith({type: ActionType.SignOut}); 74 | }); 75 | 76 | it('should return true if the auth is there and not expired', () => { 77 | const fakeAuthState = { 78 | authState: { 79 | auth: { 80 | type: 'Bearer', 81 | token: 'xxxxxxxxx', 82 | expiresAt: new Date((new Date()).getTime() + 10000), 83 | }, 84 | refresh: null, 85 | userState: null, 86 | isSignIn: false, 87 | isUsingRefreshToken: false, 88 | }, 89 | dispatch: jest.fn(), 90 | }; 91 | const wrapper = ({children}: {children: React.ReactNode}) => ( 92 | 93 | {children} 94 | 95 | ); 96 | 97 | const {result} = renderHook(() => useIsAuthenticated(), {wrapper}); 98 | expect(result.current()).toBe(true); 99 | expect(fakeAuthState.dispatch).not.toBeCalled(); 100 | }); 101 | }); 102 | 103 | export {}; 104 | -------------------------------------------------------------------------------- /src/__tests__/hooks/useSignIn.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import React from 'react'; 18 | import {renderHook} from '@testing-library/react-hooks'; 19 | import useSignIn from '../../hooks/useSignIn'; 20 | import AuthContext from '../../AuthContext'; 21 | import {ActionType} from '../../utils/actions'; 22 | 23 | Date.now = jest.fn(() => 1487076708000); 24 | 25 | const fakeTime = new Date('2020-01-01').getTime(); 26 | jest.useFakeTimers().setSystemTime(fakeTime); 27 | 28 | describe('useSignIn', () => { 29 | it('should thrown an error if the AuthContext is not available', () => { 30 | expect(useSignIn).toThrow(Error); 31 | }); 32 | 33 | it('should fail when receive refresh tokens if they are disabled', () => { 34 | const fakeAuthState = { 35 | authState: { 36 | auth: null, 37 | refresh: null, 38 | userState: null, 39 | isSignIn: false, 40 | isUsingRefreshToken: false, 41 | }, 42 | dispatch: jest.fn(), 43 | }; 44 | const wrapper = ({children}: {children: React.ReactNode}) => ( 45 | 46 | {children} 47 | 48 | ); 49 | 50 | const {result} = renderHook(() => useSignIn(), {wrapper}); 51 | expect(() => result.current({ 52 | token: 'token', 53 | tokenType: 'Bearer', 54 | authState: {data: 'data'}, 55 | expiresIn: 10, 56 | refreshToken: 'xxxx', 57 | refreshTokenExpireIn: 20, 58 | })).toThrow(Error); 59 | expect(fakeAuthState.dispatch).not.toBeCalled(); 60 | }); 61 | 62 | it('should fail when not receive refresh tokens if they are enabled', () => { 63 | const fakeAuthState = { 64 | authState: { 65 | auth: null, 66 | refresh: null, 67 | userState: null, 68 | isSignIn: false, 69 | isUsingRefreshToken: true, 70 | }, 71 | dispatch: jest.fn(), 72 | }; 73 | const wrapper = ({children}: {children: React.ReactNode}) => ( 74 | 75 | {children} 76 | 77 | ); 78 | 79 | const {result} = renderHook(() => useSignIn(), {wrapper}); 80 | expect(() => result.current({ 81 | token: 'token', 82 | tokenType: 'Bearer', 83 | authState: {data: 'data'}, 84 | expiresIn: 10, 85 | refreshToken: '', 86 | refreshTokenExpireIn: 0, 87 | })).toThrow(Error); 88 | expect(fakeAuthState.dispatch).not.toBeCalled(); 89 | }); 90 | 91 | it('should dispatch a signIn action with refresh disabled', () => { 92 | const fakeAuthState = { 93 | authState: { 94 | auth: null, 95 | refresh: null, 96 | userState: null, 97 | isSignIn: false, 98 | isUsingRefreshToken: false, 99 | }, 100 | dispatch: jest.fn(), 101 | }; 102 | const wrapper = ({children}: {children: React.ReactNode}) => ( 103 | 104 | {children} 105 | 106 | ); 107 | 108 | const {result} = renderHook(() => useSignIn(), {wrapper}); 109 | expect(() => result.current({ 110 | token: 'token', 111 | tokenType: 'Bearer', 112 | authState: {data: 'data'}, 113 | expiresIn: 10, 114 | refreshToken: '', 115 | refreshTokenExpireIn: 0, 116 | })).not.toThrow(Error); 117 | expect(fakeAuthState.dispatch).toBeCalledWith({ 118 | type: ActionType.SignIn, 119 | payload: { 120 | auth: { 121 | token: 'token', 122 | type: 'Bearer', 123 | expiresAt: new Date(fakeTime + 10 * 1000 * 60), 124 | }, 125 | refresh: null, 126 | userState: {data: 'data'}, 127 | }, 128 | }); 129 | }); 130 | 131 | it('should dispatch a signIn action with refresh enabled', () => { 132 | const fakeAuthState = { 133 | authState: { 134 | auth: null, 135 | refresh: null, 136 | userState: null, 137 | isSignIn: false, 138 | isUsingRefreshToken: true, 139 | }, 140 | dispatch: jest.fn(), 141 | }; 142 | const wrapper = ({children}: {children: React.ReactNode}) => ( 143 | 144 | {children} 145 | 146 | ); 147 | 148 | const {result} = renderHook(() => useSignIn(), {wrapper}); 149 | expect(() => result.current({ 150 | token: 'token', 151 | tokenType: 'Bearer', 152 | authState: {data: 'data'}, 153 | expiresIn: 10, 154 | refreshToken: 'xxxx', 155 | refreshTokenExpireIn: 20, 156 | })).not.toThrow(Error); 157 | expect(fakeAuthState.dispatch).toBeCalledWith({ 158 | type: ActionType.SignIn, 159 | payload: { 160 | auth: { 161 | token: 'token', 162 | type: 'Bearer', 163 | expiresAt: new Date(fakeTime + 10 * 1000 * 60), 164 | }, 165 | refresh: { 166 | expiresAt: new Date(fakeTime + 20 * 1000 * 60), 167 | token: 'xxxx', 168 | }, 169 | userState: {data: 'data'}, 170 | }, 171 | }); 172 | }); 173 | }); 174 | -------------------------------------------------------------------------------- /src/__tests__/hooks/useSignOut.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import React from 'react'; 18 | import {renderHook} from '@testing-library/react-hooks'; 19 | import useSignOut from '../../hooks/useSignOut'; 20 | import AuthContext from '../../AuthContext'; 21 | import {ActionType} from '../../utils/actions'; 22 | 23 | describe('useSignOut', () => { 24 | it('should thrown an error if the AuthContext is not available', () => { 25 | expect(useSignOut).toThrow(Error); 26 | }); 27 | 28 | it('should signOut and return true on success', () => { 29 | const fakeAuthState = { 30 | authState: { 31 | auth: null, 32 | refresh: null, 33 | userState: null, 34 | isSignIn: false, 35 | isUsingRefreshToken: false, 36 | }, 37 | dispatch: jest.fn(), 38 | }; 39 | const wrapper = ({children}: {children: React.ReactNode}) => ( 40 | 41 | {children} 42 | 43 | ); 44 | 45 | const {result} = renderHook(() => useSignOut(), {wrapper}); 46 | expect(result.current()).toBe(true); 47 | expect(fakeAuthState.dispatch).toBeCalledWith({type: ActionType.SignOut}); 48 | }); 49 | 50 | it('should signOut and return false on failure', () => { 51 | const fakeAuthState = { 52 | authState: { 53 | auth: null, 54 | refresh: null, 55 | userState: null, 56 | isSignIn: false, 57 | isUsingRefreshToken: false, 58 | }, 59 | dispatch: jest.fn(() => { 60 | throw new Error('test'); 61 | }), 62 | }; 63 | const wrapper = ({children}: {children: React.ReactNode}) => ( 64 | 65 | {children} 66 | 67 | ); 68 | 69 | const {result} = renderHook(() => useSignOut(), {wrapper}); 70 | expect(result.current()).toBe(false); 71 | expect(fakeAuthState.dispatch).toBeCalledWith({type: ActionType.SignOut}); 72 | }); 73 | }); 74 | 75 | export {}; 76 | -------------------------------------------------------------------------------- /src/__tests__/index.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | describe('PrivateRoute', () => { 18 | it('is truthy', () => { 19 | expect(1).toBeTruthy(); 20 | }); 21 | }); 22 | 23 | export {}; 24 | -------------------------------------------------------------------------------- /src/__tests__/utils/hooks.test.ts: -------------------------------------------------------------------------------- 1 | import {renderHook} from '@testing-library/react-hooks'; 2 | import {useInterval} from '../../utils/hooks'; 3 | 4 | describe('useInterval', () => { 5 | const callback = jest.fn(); 6 | 7 | // setup to use fake timers to prevent flakey results from setInterval 8 | beforeEach(() => { 9 | jest.useFakeTimers(); 10 | jest.clearAllMocks(); 11 | }); 12 | 13 | afterEach(() => { 14 | jest.runOnlyPendingTimers(); 15 | jest.useRealTimers(); 16 | }); 17 | 18 | it('Should call callback after a delay', () => { 19 | renderHook(() => useInterval(callback, 10)); 20 | expect(callback).not.toHaveBeenCalled(); 21 | 22 | // fast-forward and exhaust pending timers 23 | jest.runOnlyPendingTimers(); 24 | expect(callback).toHaveBeenCalled(); 25 | }); 26 | it('Should not call callback when no delay is passed', () => { 27 | renderHook(() => useInterval(callback, null)); 28 | expect(callback).not.toHaveBeenCalled(); 29 | }); 30 | it('Should stop execution of setInterval if new delay passed is null', () => { 31 | let delay: number | null = 10; 32 | const {rerender} = renderHook(() => useInterval(callback, delay)); 33 | expect(callback).not.toHaveBeenCalled(); 34 | 35 | // set a new delay of null during execution of prev delay 36 | delay = null; 37 | rerender(); 38 | 39 | // fast-forward and exhaust any pending timers 40 | jest.runOnlyPendingTimers(); 41 | expect(callback).not.toHaveBeenCalled(); 42 | }); 43 | it('Should return ref interval id when passed a delay', () => { 44 | const {result} = renderHook(() => useInterval(callback, 1)); 45 | expect(typeof result.current.current).toBe('number'); 46 | }); 47 | it('Should return ref with null value when no delay is passed', () => { 48 | const {result} = renderHook(() => useInterval(callback, null)); 49 | expect(result.current.current).toBeNull(); 50 | }); 51 | }); 52 | 53 | -------------------------------------------------------------------------------- /src/createRefresh.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import {createRefreshParamInterface} from './types'; 18 | 19 | /** 20 | * This function doesn't really "do anything" at runtime, 21 | * it's just help to organize the code base 22 | * Use this function to create the refresh token system 23 | */ 24 | function createRefresh(param: createRefreshParamInterface) 25 | :createRefreshParamInterface { 26 | return param; 27 | } 28 | 29 | export default createRefresh; 30 | -------------------------------------------------------------------------------- /src/higherOrderComponents/withAuthHeader.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Arkadip Bhattacharya 3 | * @fileoverview Authentication header 4 | * @copyright Arkadip Bhattacharya 2020 5 | * 6 | * Copyright 2020 Arkadip Bhattacharya 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | import * as React from 'react'; 22 | import {AuthContextConsumer} from '../AuthContext'; 23 | 24 | /** 25 | * @interface withAuthHeaderProps 26 | */ 27 | interface withAuthHeaderProps { 28 | authHeader: string 29 | } 30 | 31 | /** 32 | * @public 33 | * @function 34 | * @name withAuthHeader 35 | * @description Inject Authentication Header inside the Component's Prop 36 | * @param Component - React Component 37 | */ 38 | function withAuthHeader

( 39 | Component: React.ComponentType

, 40 | ):React.FunctionComponent

{ 41 | return (props) => { 42 | return ( 43 | 44 | {(c) => { 45 | if (c === null) { 46 | throw new 47 | Error('Auth Provider is missing. ' + 48 | 'Please add the AuthProvider before Router'); 49 | } 50 | if (c.authState.auth) { 51 | return ( 52 | 58 | ); 59 | } else { 60 | return ; 61 | } 62 | }} 63 | 64 | ); 65 | }; 66 | } 67 | /** 68 | *@exports withAuthHeader 69 | */ 70 | export default withAuthHeader; 71 | -------------------------------------------------------------------------------- /src/higherOrderComponents/withAuthUser.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Arkadip Bhattacharya 3 | * @fileoverview Authentication User 4 | * @copyright Arkadip Bhattacharya 2020 5 | * 6 | * Copyright 2020 Arkadip Bhattacharya 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | import * as React from 'react'; 21 | import {AuthContextConsumer} from '../AuthContext'; 22 | import {AuthStateUserObject} from '../types'; 23 | 24 | /** 25 | * @interface withAuthProps 26 | */ 27 | interface withAuthProps { 28 | authState: AuthStateUserObject| null 29 | } 30 | 31 | /** 32 | * @function 33 | * @name withAuthUser 34 | * @description Inject Authenticated User's state inside the Component's Prop 35 | * @param Component 36 | */ 37 | function withAuthUser

( 38 | Component: React.ComponentType

, 39 | ): React.FunctionComponent

{ 40 | return (props: P)=>{ 41 | return ( 42 | 43 | {(context) => { 44 | if (context === null) { 45 | throw new 46 | Error('Auth Provider is missing. ' + 47 | 'Please add the AuthProvider before Router'); 48 | } 49 | if (context.authState.auth) { 50 | return ( 51 | 52 | ); 53 | } else { 54 | return ( 55 | 56 | ); 57 | } 58 | }} 59 | 60 | ); 61 | }; 62 | } 63 | /** 64 | * @exports withAuthUser 65 | */ 66 | export default withAuthUser; 67 | -------------------------------------------------------------------------------- /src/higherOrderComponents/withIsAuthenticated.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Arkadip Bhattacharya 3 | * @fileoverview Authentication status 4 | * @copyright Arkadip Bhattacharya 2020 5 | * 6 | * Copyright 2020 Arkadip Bhattacharya 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | import * as React from 'react'; 22 | import {AuthContextConsumer} from '../AuthContext'; 23 | import {doSignOut} from '../utils/reducers'; 24 | 25 | /** 26 | * @interface withAuthHeaderProps 27 | */ 28 | interface withAuthHeaderProps { 29 | isAuth: string 30 | } 31 | 32 | /** 33 | * @public 34 | * @function 35 | * @name withIsAuthenticated 36 | * @description Inject Authentication status inside the Component's Prop 37 | * @param Component 38 | */ 39 | function withIsAuthenticated

( 40 | Component: React.ComponentType

, 41 | ): React.FunctionComponent

{ 42 | return (props) => { 43 | return ( 44 | 45 | {(c) => { 46 | if (c === null) { 47 | throw new 48 | Error('Auth Provider is missing. ' + 49 | 'Please add the AuthProvider before Router'); 50 | } 51 | if (c.authState.auth) { 52 | if (new Date(c.authState.auth.expiresAt) > new Date()) { 53 | return ; 54 | } else { 55 | c.dispatch(doSignOut()); 56 | return ; 57 | } 58 | } else { 59 | return ; 60 | } 61 | }} 62 | 63 | ); 64 | }; 65 | } 66 | 67 | export default withIsAuthenticated; 68 | -------------------------------------------------------------------------------- /src/higherOrderComponents/withSignIn.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Arkadip Bhattacharya 3 | * @fileoverview Sign In functionality 4 | * @copyright Arkadip Bhattacharya 2020 5 | * 6 | * Copyright 2020 Arkadip Bhattacharya 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | import * as React from 'react'; 21 | import {AuthContextConsumer} from '../AuthContext'; 22 | import {signInFunctionParams} from '../types'; 23 | import {doSignIn} from '../utils/reducers'; 24 | 25 | /** 26 | * @interface withSignInProps 27 | */ 28 | interface withSignInProps { 29 | signIn(params: signInFunctionParams): boolean 30 | } 31 | 32 | /** 33 | * @public 34 | * @function 35 | * @name withSignIn 36 | * @description Inject sign in functionality inside the Component's Prop 37 | * @param Component 38 | */ 39 | function withSignIn

( 40 | Component: React.ComponentType

, 41 | ):React.FunctionComponent

{ 42 | return (props) => { 43 | return ( 44 | 45 | {(c) => { 46 | if (c === null) { 47 | throw new 48 | Error('Auth Provider is missing. ' + 49 | 'Please add the AuthProvider before Router'); 50 | } 51 | const signIn = (signInConfig: signInFunctionParams) 52 | : boolean => { 53 | const { 54 | token, 55 | tokenType, 56 | authState, 57 | expiresIn, 58 | refreshToken, 59 | refreshTokenExpireIn, 60 | } = signInConfig; 61 | const expTime = 62 | new Date(new Date().getTime() + expiresIn * 60 * 1000); 63 | if (c.authState.isUsingRefreshToken) { 64 | // Using the power of refresh token 65 | if (!!refreshToken && !!refreshTokenExpireIn) { 66 | // refresh token params are provided 67 | // sign in with refresh token 68 | const refreshTokenExpireAt = new Date(new Date().getTime() + 69 | refreshTokenExpireIn * 60 * 1000); 70 | c.dispatch(doSignIn({ 71 | auth: { 72 | token: token, 73 | type: tokenType, 74 | expiresAt: expTime, 75 | }, 76 | userState: authState ? authState : null, 77 | refresh: { 78 | token: refreshToken, 79 | expiresAt: refreshTokenExpireAt, 80 | }, 81 | })); 82 | return true; 83 | } else { 84 | // refresh token params are not provided 85 | // throw an error 86 | throw new Error('Make sure you given "refreshToken" and ' + 87 | '"refreshTokenExpireIn" parameter'); 88 | } 89 | } else { 90 | // Not using refresh token 91 | if (!!refreshToken && !!refreshTokenExpireIn) { 92 | // params are not expected but provided 93 | // throw an error 94 | throw new Error('The app doesn\'t implement \'refreshToken\'' + 95 | ' feature.\n So you have to implement refresh token feature' + 96 | ' from \'AuthProvider\' before using it.'); 97 | } else { 98 | // sign in without the refresh token 99 | c.dispatch(doSignIn({ 100 | auth: { 101 | token: token, 102 | type: tokenType, 103 | expiresAt: expTime, 104 | }, 105 | userState: authState ? authState : null, 106 | refresh: null, 107 | })); 108 | return true; 109 | } 110 | } 111 | }; 112 | return ; 113 | }} 114 | 115 | ); 116 | }; 117 | } 118 | 119 | export default withSignIn; 120 | -------------------------------------------------------------------------------- /src/higherOrderComponents/withSignOut.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Arkadip Bhattacharya 3 | * @fileoverview Sign Out functionality 4 | * @copyright Arkadip Bhattacharya 2020 5 | * 6 | * Copyright 2020 Arkadip Bhattacharya 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | import * as React from 'react'; 21 | import {AuthContextConsumer} from '../AuthContext'; 22 | import {doSignOut} from '../utils/reducers'; 23 | 24 | /** 25 | * @interface withSignOutProps 26 | */ 27 | interface withSignOutProps { 28 | signOut(): boolean 29 | } 30 | 31 | /** 32 | * @public 33 | * @function 34 | * @name withSignOut 35 | * @description Inject sign Out functionality inside the Component's Prop 36 | * @param Component 37 | */ 38 | function withSignOut

( 39 | Component: React.ComponentType

, 40 | ): React.FunctionComponent

{ 41 | return (props) => { 42 | return ( 43 | 44 | {(c) => { 45 | if (c === null) { 46 | throw new 47 | Error('Auth Provider is missing. ' + 48 | 'Please add the AuthProvider before Router'); 49 | } 50 | const signOut = () => { 51 | try { 52 | if (c) { 53 | c.dispatch(doSignOut()); 54 | return true; 55 | } else { 56 | return false; 57 | } 58 | } catch (e) { 59 | return false; 60 | } 61 | }; 62 | return ; 63 | }} 64 | 65 | ); 66 | }; 67 | } 68 | 69 | export default withSignOut; 70 | -------------------------------------------------------------------------------- /src/hooks/useAuthHeader.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Arkadip Bhattacharya 3 | * @fileoverview Authentication header 4 | * @copyright Arkadip Bhattacharya 2020 5 | * 6 | * Copyright 2020 Arkadip Bhattacharya 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | import * as React from 'react'; 22 | import AuthContext from '../AuthContext'; 23 | 24 | /** 25 | * 26 | */ 27 | function useAuthHeader(): () => (string) { 28 | const c = React.useContext(AuthContext); 29 | if (c === null) { 30 | throw new 31 | Error('Auth Provider is missing. ' + 32 | 'Please add the AuthProvider before Router'); 33 | } 34 | 35 | 36 | return () => { 37 | if (c.authState.auth) { 38 | return `${c.authState.auth.type} ${c.authState.auth.token}`; 39 | } else { 40 | return ``; 41 | } 42 | }; 43 | } 44 | 45 | export default useAuthHeader; 46 | -------------------------------------------------------------------------------- /src/hooks/useAuthUser.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Arkadip Bhattacharya 3 | * @fileoverview Authentication User 4 | * @copyright Arkadip Bhattacharya 2020 5 | * 6 | * Copyright 2020 Arkadip Bhattacharya 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | import * as React from 'react'; 22 | import AuthContext from '../AuthContext'; 23 | import {AuthStateUserObject} from '../types'; 24 | 25 | /** 26 | * Auth State Hook 27 | * 28 | * @returns - Auth State Function 29 | */ 30 | function useAuthUser(): () => AuthStateUserObject | null { 31 | const context = React.useContext(AuthContext); 32 | if (context === null) { 33 | throw new 34 | Error('Auth Provider is missing. ' + 35 | 'Please add the AuthProvider before Router'); 36 | } 37 | return () => { 38 | return context.authState.auth ? 39 | context.authState.userState : null; 40 | }; 41 | } 42 | 43 | export default useAuthUser; 44 | -------------------------------------------------------------------------------- /src/hooks/useIsAuthenticated.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Arkadip Bhattacharya 3 | * @fileoverview Authentication status 4 | * @copyright Arkadip Bhattacharya 2020 5 | * 6 | * Copyright 2020 Arkadip Bhattacharya 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | import * as React from 'react'; 22 | import AuthContext from '../AuthContext'; 23 | import {doSignOut} from '../utils/reducers'; 24 | 25 | /** 26 | *@function 27 | *@name useIsAuthenticated 28 | *@description check weather user is authenticated or not 29 | */ 30 | function useIsAuthenticated(): ()=>boolean { 31 | const context = React.useContext(AuthContext); 32 | if (context === null) { 33 | throw new 34 | Error('Auth Provider is missing. ' + 35 | 'Please add the AuthProvider before Router'); 36 | } 37 | return () => { 38 | if (context.authState.auth) { 39 | if (new Date(context.authState.auth.expiresAt) > new Date()) { 40 | return true; 41 | } else { 42 | context.dispatch(doSignOut()); 43 | return false; 44 | } 45 | } else { 46 | return false; 47 | } 48 | }; 49 | } 50 | /** 51 | *@exports useIsAuthenticated 52 | */ 53 | export default useIsAuthenticated; 54 | -------------------------------------------------------------------------------- /src/hooks/useSignIn.ts: -------------------------------------------------------------------------------- 1 | /** 2 | *@author Arkadip Bhattacharya 3 | *@fileoverview Sign In functionality 4 | *@copyright Arkadip Bhattacharya 2020 5 | *@license Apache-2.0 6 | * 7 | * Copyright 2020 Arkadip Bhattacharya 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | */ 21 | 22 | import * as React from 'react'; 23 | import AuthContext from '../AuthContext'; 24 | import {signInFunctionParams} from '../types'; 25 | import {doSignIn} from '../utils/reducers'; 26 | 27 | /** 28 | *@function 29 | *@name useSignIn 30 | *@description Authentication SignIn Hook 31 | *@returns - Sign In function 32 | */ 33 | function useSignIn(): (signInConfig: signInFunctionParams) => boolean { 34 | const context = React.useContext(AuthContext); 35 | if (context === null) { 36 | throw new 37 | Error('Auth Provider is missing. ' + 38 | 'Please add the AuthProvider before Router'); 39 | } 40 | return (signInConfig: signInFunctionParams): boolean => { 41 | const { 42 | token, 43 | tokenType, 44 | authState, 45 | expiresIn, 46 | refreshToken, 47 | refreshTokenExpireIn, 48 | } = signInConfig; 49 | const expTime = new Date(new Date().getTime() + expiresIn * 60 * 1000); 50 | if (context.authState.isUsingRefreshToken) { 51 | // Using the power of refresh token 52 | if (!!refreshToken && !!refreshTokenExpireIn) { 53 | // refresh token params are provided 54 | // sign in with refresh token 55 | const refreshTokenExpireAt = 56 | new Date(new Date().getTime() + refreshTokenExpireIn * 60 * 1000); 57 | context.dispatch(doSignIn({ 58 | auth: { 59 | token: token, 60 | type: tokenType, 61 | expiresAt: expTime, 62 | }, 63 | userState: authState ? authState : null, 64 | refresh: { 65 | token: refreshToken, 66 | expiresAt: refreshTokenExpireAt, 67 | }, 68 | })); 69 | return true; 70 | } else { 71 | // refresh token params are not provided 72 | // throw an error 73 | throw new Error('Make sure you given "refreshToken" and ' + 74 | '"refreshTokenExpireIn" parameter'); 75 | } 76 | } else { 77 | // Not using refresh token 78 | if (!!refreshToken && !!refreshTokenExpireIn) { 79 | // params are not expected but provided 80 | // throw an error 81 | throw new Error('The app doesn\'t implement \'refreshToken\' ' + 82 | 'feature.\nSo you have to implement refresh token feature ' + 83 | 'from \'AuthProvider\' before using it.'); 84 | } else { 85 | // sign in without the refresh token 86 | context.dispatch(doSignIn({ 87 | auth: { 88 | token: token, 89 | type: tokenType, 90 | expiresAt: expTime, 91 | }, 92 | userState: authState ? authState : null, 93 | refresh: null, 94 | })); 95 | return true; 96 | } 97 | } 98 | }; 99 | } 100 | 101 | /** 102 | *@exports useSignIn 103 | */ 104 | export default useSignIn; 105 | -------------------------------------------------------------------------------- /src/hooks/useSignOut.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Arkadip Bhattacharya 3 | * @fileoverview Sign Out functionality 4 | * @copyright Arkadip Bhattacharya 2020 5 | * 6 | * Copyright 2020 Arkadip Bhattacharya 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | import * as React from 'react'; 22 | import AuthContext from '../AuthContext'; 23 | import {doSignOut} from '../utils/reducers'; 24 | 25 | /** 26 | *@public 27 | *@function 28 | *@name useSignOut 29 | *@description Sign out Hook 30 | */ 31 | function useSignOut(): () => (boolean) { 32 | /** 33 | *A constant c. 34 | *@kind constant 35 | */ 36 | const context = React.useContext(AuthContext); 37 | if (context === null) { 38 | throw new 39 | Error('Auth Provider is missing. ' + 40 | 'Please add the AuthProvider before Router'); 41 | } 42 | 43 | return () => { 44 | try { 45 | if (context) { 46 | context.dispatch(doSignOut()); 47 | return true; 48 | } else { 49 | return false; 50 | } 51 | } catch (e) { 52 | return false; 53 | } 54 | }; 55 | } 56 | /** 57 | *@exports useSignOut 58 | */ 59 | export default useSignOut; 60 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * last updated 25th August 2021 16 | */ 17 | 18 | import AuthProvider from './AuthProvider'; 19 | import createRefresh from './createRefresh'; 20 | import PrivateRoute from './PrivateRoute'; 21 | import useSignIn from './hooks/useSignIn'; 22 | import useSignOut from './hooks/useSignOut'; 23 | import useAuthUser from './hooks/useAuthUser'; 24 | import useAuthHeader from './hooks/useAuthHeader'; 25 | import useIsAuthenticated from './hooks/useIsAuthenticated'; 26 | import withSignIn from './higherOrderComponents/withSignIn'; 27 | import withSignOut from './higherOrderComponents/withSignOut'; 28 | import withAuthUser from './higherOrderComponents/withAuthUser'; 29 | import withAuthHeader from './higherOrderComponents/withAuthHeader'; 30 | import withIsAuthenticated from './higherOrderComponents/withIsAuthenticated'; 31 | 32 | // Default prop for AuthProvider 33 | AuthProvider.defaultProps = { 34 | cookieDomain: window.location.hostname, 35 | cookieSecure: window.location.protocol === 'https:', 36 | }; 37 | 38 | export { 39 | AuthProvider, 40 | PrivateRoute, 41 | createRefresh, 42 | useSignIn, 43 | useSignOut, 44 | useAuthUser, 45 | useAuthHeader, 46 | useIsAuthenticated, 47 | withSignIn, 48 | withSignOut, 49 | withAuthUser, 50 | withAuthHeader, 51 | withIsAuthenticated, 52 | }; 53 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Arkadip Bhattacharya 3 | * @fileoverview General types used in the library 4 | * @copyright Arkadip Bhattacharya 2020 5 | * 6 | * Copyright 2020 Arkadip Bhattacharya 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | import * as React from 'react'; 22 | import {AuthActions} from './utils/actions'; 23 | 24 | /** 25 | * Universal types 26 | */ 27 | export type AuthStateUserObject = { 28 | [x: string]: any; 29 | } 30 | 31 | export interface AuthKitStateInterface { 32 | auth: { 33 | token: string, 34 | type: string, 35 | expiresAt: Date 36 | } | null, 37 | refresh: { 38 | token: string, 39 | expiresAt: Date 40 | } | null, 41 | userState: AuthStateUserObject | null, 42 | isSignIn: boolean 43 | isUsingRefreshToken: boolean, 44 | // typeOfStorage: "cookie" | "localstorage" 45 | } 46 | 47 | /** 48 | * SignIn function param 49 | * Used by: useSignIn and withSignIn 50 | */ 51 | export interface signInFunctionParams { 52 | token: string 53 | tokenType: string | 'Bearer' 54 | expiresIn: number 55 | authState?: AuthStateUserObject 56 | refreshToken?: string 57 | refreshTokenExpireIn?: number 58 | } 59 | 60 | /** 61 | * Context values type 62 | */ 63 | export interface AuthContextInterface { 64 | authState: AuthKitStateInterface 65 | dispatch: React.Dispatch 66 | } 67 | 68 | /** 69 | * Auth Provider Props 70 | */ 71 | export interface AuthProviderProps { 72 | authType: 'cookie' | 'localstorage' 73 | authName: string, 74 | refresh?: createRefreshParamInterface 75 | cookieDomain?: string 76 | cookieSecure?: boolean 77 | children: React.ReactNode 78 | } 79 | 80 | /** 81 | * Refresh Token Callback Response 82 | */ 83 | export type RefreshTokenCallbackResponse = { 84 | isSuccess: boolean, 85 | newAuthToken: string, 86 | newAuthTokenExpireIn?: number | null, 87 | newRefreshToken?: string | null, 88 | newRefreshTokenExpiresIn?: number | null, 89 | newAuthUserState?: AuthStateUserObject | null, 90 | }; 91 | 92 | /** 93 | * Refresh Token types 94 | */ 95 | // Callback function 96 | 97 | export type refreshTokenCallback = (param: { 98 | authToken?: string, 99 | authTokenExpireAt?: Date, 100 | refreshToken?: string, 101 | refreshTokenExpiresAt?: Date, 102 | authUserState: AuthStateUserObject | null, 103 | }) => Promise 104 | 105 | // createRefresh function parameter 106 | export interface createRefreshParamInterface { 107 | interval: number, 108 | refreshApiCallback: refreshTokenCallback 109 | } 110 | 111 | export type refreshFunctionType = (param: createRefreshParamInterface) 112 | => createRefreshParamInterface 113 | -------------------------------------------------------------------------------- /src/utils/actions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Arkadip Bhattacharya 3 | * @fileoverview Actions for useReducer 4 | * @copyright Arkadip Bhattacharya 2020 5 | * 6 | * Copyright 2020 Arkadip Bhattacharya 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | import {AuthStateUserObject} from '../types'; 22 | 23 | export enum ActionType { 24 | SignIn, 25 | SignOut, 26 | RefreshToken 27 | } 28 | 29 | export interface SignInActionPayload { 30 | auth: { 31 | token: string, 32 | type: string, 33 | expiresAt: Date 34 | }, 35 | refresh: { 36 | token: string, 37 | expiresAt: Date 38 | } | null, 39 | userState: AuthStateUserObject | null, 40 | } 41 | 42 | export interface RefreshTokenActionPayload { 43 | newAuthToken: string | null, 44 | newAuthTokenExpireIn?: number | null, 45 | newRefreshToken?: string | null, 46 | newRefreshTokenExpiresIn?: number | null, 47 | newAuthUserState?: AuthStateUserObject | null 48 | } 49 | 50 | export interface SignInAction { 51 | type: ActionType.SignIn, 52 | payload: SignInActionPayload 53 | } 54 | 55 | export interface RefreshTokenAction { 56 | type: ActionType.RefreshToken, 57 | payload: RefreshTokenActionPayload 58 | } 59 | 60 | export interface SignOutAction { 61 | type: ActionType.SignOut; 62 | } 63 | 64 | export type AuthActions = SignInAction | SignOutAction | RefreshTokenAction 65 | -------------------------------------------------------------------------------- /src/utils/hooks.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Arkadip Bhattacharya 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import * as React from 'react'; 18 | 19 | /** 20 | * React useInterval Hook 21 | * Used to integrate the power of setInterval seamlessly 22 | * 23 | * @param callback - The callback function 24 | * @param delay - The amount of delay in minutes. 25 | * 26 | * @returns the ref of setInterval 27 | */ 28 | function useInterval(callback: ()=>void, delay:number|null) 29 | : React.MutableRefObject { 30 | const savedCallback = React.useRef(callback); 31 | const intervalRef = React.useRef(null); 32 | 33 | // Remember the latest callback if it changes. 34 | React.useEffect(() => { 35 | savedCallback.current = callback; 36 | }, [callback]); 37 | 38 | // Set up the interval. 39 | React.useEffect(() => { 40 | const tick = () => savedCallback.current(); 41 | 42 | if (typeof delay === 'number') { 43 | intervalRef.current = window.setInterval(tick, delay * 60 * 1000); 44 | } 45 | 46 | return () => { 47 | if (intervalRef.current) { 48 | window.clearTimeout(intervalRef.current); 49 | } 50 | }; 51 | }, [delay]); 52 | 53 | return intervalRef; 54 | } 55 | 56 | export {useInterval}; 57 | -------------------------------------------------------------------------------- /src/utils/reducers.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Arkadip Bhattacharya 3 | * @fileoverview Reducers for useReducer 4 | * @copyright Arkadip Bhattacharya 2020 5 | * 6 | * Copyright 2020 Arkadip Bhattacharya 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | import {AuthKitStateInterface} from '../types'; 21 | import { 22 | ActionType, 23 | AuthActions, 24 | SignInAction, 25 | SignInActionPayload, 26 | SignOutAction, 27 | RefreshTokenAction, 28 | RefreshTokenActionPayload, 29 | } from './actions'; 30 | 31 | /** 32 | * Auth Reducer 33 | * Used in auth state 34 | * @param state 35 | * @param action 36 | */ 37 | export function authReducer(state: AuthKitStateInterface, 38 | action: AuthActions) 39 | : AuthKitStateInterface { 40 | switch (action.type) { 41 | case ActionType.SignIn: 42 | return { 43 | ...state, 44 | auth: action.payload.auth, 45 | refresh: action.payload.refresh, 46 | userState: action.payload.userState, 47 | isSignIn: true, 48 | }; 49 | case ActionType.SignOut: 50 | return { 51 | ...state, 52 | auth: null, 53 | refresh: null, 54 | userState: null, 55 | isSignIn: false, 56 | }; 57 | case ActionType.RefreshToken: 58 | if (state.isSignIn && state.auth && state.refresh) { 59 | return { 60 | ...state, 61 | auth: { 62 | token: action.payload.newAuthToken ? 63 | action.payload.newAuthToken : state.auth.token, 64 | type: state.auth.type, 65 | expiresAt: action.payload.newAuthTokenExpireIn ? 66 | new Date(new Date().getTime() + 67 | action.payload.newAuthTokenExpireIn * 60 * 1000) : 68 | state.auth.expiresAt, 69 | }, 70 | refresh: { 71 | token: action.payload.newRefreshToken ? 72 | action.payload.newRefreshToken : state.refresh.token, 73 | expiresAt: action.payload.newRefreshTokenExpiresIn ? 74 | new Date(new Date().getTime() + 75 | action.payload.newRefreshTokenExpiresIn * 60 * 1000) : 76 | state.refresh.expiresAt, 77 | }, 78 | userState: action.payload.newAuthUserState ? 79 | action.payload.newAuthUserState : state.userState, 80 | }; 81 | } else { 82 | return state; 83 | } 84 | } 85 | } 86 | 87 | // Helper functions 88 | /** 89 | * used to make sign in 90 | * @param signInParams 91 | */ 92 | export function doSignIn(signInParams: SignInActionPayload): SignInAction { 93 | return ({ 94 | type: ActionType.SignIn, 95 | payload: signInParams, 96 | }); 97 | } 98 | 99 | /** 100 | * used to refresh the Token 101 | * @param refreshTokenParam 102 | */ 103 | export function doRefresh(refreshTokenParam: RefreshTokenActionPayload): 104 | RefreshTokenAction { 105 | return ({ 106 | type: ActionType.RefreshToken, 107 | payload: refreshTokenParam, 108 | }); 109 | } 110 | 111 | /** 112 | * Used to make sign out 113 | */ 114 | export function doSignOut(): SignOutAction { 115 | return ({ 116 | type: ActionType.SignOut, 117 | }); 118 | } 119 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "declarationDir": "./types", 5 | "sourceMap": true, 6 | "module": "ESNext", 7 | "outDir": "./dist", 8 | "target": "ES5", 9 | "lib": [ 10 | "dom", 11 | "es6" 12 | ], 13 | "moduleResolution": "Node", 14 | "jsx": "react", 15 | "esModuleInterop": true, 16 | "noImplicitReturns": true, 17 | "noImplicitThis": true, 18 | "noImplicitAny": true, 19 | "strictNullChecks": true, 20 | "suppressImplicitAnyIndexErrors": true, 21 | "noUnusedLocals": true, 22 | "noUnusedParameters": true, 23 | "allowSyntheticDefaultImports": true, 24 | "allowJs": true, 25 | "strict": true, 26 | "forceConsistentCasingInFileNames": true, 27 | "resolveJsonModule": true, 28 | "isolatedModules": true, 29 | "noEmit": false 30 | }, 31 | "include": [ 32 | "src/**/*.ts", 33 | "src/**/*.tsx" 34 | ], 35 | "exclude": [ 36 | "node_modules", 37 | "dist", 38 | "types" 39 | ] 40 | } 41 | --------------------------------------------------------------------------------