├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── 1-bug-report.yml │ ├── 2-feature-request.yml │ └── 3-doc-issue.yml └── workflows │ ├── ci_demo-apps.yml │ ├── ci_release.yml │ ├── ci_test_auth-js.yml │ ├── ci_test_auth-vue.yml │ ├── ci_test_ngx-auth.yml │ └── ci_website.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .prettierignore ├── .prettierrc ├── .vscode ├── extensions.json └── settings.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── DEVELOPER.md ├── LICENSE ├── README.md ├── apps ├── demo-app │ ├── capacitor │ │ ├── android │ │ │ ├── .gitignore │ │ │ ├── .idea │ │ │ │ ├── .gitignore │ │ │ │ ├── compiler.xml │ │ │ │ ├── deploymentTargetDropDown.xml │ │ │ │ ├── jarRepositories.xml │ │ │ │ └── misc.xml │ │ │ ├── app │ │ │ │ ├── .gitignore │ │ │ │ ├── build.gradle │ │ │ │ ├── capacitor.build.gradle │ │ │ │ ├── proguard-rules.pro │ │ │ │ └── src │ │ │ │ │ ├── androidTest │ │ │ │ │ └── java │ │ │ │ │ │ └── com │ │ │ │ │ │ └── getcapacitor │ │ │ │ │ │ └── myapp │ │ │ │ │ │ └── ExampleInstrumentedTest.java │ │ │ │ │ ├── main │ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ │ ├── assets │ │ │ │ │ │ ├── capacitor.config.json │ │ │ │ │ │ └── capacitor.plugins.json │ │ │ │ │ ├── java │ │ │ │ │ │ └── demoapp │ │ │ │ │ │ │ └── authjs │ │ │ │ │ │ │ └── MainActivity.java │ │ │ │ │ └── res │ │ │ │ │ │ ├── drawable-land-hdpi │ │ │ │ │ │ └── splash.png │ │ │ │ │ │ ├── drawable-land-mdpi │ │ │ │ │ │ └── splash.png │ │ │ │ │ │ ├── drawable-land-xhdpi │ │ │ │ │ │ └── splash.png │ │ │ │ │ │ ├── drawable-land-xxhdpi │ │ │ │ │ │ └── splash.png │ │ │ │ │ │ ├── drawable-land-xxxhdpi │ │ │ │ │ │ └── splash.png │ │ │ │ │ │ ├── drawable-port-hdpi │ │ │ │ │ │ └── splash.png │ │ │ │ │ │ ├── drawable-port-mdpi │ │ │ │ │ │ └── splash.png │ │ │ │ │ │ ├── drawable-port-xhdpi │ │ │ │ │ │ └── splash.png │ │ │ │ │ │ ├── drawable-port-xxhdpi │ │ │ │ │ │ └── splash.png │ │ │ │ │ │ ├── drawable-port-xxxhdpi │ │ │ │ │ │ └── splash.png │ │ │ │ │ │ ├── drawable-v24 │ │ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ │ │ ├── drawable │ │ │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ │ │ └── splash.png │ │ │ │ │ │ ├── layout │ │ │ │ │ │ └── activity_main.xml │ │ │ │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ │ │ ├── ic_launcher.xml │ │ │ │ │ │ └── ic_launcher_round.xml │ │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ │ ├── values │ │ │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ │ │ ├── strings.xml │ │ │ │ │ │ └── styles.xml │ │ │ │ │ │ └── xml │ │ │ │ │ │ ├── config.xml │ │ │ │ │ │ └── file_paths.xml │ │ │ │ │ └── test │ │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── getcapacitor │ │ │ │ │ └── myapp │ │ │ │ │ └── ExampleUnitTest.java │ │ │ ├── build.gradle │ │ │ ├── capacitor.settings.gradle │ │ │ ├── gradle.properties │ │ │ ├── gradle │ │ │ │ └── wrapper │ │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ │ └── gradle-wrapper.properties │ │ │ ├── gradlew │ │ │ ├── gradlew.bat │ │ │ ├── settings.gradle │ │ │ └── variables.gradle │ │ ├── capacitor.config.ts │ │ ├── ios │ │ │ ├── .gitignore │ │ │ └── App │ │ │ │ ├── App.xcodeproj │ │ │ │ ├── project.pbxproj │ │ │ │ └── project.xcworkspace │ │ │ │ │ └── contents.xcworkspacedata │ │ │ │ ├── App.xcworkspace │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata │ │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ │ ├── App │ │ │ │ ├── AppDelegate.swift │ │ │ │ ├── Assets.xcassets │ │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ │ ├── AppIcon-512@2x.png │ │ │ │ │ │ └── Contents.json │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Splash.imageset │ │ │ │ │ │ ├── Contents.json │ │ │ │ │ │ ├── splash-2732x2732-1.png │ │ │ │ │ │ ├── splash-2732x2732-2.png │ │ │ │ │ │ └── splash-2732x2732.png │ │ │ │ ├── Base.lproj │ │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ │ └── Main.storyboard │ │ │ │ ├── Info.plist │ │ │ │ ├── capacitor.config.json │ │ │ │ └── config.xml │ │ │ │ ├── Podfile │ │ │ │ └── Podfile.lock │ │ └── package.json │ └── web │ │ ├── auth-js │ │ ├── .babelrc │ │ ├── project.json │ │ ├── src │ │ │ ├── app │ │ │ │ └── app.element.ts │ │ │ ├── environments │ │ │ │ ├── environment.prod.ts │ │ │ │ └── environment.ts │ │ │ ├── favicon.ico │ │ │ ├── index.html │ │ │ ├── main.ts │ │ │ └── styles.scss │ │ ├── tsconfig.app.json │ │ ├── tsconfig.json │ │ └── webpack.config.js │ │ ├── auth-vue │ │ ├── index.html │ │ ├── project.json │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── App.vue │ │ │ ├── main.ts │ │ │ ├── router │ │ │ │ └── index.ts │ │ │ ├── shims-vue.d.ts │ │ │ ├── styles.scss │ │ │ └── views │ │ │ │ ├── DemoView.vue │ │ │ │ └── PageView.vue │ │ ├── tsconfig.app.json │ │ ├── tsconfig.json │ │ └── vite.config.mjs │ │ ├── common │ │ ├── components │ │ │ ├── demo-app-debug.element.ts │ │ │ ├── demo-app-header.element.ts │ │ │ ├── demo-app-main.element.ts │ │ │ ├── demo-app-playground.element.ts │ │ │ └── demo-app-settings.element.ts │ │ ├── core │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── jest.config.ts │ │ ├── project.json │ │ ├── settings │ │ │ ├── default-settings.ts │ │ │ ├── demo-app-settings.service.ts │ │ │ ├── index.ts │ │ │ └── library-settings-definition.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.lib.json │ │ └── tsconfig.spec.json │ │ ├── ngx-auth │ │ ├── .browserslistrc │ │ ├── project.json │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app │ │ │ │ ├── app.component.html │ │ │ │ ├── app.component.ts │ │ │ │ ├── app.config.ts │ │ │ │ ├── app.module.ts │ │ │ │ ├── app.routes.ts │ │ │ │ └── demo │ │ │ │ │ ├── components │ │ │ │ │ └── page │ │ │ │ │ │ ├── page.component.html │ │ │ │ │ │ ├── page.component.scss │ │ │ │ │ │ └── page.component.ts │ │ │ │ │ ├── demo.component.html │ │ │ │ │ ├── demo.component.ts │ │ │ │ │ └── demo.routes.ts │ │ │ ├── index.html │ │ │ ├── main.ts │ │ │ └── styles.scss │ │ ├── tsconfig.app.json │ │ ├── tsconfig.editor.json │ │ └── tsconfig.json │ │ └── package.json ├── demo-e2e │ ├── package.json │ ├── src │ │ ├── pageobjects │ │ │ ├── demo.page.ts │ │ │ ├── idp-page.model.ts │ │ │ └── keycloak.page.ts │ │ ├── polyfills │ │ │ └── puppeteer.ts │ │ └── specs │ │ │ └── oidc │ │ │ └── redirect.e2e.ts │ ├── tsconfig.json │ └── wdio.config.ts ├── demo-idp │ ├── demo-realm.json │ ├── docker-compose.yml │ ├── export-demo-realm.sh │ └── package.json └── website │ ├── .gitignore │ ├── docs │ ├── api │ │ ├── angular │ │ │ ├── auth-guard.md │ │ │ ├── auth-interceptor.md │ │ │ └── auth-service.md │ │ ├── mobile.md │ │ └── vanilla-js │ │ │ └── auth-manager.md │ ├── getting-started │ │ ├── angular.mdx │ │ ├── configuration.mdx │ │ ├── intro.md │ │ ├── mobile.mdx │ │ ├── playground.md │ │ ├── providers.mdx │ │ ├── usage.md │ │ ├── vanilla-js.mdx │ │ └── vue-js.mdx │ └── guides │ │ └── guides.md │ ├── docusaurus.config.js │ ├── package.json │ ├── sidebars.js │ ├── src │ ├── components │ │ ├── Features.tsx │ │ ├── Frameworks.tsx │ │ └── Intro.tsx │ ├── css │ │ ├── custom.css │ │ ├── home.css │ │ ├── not-found.css │ │ └── search.css │ ├── pages │ │ └── index.tsx │ └── theme │ │ ├── Navbar │ │ └── index.tsx │ │ └── NotFound │ │ └── Content.tsx │ ├── static │ ├── .nojekyll │ └── assets │ │ ├── favicon.ico │ │ └── svg │ │ ├── 404.svg │ │ ├── angular.svg │ │ ├── code.svg │ │ ├── globe.svg │ │ ├── hexagons.svg │ │ ├── javascript.svg │ │ ├── logo.svg │ │ ├── puzzle.svg │ │ ├── shield-check.svg │ │ ├── shield.svg │ │ ├── smartphone.svg │ │ ├── thumbs-up.svg │ │ └── vue-js.svg │ └── tsconfig.json ├── eslint.config.mjs ├── jest.config.ts ├── jest.preset.js ├── libs ├── auth-js │ ├── @types │ │ └── mobile │ │ │ └── index.d.ts │ ├── CHANGELOG.md │ ├── README.md │ ├── build.mjs │ ├── core │ │ ├── auth-logger.ts │ │ ├── auth-manager.ts │ │ ├── auth-subscriptions.ts │ │ ├── auth-utils.ts │ │ ├── index.spec.ts │ │ ├── index.ts │ │ ├── main.ts │ │ └── models │ │ │ ├── auth-guard-options.model.ts │ │ │ ├── auth-guard-validator.model.ts │ │ │ ├── auth-settings.model.ts │ │ │ ├── auth-subscriber-options.model.ts │ │ │ ├── auth-subscriber.model.ts │ │ │ └── auth-subscription.model.ts │ ├── index.ts │ ├── jest.config.ts │ ├── oidc │ │ ├── assets │ │ │ ├── popup_redirect.html │ │ │ └── silent_redirect.html │ │ ├── default-settings.ts │ │ ├── index.ts │ │ ├── main.ts │ │ ├── mobile │ │ │ ├── mobile-navigator.ts │ │ │ ├── mobile-storage.ts │ │ │ └── mobile-window.ts │ │ ├── models │ │ │ ├── access-token.model.ts │ │ │ ├── args.model.ts │ │ │ ├── default-settings.model.ts │ │ │ ├── desktop-navigation.enum.ts │ │ │ ├── id-token.model.ts │ │ │ ├── inject-token-pattern.model.ts │ │ │ ├── inject-token.model.ts │ │ │ ├── mobile-window-params.model.ts │ │ │ ├── oidc-auth-settings.model.ts │ │ │ └── user-session.model.ts │ │ ├── oidc-auth-guard.ts │ │ ├── oidc-auth-interceptor.ts │ │ ├── oidc-auth-manager.ts │ │ ├── oidc-auth-service.ts │ │ └── oidc-user-manager.ts │ ├── package.json │ ├── project.json │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── auth-vue │ ├── CHANGELOG.md │ ├── README.md │ ├── build.mjs │ ├── core │ │ ├── auth.guard.ts │ │ ├── auth.provider.ts │ │ ├── auth.service.ts │ │ └── index.ts │ ├── index.ts │ ├── package.json │ ├── project.json │ ├── tsconfig.json │ └── tsconfig.lib.json └── ngx-auth │ ├── CHANGELOG.md │ ├── README.md │ ├── core │ ├── auth.guard.ts │ ├── auth.provider.ts │ ├── auth.service.ts │ └── index.ts │ ├── image │ ├── auth-image.component.ts │ ├── index.ts │ └── ng-package.json │ ├── index.ts │ ├── jest.config.ts │ ├── ng-package.json │ ├── package.json │ ├── project.json │ ├── schematics │ ├── collection.json │ ├── ng-add │ │ ├── index.ts │ │ ├── ng-add-options.ts │ │ ├── ng-add.spec.ts │ │ └── schema.json │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.spec.json │ └── utils.ts │ ├── test-setup.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ └── tsconfig.spec.json ├── nx.json ├── package-lock.json ├── package.json ├── patches └── nx+21.2.2.patch ├── scripts ├── build-lib.mjs └── release.mjs ├── tsconfig.base.json └── tsconfig.strict.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 4 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.ts] 13 | quote_type = single 14 | 15 | [*.md] 16 | max_line_length = off 17 | trim_trailing_whitespace = false 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-bug-report.yml: -------------------------------------------------------------------------------- 1 | name: 🐞 Bug report 2 | description: Report a bug in the library 3 | title: '[BUG] ' 4 | labels: [bug, needs triage] 5 | 6 | body: 7 | - type: checkboxes 8 | attributes: 9 | label: Is there an existing issue for this? 10 | description: | 11 | Please search open and closed issues before submitting a new one. 12 | Existing issues often contain information about workarounds, resolution or progress updates. 13 | options: 14 | - label: I have searched the existing issues 15 | required: true 16 | 17 | - type: input 18 | attributes: 19 | label: Library version 20 | description: Please make sure you have installed the latest version and verified it is still an issue. 21 | placeholder: latest 22 | validations: 23 | required: true 24 | 25 | - type: textarea 26 | attributes: 27 | label: Description 28 | description: A clear & concise description of what you're experiencing. 29 | validations: 30 | required: true 31 | 32 | - type: textarea 33 | attributes: 34 | label: Steps to reproduce 35 | description: | 36 | Issues that don't have enough info and can't be reproduced will be closed. 37 | Please provide the steps to reproduce the behavior and if applicable create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) 38 | in a [new repository](https://github.com/new), a [gist](https://gist.github.com) or a [live demo](https://stackblitz.com). 39 | validations: 40 | required: false 41 | 42 | - type: textarea 43 | attributes: 44 | label: Environment 45 | description: | 46 | examples: 47 | - **OS Name**: macOS Monterey (version 12.6.1) 48 | - **System Model Name**: MacBook Pro (16-inch, 2019) 49 | - **npm**: **`npm -v`**: 7.6.3 50 | - **Node.js**: **`node -v`**: 13.14.0 51 | value: | 52 | - **OS Name**: 53 | - **System Model Name**: 54 | - **npm**: 55 | - **Node.js**: 56 | validations: 57 | required: false 58 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-feature-request.yml: -------------------------------------------------------------------------------- 1 | name: 🚀 Feature request 2 | description: Suggest a feature for the library 3 | title: '[FEATURE] <title>' 4 | labels: [enhancement, needs triage] 5 | 6 | body: 7 | - type: textarea 8 | attributes: 9 | label: Description 10 | description: A clear and concise description of the problem or missing capability. 11 | validations: 12 | required: true 13 | 14 | - type: textarea 15 | attributes: 16 | label: Proposed solution 17 | description: If you have a solution in mind, please describe it. 18 | validations: 19 | required: true 20 | 21 | - type: textarea 22 | attributes: 23 | label: Alternatives considered 24 | description: Have you considered any alternative solutions or workarounds? 25 | validations: 26 | required: false 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/3-doc-issue.yml: -------------------------------------------------------------------------------- 1 | name: 📚 Docs enhancement 2 | description: File an enhancement or report an issue in the library's documentation 3 | title: '[DOCS] <title>' 4 | labels: [documentation, needs triage] 5 | 6 | body: 7 | - type: checkboxes 8 | attributes: 9 | label: Documentation can be submitted with pull requests 10 | options: 11 | - label: I know that I can edit the docs myself but prefer to file this issue instead 12 | required: true 13 | 14 | - type: input 15 | attributes: 16 | label: Docs URL 17 | description: The URL of the page you'd like to see an enhancement to or report a problem from. 18 | validations: 19 | required: false 20 | 21 | - type: textarea 22 | attributes: 23 | label: Description 24 | description: A clear and concise description of the enhancement or problem. 25 | validations: 26 | required: true 27 | -------------------------------------------------------------------------------- /.github/workflows/ci_demo-apps.yml: -------------------------------------------------------------------------------- 1 | name: Deploy demo-apps 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | tags-ignore: 9 | - '**' 10 | paths: 11 | - '.github/workflows/ci_demo-apps.yml' 12 | - 'apps/demo-app/**' 13 | - 'libs/**' 14 | 15 | env: 16 | HUSKY: 0 17 | 18 | concurrency: 19 | group: deploy-demo-apps-group-${{ github.ref }} 20 | cancel-in-progress: true 21 | 22 | jobs: 23 | ci_demo-apps: 24 | runs-on: ubuntu-latest 25 | steps: 26 | - name: Setup 27 | uses: badisi/actions/setup@v2 28 | 29 | - name: Build demo-app:auth-js 30 | working-directory: apps/demo-app/web 31 | env: 32 | BASE_URL: /${{ github.event.repository.name }}/demo-app/auth-js/ 33 | run: npm run build:auth-js -- --base-href=${{ env.BASE_URL }} --deploy-url=${{ env.BASE_URL }} 34 | 35 | - name: Build demo-app:ngx-auth 36 | working-directory: apps/demo-app/web 37 | env: 38 | BASE_URL: /${{ github.event.repository.name }}/demo-app/ngx-auth/ 39 | run: npm run build:ngx-auth -- --base-href=${{ env.BASE_URL }} --deploy-url=${{ env.BASE_URL }} 40 | 41 | - name: Build demo-app:auth-vue 42 | working-directory: apps/demo-app/web 43 | env: 44 | BASE_URL: /${{ github.event.repository.name }}/demo-app/auth-vue/ 45 | run: npm run build:auth-vue 46 | 47 | - name: Deploy to GitHub Pages 48 | uses: peaceiris/actions-gh-pages@v4 49 | with: 50 | commit_message: 'deploy(demo-apps):' 51 | github_token: ${{ secrets.GITHUB_TOKEN }} 52 | publish_dir: ./dist/demo-app 53 | destination_dir: demo-app 54 | -------------------------------------------------------------------------------- /.github/workflows/ci_release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | run-name: Release ${{ inputs.package }}${{ inputs.dry-run && ' (dry-run)' || '' }} 3 | 4 | on: 5 | workflow_dispatch: 6 | inputs: 7 | package: 8 | description: Package 9 | required: true 10 | type: choice 11 | options: 12 | - -- all -- 13 | - auth-js 14 | - ngx-auth 15 | - auth-vue 16 | dry-run: 17 | description: --dry-run 18 | type: boolean 19 | default: false 20 | 21 | env: 22 | HUSKY: 0 23 | FORCE_COLOR: 3 24 | 25 | jobs: 26 | ci_release: 27 | uses: badisi/actions/.github/workflows/action.yml@v2 28 | secrets: 29 | GIT_USER_NAME: ${{ github.actor }} 30 | GIT_USER_EMAIL: ${{ github.actor }}@users.noreply.github.com 31 | GH_TOKEN: ${{ secrets.AUTH_JS_GITHUB_TOKEN }} 32 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 33 | with: 34 | working-directory: ${{ (inputs.package == '-- all --') && '.' || format('libs/{0}', inputs.package) }} 35 | dry-run: ${{ inputs.dry-run }} 36 | lint: true 37 | test: true 38 | build: true 39 | release: true 40 | -------------------------------------------------------------------------------- /.github/workflows/ci_test_auth-js.yml: -------------------------------------------------------------------------------- 1 | name: Test auth-js 2 | 3 | on: 4 | workflow_dispatch: 5 | repository_dispatch: 6 | types: [test_auth-js] 7 | push: 8 | branches: 9 | - '**' 10 | tags-ignore: 11 | - '**' 12 | paths: 13 | - '.github/workflows/ci_test_auth-js.yml' 14 | - 'libs/auth-js/**' 15 | 16 | env: 17 | HUSKY: 0 18 | 19 | concurrency: 20 | group: ci-test-auth-js-group-${{ github.ref }} 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | ci_test_auth-js: 25 | uses: badisi/actions/.github/workflows/action.yml@v2 26 | with: 27 | working-directory: libs/auth-js 28 | runs-on: '["ubuntu-latest", "macos-latest", "windows-latest"]' 29 | node-versions: '[22]' 30 | lint: true 31 | test: true 32 | 33 | ci_test_deps: 34 | needs: ci_test_auth-js 35 | runs-on: 'ubuntu-latest' 36 | steps: 37 | - name: Test ngx-auth 38 | uses: peter-evans/repository-dispatch@v3 39 | with: 40 | event-type: test_ngx-auth 41 | 42 | - name: Test auth-vue 43 | uses: peter-evans/repository-dispatch@v3 44 | with: 45 | event-type: test_auth-vue 46 | -------------------------------------------------------------------------------- /.github/workflows/ci_test_auth-vue.yml: -------------------------------------------------------------------------------- 1 | name: Test auth-vue 2 | 3 | on: 4 | workflow_dispatch: 5 | repository_dispatch: 6 | types: [test_auth-vue] 7 | push: 8 | branches: 9 | - '**' 10 | tags-ignore: 11 | - '**' 12 | paths: 13 | - '.github/workflows/ci_test_auth-vue.yml' 14 | - 'libs/auth-vue/**' 15 | 16 | env: 17 | HUSKY: 0 18 | 19 | concurrency: 20 | group: ci-test-auth-vue-group-${{ github.ref }} 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | ci_test_auth-vue: 25 | uses: badisi/actions/.github/workflows/action.yml@v2 26 | with: 27 | working-directory: libs/auth-vue 28 | runs-on: '["ubuntu-latest", "macos-latest", "windows-latest"]' 29 | node-versions: '[22]' 30 | lint: true 31 | test: true 32 | -------------------------------------------------------------------------------- /.github/workflows/ci_test_ngx-auth.yml: -------------------------------------------------------------------------------- 1 | name: Test ngx-auth 2 | 3 | on: 4 | workflow_dispatch: 5 | repository_dispatch: 6 | types: [test_ngx-auth] 7 | push: 8 | branches: 9 | - '**' 10 | tags-ignore: 11 | - '**' 12 | paths: 13 | - '.github/workflows/ci_test_ngx-auth.yml' 14 | - 'libs/ngx-auth/**' 15 | 16 | env: 17 | HUSKY: 0 18 | 19 | concurrency: 20 | group: ci-test-ngx-auth-group-${{ github.ref }} 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | ci_test_ngx-auth: 25 | uses: badisi/actions/.github/workflows/action.yml@v2 26 | with: 27 | working-directory: libs/ngx-auth 28 | runs-on: '["ubuntu-latest", "macos-latest", "windows-latest"]' 29 | node-versions: '[22]' 30 | lint: true 31 | test: true 32 | -------------------------------------------------------------------------------- /.github/workflows/ci_website.yml: -------------------------------------------------------------------------------- 1 | name: Deploy website 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | tags-ignore: 9 | - '**' 10 | paths: 11 | - '.github/workflows/ci_website.yml' 12 | - 'apps/website/**' 13 | 14 | env: 15 | HUSKY: 0 16 | 17 | concurrency: 18 | group: deploy-site-group-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | jobs: 22 | ci_site: 23 | runs-on: ubuntu-latest 24 | steps: 25 | - name: Setup 26 | uses: badisi/actions/setup@v2 27 | 28 | - name: Build website 29 | working-directory: apps/website 30 | run: npm run build 31 | 32 | # 33 | # We do not use "peaceiris/actions-gh-page" action here as it wipes out 34 | # the whole repo and we don't want to lose the demo-app folder. 35 | # 36 | - name: Deploy to GitHub Pages 37 | run: | 38 | export TMP_WORKDIR="${{ runner.temp }}/gh-pages" 39 | rm -rf "$TMP_WORKDIR" 40 | mkdir -p "$TMP_WORKDIR" 41 | cd "$TMP_WORKDIR" 42 | git clone --depth=1 --single-branch --branch gh-pages "${{ github.server_url }}/${{ github.repository }}.git" . 43 | find . -mindepth 1 ! -path './demo-app*' ! -path './.gitignore' ! -path './.git*' -exec rm -rf {} + 44 | cp -r "${{ github.workspace }}/dist/website"/. "$TMP_WORKDIR/" 45 | git add . 46 | git config user.name "${{ github.actor }}" 47 | git config user.email "${{ github.actor }}@users.noreply.github.com" 48 | git commit -m "deploy(website): ${{ github.sha }}" || echo "No changes to commit" 49 | git push https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git gh-pages 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | dist 5 | tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | 41 | .nx/cache 42 | .nx/workspace-data 43 | 44 | .angular 45 | 46 | vite.config.*.timestamp* 47 | .cursor/rules/nx-rules.mdc 48 | .github/instructions/nx.instructions.md 49 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | printf "> Validating commit message... " 2 | npx --no -- commitlint --edit "$1" 3 | printf "OK\n" 4 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | printf "> Linting staged files... " 2 | npx --no -- lint-staged --quiet 3 | printf "OK\n" 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .angular 2 | .git 3 | .nx 4 | .docusaurus 5 | node_modules 6 | dist 7 | capacitor 8 | package-lock.json 9 | 10 | **/*.mdx 11 | **/*.md 12 | **/*.ts 13 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/prettierrc.json", 3 | "plugins": [ 4 | "prettier-plugin-multiline-arrays" 5 | ], 6 | "multilineArraysWrapThreshold": 1, 7 | "singleQuote": true, 8 | "bracketSameLine": true, 9 | "tabWidth": 4, 10 | "printWidth": 80, 11 | "endOfLine": "auto", 12 | "trailingComma": "none", 13 | "arrowParens": "avoid", 14 | "htmlWhitespaceSensitivity": "ignore", 15 | "proseWrap": "never" 16 | } 17 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "esbenp.prettier-vscode", 4 | "dbaeumer.vscode-eslint", 5 | "angular.ng-template", 6 | "sibiraj-s.vscode-scss-formatter", 7 | "pkief.material-icon-theme" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.eol": "\n", 3 | "files.watcherExclude": { 4 | "**/dist/**": true, 5 | "**/tmp/**": true 6 | }, 7 | "search.exclude": { 8 | "**/node_modules": true, 9 | "**/dist": true, 10 | "**/tmp": true 11 | }, 12 | "workbench.iconTheme": "material-icon-theme", 13 | "material-icon-theme.folders.theme": "none", 14 | "material-icon-theme.opacity": 0.6, 15 | "[javascript]": { 16 | "editor.defaultFormatter": "esbenp.prettier-vscode" 17 | }, 18 | "[typescript]": { 19 | "editor.defaultFormatter": "dbaeumer.vscode-eslint" 20 | }, 21 | "[html]": { 22 | "editor.defaultFormatter": "esbenp.prettier-vscode" 23 | }, 24 | "[scss]": { 25 | "editor.defaultFormatter": "esbenp.prettier-vscode" 26 | }, 27 | "[css]": { 28 | "editor.defaultFormatter": "esbenp.prettier-vscode" 29 | }, 30 | "[json]": { 31 | "editor.defaultFormatter": "esbenp.prettier-vscode" 32 | }, 33 | "[jsonc]": { 34 | "editor.defaultFormatter": "esbenp.prettier-vscode" 35 | }, 36 | "editor.codeActionsOnSave": { 37 | "source.fixAll.eslint": "explicit" 38 | }, 39 | "editor.formatOnSave": true, 40 | "eslint.format.enable": true, 41 | "html.format.wrapAttributes": "force-aligned", 42 | "html.format.wrapLineLength": 120, 43 | "npm.exclude": "**/{dist,tmp}{,/**}", 44 | "npm.packageManager": "npm", 45 | "npm.scriptExplorerExclude": [ 46 | "install", 47 | "prepare" 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /DEVELOPER.md: -------------------------------------------------------------------------------- 1 | # Development 2 | 3 | This document describes how you can test, build and publish the library. 4 | 5 | ## Prerequisite 6 | 7 | Before you can build and test this library you must install and configure the following products on your development machine: 8 | 9 | * [Node.js][nodejs] 10 | * [Git][git] 11 | 12 | You will then need to install the library required dependencies: 13 | 14 | ```sh 15 | cd <library-path> 16 | npm install 17 | ``` 18 | 19 | ## Testing locally 20 | 21 | You can test the library while developing it, as follow: 22 | 23 | 1. Start the testing application 24 | 25 | ```sh 26 | npm start 27 | ``` 28 | 29 | 2. Make any modifications 30 | 31 | * to the **library**: in `libs/library/src/` 32 | * to the **testing application**: in `libs/tests-app/src/` 33 | * to the **tests**: in `libs/tests/harness.e2e.ts` 34 | 35 | 3. Run the test 36 | 37 | ```sh 38 | npm run test 39 | ``` 40 | 41 | ## Building the library 42 | 43 | The library will be built in the `./dist` directory. 44 | 45 | ```sh 46 | npm run build:lib 47 | ``` 48 | 49 | ## Publishing to NPM repository 50 | 51 | This project comes with automatic continuous delivery (CD) using *GitHub Actions*. 52 | 53 | 1. Bump the library version in `./package.json` 54 | 2. Push the changes 55 | 3. Create a new: [GitHub release](https://github.com/badisi/auth-js/releases/new) 56 | 4. Watch the results in: [Actions](https://github.com/badisi/auth-js/actions) 57 | 58 | 59 | 60 | [git]: https://git-scm.com/ 61 | [nodejs]: https://nodejs.org/ 62 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/.gitignore: -------------------------------------------------------------------------------- 1 | # Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore 2 | 3 | # Built application files 4 | *.apk 5 | *.aar 6 | *.ap_ 7 | *.aab 8 | 9 | # Files for the ART/Dalvik VM 10 | *.dex 11 | 12 | # Java class files 13 | *.class 14 | 15 | # Generated files 16 | bin/ 17 | gen/ 18 | out/ 19 | # Uncomment the following line in case you need and you don't have the release build type files in your app 20 | # release/ 21 | 22 | # Gradle files 23 | .gradle/ 24 | build/ 25 | 26 | # Local configuration file (sdk path, etc) 27 | local.properties 28 | 29 | # Proguard folder generated by Eclipse 30 | proguard/ 31 | 32 | # Log Files 33 | *.log 34 | 35 | # Android Studio Navigation editor temp files 36 | .navigation/ 37 | 38 | # Android Studio captures folder 39 | captures/ 40 | 41 | # IntelliJ 42 | *.iml 43 | .idea/workspace.xml 44 | .idea/tasks.xml 45 | .idea/gradle.xml 46 | .idea/assetWizardSettings.xml 47 | .idea/dictionaries 48 | .idea/libraries 49 | # Android Studio 3 in .gitignore file. 50 | .idea/caches 51 | .idea/modules.xml 52 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 53 | .idea/navEditor.xml 54 | 55 | # Keystore files 56 | # Uncomment the following lines if you do not want to check your keystore files in. 57 | #*.jks 58 | #*.keystore 59 | 60 | # External native build folder generated in Android Studio 2.2 and later 61 | .externalNativeBuild 62 | .cxx/ 63 | 64 | # Google Services (e.g. APIs or Firebase) 65 | # google-services.json 66 | 67 | # Freeline 68 | freeline.py 69 | freeline/ 70 | freeline_project_description.json 71 | 72 | # fastlane 73 | fastlane/report.xml 74 | fastlane/Preview.html 75 | fastlane/screenshots 76 | fastlane/test_output 77 | fastlane/readme.md 78 | 79 | # Version control 80 | vcs.xml 81 | 82 | # lint 83 | lint/intermediates/ 84 | lint/generated/ 85 | lint/outputs/ 86 | lint/tmp/ 87 | # lint/reports/ 88 | 89 | # Android Profiling 90 | *.hprof 91 | 92 | # Cordova plugins for Capacitor 93 | capacitor-cordova-android-plugins 94 | 95 | # Copied web assets 96 | app/src/main/assets/public 97 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <project version="4"> 3 | <component name="CompilerConfiguration"> 4 | <bytecodeTargetLevel target="11" /> 5 | </component> 6 | </project> -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/.idea/deploymentTargetDropDown.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <project version="4"> 3 | <component name="deploymentTargetDropDown"> 4 | <targetSelectedWithDropDown> 5 | <Target> 6 | <type value="QUICK_BOOT_TARGET" /> 7 | <deviceKey> 8 | <Key> 9 | <type value="VIRTUAL_DEVICE_PATH" /> 10 | <value value="$USER_HOME$/.android/avd/Pixel_2_API_24.avd" /> 11 | </Key> 12 | </deviceKey> 13 | </Target> 14 | </targetSelectedWithDropDown> 15 | <timeTargetWasSelectedWithDropDown value="2022-09-09T14:58:34.505192Z" /> 16 | </component> 17 | </project> -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <project version="4"> 3 | <component name="RemoteRepositoriesConfiguration"> 4 | <remote-repository> 5 | <option name="id" value="central" /> 6 | <option name="name" value="Maven Central repository" /> 7 | <option name="url" value="https://repo1.maven.org/maven2" /> 8 | </remote-repository> 9 | <remote-repository> 10 | <option name="id" value="jboss.community" /> 11 | <option name="name" value="JBoss Community repository" /> 12 | <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" /> 13 | </remote-repository> 14 | <remote-repository> 15 | <option name="id" value="MavenRepo" /> 16 | <option name="name" value="MavenRepo" /> 17 | <option name="url" value="https://repo.maven.apache.org/maven2/" /> 18 | </remote-repository> 19 | <remote-repository> 20 | <option name="id" value="Google" /> 21 | <option name="name" value="Google" /> 22 | <option name="url" value="https://dl.google.com/dl/android/maven2/" /> 23 | </remote-repository> 24 | </component> 25 | </project> -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <project version="4"> 3 | <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK"> 4 | <output url="file://$PROJECT_DIR$/build/classes" /> 5 | </component> 6 | <component name="ProjectType"> 7 | <option name="id" value="Android" /> 8 | </component> 9 | </project> -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build/* 2 | !/build/.npmkeep 3 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | namespace "demoapp.authjs" 5 | compileSdkVersion rootProject.ext.compileSdkVersion 6 | defaultConfig { 7 | applicationId "demoapp.authjs" 8 | minSdkVersion rootProject.ext.minSdkVersion 9 | targetSdkVersion rootProject.ext.targetSdkVersion 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 13 | aaptOptions { 14 | // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. 15 | // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61 16 | ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~' 17 | } 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | } 26 | 27 | repositories { 28 | flatDir{ 29 | dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs' 30 | } 31 | } 32 | 33 | dependencies { 34 | implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion" 35 | implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion" 36 | implementation fileTree(include: ['*.jar'], dir: 'libs') 37 | implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" 38 | implementation project(':capacitor-android') 39 | testImplementation "junit:junit:$junitVersion" 40 | androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion" 41 | androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" 42 | implementation project(':capacitor-cordova-android-plugins') 43 | } 44 | 45 | apply from: 'capacitor.build.gradle' 46 | 47 | try { 48 | def servicesJSON = file('google-services.json') 49 | if (servicesJSON.text) { 50 | apply plugin: 'com.google.gms.google-services' 51 | } 52 | } catch(Exception e) { 53 | logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work") 54 | } 55 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/capacitor.build.gradle: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN 2 | 3 | android { 4 | compileOptions { 5 | sourceCompatibility JavaVersion.VERSION_17 6 | targetCompatibility JavaVersion.VERSION_17 7 | } 8 | } 9 | 10 | apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle" 11 | dependencies { 12 | implementation project(':capacitor-app') 13 | implementation project(':capacitor-browser') 14 | implementation project(':capacitor-preferences') 15 | implementation project(':capacitor-secure-storage-plugin') 16 | 17 | } 18 | 19 | 20 | if (hasProperty('postBuildExtras')) { 21 | postBuildExtras() 22 | } 23 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.getcapacitor.myapp; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import android.content.Context; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | import androidx.test.platform.app.InstrumentationRegistry; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> 15 | */ 16 | @RunWith(AndroidJUnit4.class) 17 | public class ExampleInstrumentedTest { 18 | 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 23 | 24 | assertEquals("com.getcapacitor.app", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 | > 4 | 5 | <application 6 | android:allowBackup="false" 7 | android:icon="@mipmap/ic_launcher" 8 | android:label="@string/app_name" 9 | android:roundIcon="@mipmap/ic_launcher_round" 10 | android:supportsRtl="true" 11 | android:theme="@style/AppTheme"> 12 | 13 | <activity 14 | android:exported="true" 15 | android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode" 16 | android:name="demoapp.authjs.MainActivity" 17 | android:label="@string/title_activity_main" 18 | android:theme="@style/AppTheme.NoActionBarLaunch" 19 | android:launchMode="singleTask"> 20 | 21 | <intent-filter> 22 | <action android:name="android.intent.action.MAIN" /> 23 | <category android:name="android.intent.category.LAUNCHER" /> 24 | </intent-filter> 25 | 26 | <intent-filter> 27 | <action android:name="android.intent.action.VIEW" /> 28 | <category android:name="android.intent.category.DEFAULT" /> 29 | <category android:name="android.intent.category.BROWSABLE" /> 30 | <data android:scheme="demo-app" /> 31 | </intent-filter> 32 | </activity> 33 | 34 | <provider 35 | android:name="androidx.core.content.FileProvider" 36 | android:authorities="${applicationId}.fileprovider" 37 | android:exported="false" 38 | android:grantUriPermissions="true"> 39 | <meta-data 40 | android:name="android.support.FILE_PROVIDER_PATHS" 41 | android:resource="@xml/file_paths"></meta-data> 42 | </provider> 43 | </application> 44 | 45 | <!-- Permissions --> 46 | 47 | <uses-permission android:name="android.permission.INTERNET" /> 48 | </manifest> 49 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/assets/capacitor.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "appId": "demoapp", 3 | "appName": "demo-app", 4 | "loggingBehavior": "debug", 5 | "server": { 6 | "url": "http://10.0.2.2:4200", 7 | "cleartext": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/assets/capacitor.plugins.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "pkg": "@capacitor/app", 4 | "classpath": "com.capacitorjs.plugins.app.AppPlugin" 5 | }, 6 | { 7 | "pkg": "@capacitor/browser", 8 | "classpath": "com.capacitorjs.plugins.browser.BrowserPlugin" 9 | }, 10 | { 11 | "pkg": "@capacitor/preferences", 12 | "classpath": "com.capacitorjs.plugins.preferences.PreferencesPlugin" 13 | }, 14 | { 15 | "pkg": "capacitor-secure-storage-plugin", 16 | "classpath": "com.whitestein.securestorage.SecureStoragePluginPlugin" 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/java/demoapp/authjs/MainActivity.java: -------------------------------------------------------------------------------- 1 | package demoapp.authjs; 2 | 3 | import com.getcapacitor.BridgeActivity; 4 | 5 | public class MainActivity extends BridgeActivity {} 6 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/drawable-land-hdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/drawable-land-hdpi/splash.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/drawable-land-mdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/drawable-land-mdpi/splash.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/drawable-land-xhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/drawable-land-xhdpi/splash.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/drawable-land-xxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/drawable-land-xxhdpi/splash.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/drawable-land-xxxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/drawable-land-xxxhdpi/splash.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/drawable-port-hdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/drawable-port-hdpi/splash.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/drawable-port-mdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/drawable-port-mdpi/splash.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/drawable-port-xhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/drawable-port-xhdpi/splash.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/drawable-port-xxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/drawable-port-xxhdpi/splash.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/drawable-port-xxxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/drawable-port-xxxhdpi/splash.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | <vector xmlns:android="http://schemas.android.com/apk/res/android" 2 | xmlns:aapt="http://schemas.android.com/aapt" 3 | android:width="108dp" 4 | android:height="108dp" 5 | android:viewportHeight="108" 6 | android:viewportWidth="108"> 7 | <path 8 | android:fillType="evenOdd" 9 | android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z" 10 | android:strokeColor="#00000000" 11 | android:strokeWidth="1"> 12 | <aapt:attr name="android:fillColor"> 13 | <gradient 14 | android:endX="78.5885" 15 | android:endY="90.9159" 16 | android:startX="48.7653" 17 | android:startY="61.0927" 18 | android:type="linear"> 19 | <item 20 | android:color="#44000000" 21 | android:offset="0.0" /> 22 | <item 23 | android:color="#00000000" 24 | android:offset="1.0" /> 25 | </gradient> 26 | </aapt:attr> 27 | </path> 28 | <path 29 | android:fillColor="#FFFFFF" 30 | android:fillType="nonZero" 31 | android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z" 32 | android:strokeColor="#00000000" 33 | android:strokeWidth="1" /> 34 | </vector> 35 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/drawable/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/drawable/splash.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 | xmlns:app="http://schemas.android.com/apk/res-auto" 4 | xmlns:tools="http://schemas.android.com/tools" 5 | android:layout_width="match_parent" 6 | android:layout_height="match_parent" 7 | tools:context=".MainActivity"> 8 | 9 | <WebView 10 | android:layout_width="match_parent" 11 | android:layout_height="match_parent" /> 12 | </androidx.coordinatorlayout.widget.CoordinatorLayout> 13 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> 3 | <background android:drawable="@color/ic_launcher_background"/> 4 | <foreground android:drawable="@mipmap/ic_launcher_foreground"/> 5 | </adaptive-icon> -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> 3 | <background android:drawable="@color/ic_launcher_background"/> 4 | <foreground android:drawable="@mipmap/ic_launcher_foreground"/> 5 | </adaptive-icon> -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <resources> 3 | <color name="ic_launcher_background">#FFFFFF</color> 4 | </resources> -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | <?xml version='1.0' encoding='utf-8'?> 2 | <resources> 3 | <string name="app_name">demo-app-auth-js</string> 4 | <string name="title_activity_main">demo-app-auth-js</string> 5 | <string name="package_name">demoapp.authjs</string> 6 | <string name="custom_url_scheme">demoapp.authjs</string> 7 | </resources> 8 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <resources> 3 | 4 | <!-- Base application theme. --> 5 | <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> 6 | <!-- Customize your theme here. --> 7 | <item name="colorPrimary">@color/colorPrimary</item> 8 | <item name="colorPrimaryDark">@color/colorPrimaryDark</item> 9 | <item name="colorAccent">@color/colorAccent</item> 10 | </style> 11 | 12 | <style name="AppTheme.NoActionBar" parent="Theme.AppCompat.DayNight.NoActionBar"> 13 | <item name="windowActionBar">false</item> 14 | <item name="windowNoTitle">true</item> 15 | <item name="android:background">@null</item> 16 | <item name="android:statusBarColor">#673ab7</item> 17 | </style> 18 | 19 | <style name="AppTheme.NoActionBarLaunch" parent="Theme.SplashScreen"> 20 | <item name="android:background">@drawable/splash</item> 21 | </style> 22 | </resources> 23 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/xml/config.xml: -------------------------------------------------------------------------------- 1 | <?xml version='1.0' encoding='utf-8'?> 2 | <widget version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> 3 | <access origin="*" /> 4 | 5 | 6 | </widget> -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/main/res/xml/file_paths.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <paths xmlns:android="http://schemas.android.com/apk/res/android"> 3 | <external-path name="my_images" path="." /> 4 | <cache-path name="my_cache_images" path="." /> 5 | </paths> -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.getcapacitor.myapp; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> 11 | */ 12 | public class ExampleUnitTest { 13 | 14 | @Test 15 | public void addition_isCorrect() throws Exception { 16 | assertEquals(4, 2 + 2); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | mavenCentral() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:8.0.0' 11 | classpath 'com.google.gms:google-services:4.3.15' 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | apply from: "variables.gradle" 19 | 20 | allprojects { 21 | repositories { 22 | google() 23 | mavenCentral() 24 | } 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/capacitor.settings.gradle: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN 2 | include ':capacitor-android' 3 | project(':capacitor-android').projectDir = new File('../../../../node_modules/@capacitor/android/capacitor') 4 | 5 | include ':capacitor-app' 6 | project(':capacitor-app').projectDir = new File('../../../../node_modules/@capacitor/app/android') 7 | 8 | include ':capacitor-browser' 9 | project(':capacitor-browser').projectDir = new File('../../../../node_modules/@capacitor/browser/android') 10 | 11 | include ':capacitor-preferences' 12 | project(':capacitor-preferences').projectDir = new File('../../../../node_modules/@capacitor/preferences/android') 13 | 14 | include ':capacitor-secure-storage-plugin' 15 | project(':capacitor-secure-storage-plugin').projectDir = new File('../../../../node_modules/capacitor-secure-storage-plugin/android') 16 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | # AndroidX package structure to make it clearer which packages are bundled with the 20 | # Android operating system, and which are packaged with your app's APK 21 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 22 | android.useAndroidX=true 23 | 24 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | include ':capacitor-cordova-android-plugins' 3 | project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/') 4 | 5 | apply from: 'capacitor.settings.gradle' -------------------------------------------------------------------------------- /apps/demo-app/capacitor/android/variables.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | minSdkVersion = 22 3 | compileSdkVersion = 33 4 | targetSdkVersion = 33 5 | androidxActivityVersion = '1.7.0' 6 | androidxAppCompatVersion = '1.6.1' 7 | androidxCoordinatorLayoutVersion = '1.2.0' 8 | androidxCoreVersion = '1.10.0' 9 | androidxFragmentVersion = '1.5.6' 10 | junitVersion = '4.13.2' 11 | androidxJunitVersion = '1.1.5' 12 | androidxEspressoCoreVersion = '3.5.1' 13 | cordovaAndroidVersion = '10.1.1' 14 | coreSplashScreenVersion = '1.0.0' 15 | androidxWebkitVersion = '1.6.1' 16 | } 17 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/capacitor.config.ts: -------------------------------------------------------------------------------- 1 | import { CapacitorConfig } from '@capacitor/cli'; 2 | 3 | const config: CapacitorConfig = { 4 | appId: 'demoapp', 5 | appName: 'demo-app', 6 | loggingBehavior: 'debug' 7 | }; 8 | 9 | // eslint-disable-next-line no-loops/no-loops 10 | for (let i = 0; i < process.argv.length; i++) { 11 | if (process.argv[i] === '--serverUrl') { 12 | config.server = { 13 | url: process.argv[++i], 14 | cleartext: true // Needed for Android, to avoid error ERR_CLEARTEXT_NOT_PERMITTED 15 | }; 16 | } 17 | } 18 | 19 | export default config; 20 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/.gitignore: -------------------------------------------------------------------------------- 1 | App/build 2 | App/Pods 3 | App/App/public 4 | App/output 5 | DerivedData 6 | xcuserdata 7 | 8 | # Cordova plugins for Capacitor 9 | capacitor-cordova-ios-plugins 10 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <Workspace 3 | version = "1.0"> 4 | <FileRef 5 | location = "self:App.xcodeproj"> 6 | </FileRef> 7 | </Workspace> 8 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <Workspace 3 | version = "1.0"> 4 | <FileRef 5 | location = "group:App.xcodeproj"> 6 | </FileRef> 7 | <FileRef 8 | location = "group:Pods/Pods.xcodeproj"> 9 | </FileRef> 10 | </Workspace> 11 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>IDEDidComputeMac32BitWarning</key> 6 | <true/> 7 | </dict> 8 | </plist> 9 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "AppIcon-512@2x.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "splash-2732x2732-2.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "splash-2732x2732-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "splash-2732x2732.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17132" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> 3 | <device id="retina4_7" orientation="portrait" appearance="light"/> 4 | <dependencies> 5 | <deployment identifier="iOS"/> 6 | <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17105"/> 7 | <capability name="System colors in document resources" minToolsVersion="11.0"/> 8 | <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> 9 | </dependencies> 10 | <scenes> 11 | <!--View Controller--> 12 | <scene sceneID="EHf-IW-A2E"> 13 | <objects> 14 | <viewController id="01J-lp-oVM" sceneMemberID="viewController"> 15 | <imageView key="view" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Splash" id="snD-IY-ifK"> 16 | <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> 17 | <autoresizingMask key="autoresizingMask"/> 18 | <color key="backgroundColor" systemColor="systemBackgroundColor"/> 19 | </imageView> 20 | </viewController> 21 | <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> 22 | </objects> 23 | <point key="canvasLocation" x="53" y="375"/> 24 | </scene> 25 | </scenes> 26 | <resources> 27 | <image name="Splash" width="1366" height="1366"/> 28 | <systemColor name="systemBackgroundColor"> 29 | <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> 30 | </systemColor> 31 | </resources> 32 | </document> 33 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14111" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> 3 | <device id="retina4_7" orientation="portrait"> 4 | <adaptation id="fullscreen"/> 5 | </device> 6 | <dependencies> 7 | <deployment identifier="iOS"/> 8 | <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/> 9 | </dependencies> 10 | <scenes> 11 | <!--Bridge View Controller--> 12 | <scene sceneID="tne-QT-ifu"> 13 | <objects> 14 | <viewController id="BYZ-38-t0r" customClass="CAPBridgeViewController" customModule="Capacitor" sceneMemberID="viewController"/> 15 | <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> 16 | </objects> 17 | </scene> 18 | </scenes> 19 | </document> 20 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App/Info.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>CFBundleDevelopmentRegion</key> 6 | <string>en</string> 7 | <key>CFBundleDisplayName</key> 8 | <string>demo-app-auth-js</string> 9 | <key>CFBundleExecutable</key> 10 | <string>$(EXECUTABLE_NAME)</string> 11 | <key>CFBundleIdentifier</key> 12 | <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> 13 | <key>CFBundleInfoDictionaryVersion</key> 14 | <string>6.0</string> 15 | <key>CFBundleName</key> 16 | <string>$(PRODUCT_NAME)</string> 17 | <key>CFBundlePackageType</key> 18 | <string>APPL</string> 19 | <key>CFBundleShortVersionString</key> 20 | <string>1.0</string> 21 | <key>CFBundleURLTypes</key> 22 | <array> 23 | <dict> 24 | <key>CFBundleTypeRole</key> 25 | <string>Editor</string> 26 | <key>CFBundleURLName</key> 27 | <string>demoapp.authjs</string> 28 | <key>CFBundleURLSchemes</key> 29 | <array> 30 | <string>demo-app</string> 31 | </array> 32 | </dict> 33 | </array> 34 | <key>CFBundleVersion</key> 35 | <string>1</string> 36 | <key>LSRequiresIPhoneOS</key> 37 | <true/> 38 | <key>UILaunchStoryboardName</key> 39 | <string>LaunchScreen</string> 40 | <key>UIMainStoryboardFile</key> 41 | <string>Main</string> 42 | <key>UIRequiredDeviceCapabilities</key> 43 | <array> 44 | <string>armv7</string> 45 | </array> 46 | <key>UISupportedInterfaceOrientations</key> 47 | <array> 48 | <string>UIInterfaceOrientationPortrait</string> 49 | <string>UIInterfaceOrientationLandscapeLeft</string> 50 | <string>UIInterfaceOrientationLandscapeRight</string> 51 | </array> 52 | <key>UISupportedInterfaceOrientations~ipad</key> 53 | <array> 54 | <string>UIInterfaceOrientationPortrait</string> 55 | <string>UIInterfaceOrientationPortraitUpsideDown</string> 56 | <string>UIInterfaceOrientationLandscapeLeft</string> 57 | <string>UIInterfaceOrientationLandscapeRight</string> 58 | </array> 59 | <key>UIViewControllerBasedStatusBarAppearance</key> 60 | <true/> 61 | </dict> 62 | </plist> 63 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App/capacitor.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "appId": "demoapp", 3 | "appName": "demo-app", 4 | "loggingBehavior": "debug", 5 | "server": { 6 | "url": "http://localhost:4200", 7 | "cleartext": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/App/config.xml: -------------------------------------------------------------------------------- 1 | <?xml version='1.0' encoding='utf-8'?> 2 | <widget version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> 3 | <access origin="*" /> 4 | 5 | 6 | </widget> -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../../../../../node_modules/@capacitor/ios/scripts/pods_helpers' 2 | 3 | platform :ios, '13.0' 4 | use_frameworks! 5 | 6 | # Workaround to avoid Xcode caching of Pods that requires 7 | # Product -> Clean Build Folder after new Cordova plugins installed 8 | # Requires CocoaPods 1.6 or newer 9 | install! 'cocoapods', :disable_input_output_paths => true 10 | 11 | def capacitor_pods 12 | pod 'Capacitor', :path => '../../../../../node_modules/@capacitor/ios' 13 | pod 'CapacitorCordova', :path => '../../../../../node_modules/@capacitor/ios' 14 | pod 'CapacitorApp', :path => '../../../../../node_modules/@capacitor/app' 15 | pod 'CapacitorBrowser', :path => '../../../../../node_modules/@capacitor/browser' 16 | pod 'CapacitorPreferences', :path => '../../../../../node_modules/@capacitor/preferences' 17 | pod 'CapacitorSecureStoragePlugin', :path => '../../../../../node_modules/capacitor-secure-storage-plugin' 18 | end 19 | 20 | target 'App' do 21 | capacitor_pods 22 | # Add your Pods here 23 | end 24 | 25 | 26 | post_install do |installer| 27 | assertDeploymentTarget(installer) 28 | end 29 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/ios/App/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Capacitor (5.7.8): 3 | - CapacitorCordova 4 | - CapacitorApp (5.0.8): 5 | - Capacitor 6 | - CapacitorBrowser (5.2.1): 7 | - Capacitor 8 | - CapacitorCordova (5.7.8) 9 | - CapacitorPreferences (5.0.8): 10 | - Capacitor 11 | - CapacitorSecureStoragePlugin (0.9.0): 12 | - Capacitor 13 | - SwiftKeychainWrapper 14 | - SwiftKeychainWrapper (4.0.1) 15 | 16 | DEPENDENCIES: 17 | - "Capacitor (from `../../../../../node_modules/@capacitor/ios`)" 18 | - "CapacitorApp (from `../../../../../node_modules/@capacitor/app`)" 19 | - "CapacitorBrowser (from `../../../../../node_modules/@capacitor/browser`)" 20 | - "CapacitorCordova (from `../../../../../node_modules/@capacitor/ios`)" 21 | - "CapacitorPreferences (from `../../../../../node_modules/@capacitor/preferences`)" 22 | - CapacitorSecureStoragePlugin (from `../../../../../node_modules/capacitor-secure-storage-plugin`) 23 | 24 | SPEC REPOS: 25 | trunk: 26 | - SwiftKeychainWrapper 27 | 28 | EXTERNAL SOURCES: 29 | Capacitor: 30 | :path: "../../../../../node_modules/@capacitor/ios" 31 | CapacitorApp: 32 | :path: "../../../../../node_modules/@capacitor/app" 33 | CapacitorBrowser: 34 | :path: "../../../../../node_modules/@capacitor/browser" 35 | CapacitorCordova: 36 | :path: "../../../../../node_modules/@capacitor/ios" 37 | CapacitorPreferences: 38 | :path: "../../../../../node_modules/@capacitor/preferences" 39 | CapacitorSecureStoragePlugin: 40 | :path: "../../../../../node_modules/capacitor-secure-storage-plugin" 41 | 42 | SPEC CHECKSUMS: 43 | Capacitor: 747aadb4fa786f460d8cd9d0557cb81440a13747 44 | CapacitorApp: 102e553c3b1fdc255969c39aa19b529675690ef4 45 | CapacitorBrowser: bac3132be6506411704149f9f2099843ffe470a0 46 | CapacitorCordova: 31ab98dca2ddcee051027a1afe7e8c85c82f7297 47 | CapacitorPreferences: 9e59596c5fd9915ed45279d1fda68978c5706401 48 | CapacitorSecureStoragePlugin: e91d7df060f2495a1acff9583641a6953e3aacba 49 | SwiftKeychainWrapper: 807ba1d63c33a7d0613288512399cd1eda1e470c 50 | 51 | PODFILE CHECKSUM: 30cc9ca62b326a988b41e9cd758c90bb8e2943c3 52 | 53 | COCOAPODS: 1.11.2 54 | -------------------------------------------------------------------------------- /apps/demo-app/capacitor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-app-capacitor", 3 | "private": true, 4 | "license": "GPL-3.0-only", 5 | "scripts": { 6 | "start:ios:localhost": "npx cap run ios --serverUrl http://localhost:4200", 7 | "start:ios:demo-auth-js": "npx cap run ios --serverUrl https://badisi.github.io/auth-js/demo-app/auth-js", 8 | "start:ios:demo-auth-vue": "npx cap run ios --serverUrl https://badisi.github.io/auth-js/demo-app/auth-vue", 9 | "start:ios:demo-ngx-auth": "npx cap run ios --serverUrl https://badisi.github.io/auth-js/demo-app/ngx-auth", 10 | "start:android:localhost": "npx cap run android --serverUrl http://10.0.2.2:4200", 11 | "start:android:demo-auth-js": "npx cap run android --serverUrl https://badisi.github.io/auth-js/demo-app/auth-js", 12 | "start:android:demo-auth-vue": "npx cap run android --serverUrl https://badisi.github.io/auth-js/demo-app/auth-vue", 13 | "start:android:demo-ngx-auth": "npx cap run android --serverUrl https://badisi.github.io/auth-js/demo-app/ngx-auth" 14 | }, 15 | "dependencies": { 16 | "@capacitor/android": "^5.7.4", 17 | "@capacitor/app": "^5.0.7", 18 | "@capacitor/browser": "^5.2.0", 19 | "@capacitor/core": "^5.7.4", 20 | "@capacitor/ios": "^5.7.4", 21 | "@capacitor/preferences": "^5.0.7", 22 | "capacitor-secure-storage-plugin": "^0.9.0" 23 | }, 24 | "devDependencies": { 25 | "@capacitor/cli": "^5.7.4" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-js/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@nx/js/babel" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-js/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | name: 'PROD', 3 | production: true 4 | }; 5 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-js/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // When building for production, this file is replaced with `environment.prod.ts`. 3 | 4 | export const environment = { 5 | name: 'DEV', 6 | production: false 7 | }; 8 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-js/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/web/auth-js/src/favicon.ico -------------------------------------------------------------------------------- /apps/demo-app/web/auth-js/src/index.html: -------------------------------------------------------------------------------- 1 | <!doctype html> 2 | <html lang="en"> 3 | <head> 4 | <meta charset="utf-8" /> 5 | <title>Playground | Auth-js 6 | 7 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-js/src/main.ts: -------------------------------------------------------------------------------- 1 | import './app/app.element'; 2 | 3 | import { initOidc } from '@badisi/auth-js/oidc'; 4 | import { DemoAppSettingsService } from 'demo-app-common'; 5 | 6 | import { environment } from './environments/environment'; 7 | 8 | ((): void => { 9 | window.appSettings = new DemoAppSettingsService(!environment.production); 10 | 11 | const el = document.createElement('div'); 12 | el.innerHTML = 'Loading...'; 13 | document.body.appendChild(el); 14 | 15 | initOidc(window.appSettings.getCurrentSettings().librarySettings) 16 | .then(manager => { 17 | window.authManager = manager; 18 | el.replaceWith(document.createElement('app-root')); 19 | }) 20 | .catch((err: unknown) => { 21 | const message = (err instanceof Error) ? err.message : String(err); 22 | el.innerHTML = `${message}
`; 23 | document.body.querySelector('#loginButton')?.addEventListener( 24 | 'click', () => { location.reload(); }, { once: true } 25 | ); 26 | console.error(err); 27 | }); 28 | })(); 29 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-js/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | html, 4 | body { 5 | height: 100%; 6 | } 7 | 8 | body { 9 | margin: var(--safe-area-inset-top) 0 var(--safe-area-inset-bottom) 0; 10 | font-family: 11 | system-ui, 12 | -apple-system, 13 | 'Inter', 14 | sans-serif; 15 | background-color: #fafafa; 16 | } 17 | 18 | :root { 19 | /* iOS Safari 11.2, Safari 11 */ 20 | @supports (top: constant(safe-area-inset-top)) { 21 | --safe-area-inset-top: constant(safe-area-inset-top); 22 | --safe-area-inset-bottom: constant(safe-area-inset-bottom); 23 | } 24 | 25 | /* iOS Safari 11.4+, Safari 11.1+, Chrome 69+, Opera 56+ */ 26 | @supports (top: env(safe-area-inset-top)) { 27 | --safe-area-inset-top: env(safe-area-inset-top); 28 | --safe-area-inset-bottom: env(safe-area-inset-bottom); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-js/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../../dist/out-tsc", 5 | "types": [ 6 | "../../../../libs/auth-js/@types/mobile" 7 | ] 8 | }, 9 | "include": [ 10 | "src/**/*.ts" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-js/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "esModuleInterop": true, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "resolveJsonModule": true 12 | }, 13 | "files": [], 14 | "include": [], 15 | "references": [ 16 | { 17 | "path": "./tsconfig.app.json" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-js/webpack.config.js: -------------------------------------------------------------------------------- 1 | const { composePlugins, withNx, withWeb } = require('@nx/webpack'); 2 | const { resolve } = require('node:path'); 3 | 4 | // Note: This was added by an Nx migration. Webpack builds are required to have a corresponding Webpack config file. 5 | // See: https://nx.dev/recipes/webpack/webpack-config-setup 6 | module.exports = composePlugins(withNx(), withWeb(), config => { 7 | const babelLoader = (config.module.rules ?? []).find(rule => rule.loader && rule.loader.includes('babel-loader')); 8 | if (babelLoader) { 9 | babelLoader.options.cacheDirectory = resolve(__dirname, '../../../../node_modules/.cache/babel-loader'); 10 | } 11 | return config; 12 | }); 13 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-vue/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Playground | Auth-vue 6 | 7 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-vue/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-app-auth-vue", 3 | "$schema": "../../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "application", 5 | "sourceRoot": "apps/demo-app/web/auth-vue/src", 6 | "tags": [], 7 | "targets": { 8 | "build": { 9 | "executor": "@nx/vite:build", 10 | "outputs": [ 11 | "{options.outputPath}" 12 | ], 13 | "options": { 14 | "outputPath": "dist/demo-app/auth-vue", 15 | "tsConfig": "apps/demo-app/web/auth-vue/tsconfig.app.json", 16 | "configFile": "apps/demo-app/web/auth-vue/vite.config.mjs" 17 | } 18 | }, 19 | "serve": { 20 | "executor": "@nx/vite:dev-server", 21 | "options": { 22 | "host": "0.0.0.0", 23 | "buildTarget": "demo-app-auth-vue:build" 24 | } 25 | }, 26 | "lint": { 27 | "executor": "@nx/eslint:lint" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-vue/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/web/auth-vue/public/favicon.ico -------------------------------------------------------------------------------- /apps/demo-app/web/auth-vue/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-vue/src/main.ts: -------------------------------------------------------------------------------- 1 | import './styles.scss'; 2 | 3 | import { initAuth } from '@badisi/auth-vue'; 4 | import { DemoAppSettingsService } from 'demo-app-common'; 5 | import { createApp } from 'vue'; 6 | 7 | import app from './App.vue'; 8 | import router from './router'; 9 | 10 | ((): void => { 11 | window.appSettings = new DemoAppSettingsService(!import.meta.env.PROD); 12 | 13 | const el = document.createElement('div'); 14 | el.innerHTML = 'Loading...'; 15 | document.body.appendChild(el); 16 | 17 | initAuth(window.appSettings.getCurrentSettings().librarySettings) 18 | .then(authPlugin => { 19 | el.replaceWith(document.createElement('root')); 20 | 21 | const vueApp = createApp(app); 22 | vueApp.use(authPlugin, { router }); 23 | vueApp.use(router); 24 | vueApp.mount('root'); 25 | }) 26 | .catch((err: unknown) => { 27 | const message = (err instanceof Error) ? err.message : String(err); 28 | el.innerHTML = `${message}
`; 29 | document.body.querySelector('#loginButton')?.addEventListener( 30 | 'click', () => { location.reload(); }, { once: true } 31 | ); 32 | console.error(err); 33 | }); 34 | })(); 35 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-vue/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { rolesValidator } from 'demo-app-common'; 2 | import { createRouter, createWebHistory, type RouteComponent } from 'vue-router'; 3 | 4 | import demoView from '../views/DemoView.vue'; 5 | 6 | const router = createRouter({ 7 | history: createWebHistory(import.meta.env.BASE_URL), 8 | routes: [ 9 | { 10 | path: '/', 11 | component: demoView, 12 | children: [ 13 | { 14 | path: 'forbidden', 15 | component: (): Promise => import('../views/PageView.vue'), 16 | meta: { 17 | title: 'ACCESS FORBIDDEN' 18 | } 19 | }, 20 | { 21 | path: 'public', 22 | component: (): Promise => import('../views/PageView.vue'), 23 | meta: { 24 | title: 'PUBLIC CONTENT' 25 | } 26 | }, 27 | { 28 | path: 'private', 29 | component: (): Promise => import('../views/PageView.vue'), 30 | meta: { 31 | title: 'PRIVATE CONTENT', 32 | authGuard: true, 33 | // authGuard: { fallbackUrl: 'forbidden' }, 34 | // authGuard: { validator: () => false }, 35 | // authGuard: { validator: hasRole('view-profile') } 36 | } 37 | }, 38 | { 39 | path: 'protected', 40 | component: (): Promise => import('../views/PageView.vue'), 41 | meta: { 42 | title: 'PROTECTED CONTENT', 43 | authGuard: { 44 | validator: rolesValidator() 45 | } 46 | } 47 | } 48 | ] 49 | } 50 | ] 51 | }); 52 | 53 | export default router; 54 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-vue/src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import type { DefineComponent } from 'vue'; 3 | const component: DefineComponent; 4 | export default component; 5 | } 6 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-vue/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | html, 4 | body { 5 | height: 100%; 6 | } 7 | 8 | body { 9 | margin: var(--safe-area-inset-top) 0 var(--safe-area-inset-bottom) 0; 10 | font-family: 11 | system-ui, 12 | -apple-system, 13 | 'Inter', 14 | sans-serif; 15 | background-color: #fafafa; 16 | } 17 | 18 | :root { 19 | /* iOS Safari 11.2, Safari 11 */ 20 | @supports (top: constant(safe-area-inset-top)) { 21 | --safe-area-inset-top: constant(safe-area-inset-top); 22 | --safe-area-inset-bottom: constant(safe-area-inset-bottom); 23 | } 24 | 25 | /* iOS Safari 11.4+, Safari 11.1+, Chrome 69+, Opera 56+ */ 26 | @supports (top: env(safe-area-inset-top)) { 27 | --safe-area-inset-top: env(safe-area-inset-top); 28 | --safe-area-inset-bottom: env(safe-area-inset-bottom); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-vue/src/views/DemoView.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 66 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-vue/src/views/PageView.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-vue/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../../dist/out-tsc", 5 | "types": [ 6 | "../../../../libs/auth-js/@types/mobile", 7 | "vite/client" 8 | ] 9 | }, 10 | "include": [ 11 | "src/**/*.ts", 12 | "src/**/*.vue" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-vue/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "esModuleInterop": true, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "resolveJsonModule": true 12 | }, 13 | "files": [], 14 | "include": [], 15 | "references": [ 16 | { 17 | "path": "./tsconfig.app.json" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /apps/demo-app/web/auth-vue/vite.config.mjs: -------------------------------------------------------------------------------- 1 | /// 2 | import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; 3 | import vue from '@vitejs/plugin-vue'; 4 | import { defineConfig } from 'vite'; 5 | import simpleHtmlPlugin from 'vite-plugin-simple-html'; 6 | import { viteStaticCopy } from 'vite-plugin-static-copy'; 7 | 8 | const baseHref = process.env.BASE_URL || '/'; 9 | 10 | export default defineConfig({ 11 | root: __dirname, 12 | base: baseHref, 13 | cacheDir: '../../../../node_modules/.vite/demo-app/auth-vue', 14 | server: { 15 | port: 4200, 16 | host: 'localhost' 17 | }, 18 | plugins: [ 19 | vue({ 20 | template: { 21 | compilerOptions: { 22 | isCustomElement: tag => tag.startsWith('demo-app-') 23 | } 24 | } 25 | }), 26 | nxViteTsPaths(), 27 | simpleHtmlPlugin({ 28 | minify: false, 29 | inject: { 30 | data: { 31 | baseHref: baseHref 32 | } 33 | } 34 | }), 35 | viteStaticCopy({ 36 | targets: [ 37 | { 38 | src: '../../../../libs/auth-js/oidc/assets/*', 39 | dest: 'oidc/callback/' 40 | } 41 | ] 42 | }) 43 | ], 44 | build: { 45 | outDir: '../../../../dist/demo-app/auth-vue', 46 | emptyOutDir: true, 47 | reportCompressedSize: true, 48 | commonjsOptions: { 49 | transformMixedEsModules: true 50 | } 51 | } 52 | }); 53 | -------------------------------------------------------------------------------- /apps/demo-app/web/common/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components/demo-app-debug.element'; 2 | export * from './components/demo-app-header.element'; 3 | export * from './components/demo-app-main.element'; 4 | export * from './components/demo-app-playground.element'; 5 | export * from './components/demo-app-settings.element'; 6 | export * from './core'; 7 | export * from './settings/default-settings'; 8 | export * from './settings/demo-app-settings.service'; 9 | export * from './settings/library-settings-definition'; 10 | -------------------------------------------------------------------------------- /apps/demo-app/web/common/jest.config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | displayName: 'demo-app-common', 3 | preset: '../../../../jest.preset.js', 4 | transform: { 5 | '^.+\\.[tj]s$': [ 6 | 'ts-jest', 7 | { tsconfig: '/tsconfig.spec.json' }] 8 | }, 9 | moduleFileExtensions: [ 10 | 'ts', 11 | 'js', 12 | 'html' 13 | ], 14 | coverageDirectory: '../../../../coverage/apps/demo-app/web/common' 15 | }; 16 | -------------------------------------------------------------------------------- /apps/demo-app/web/common/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-app-common", 3 | "$schema": "../../../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "apps/demo-app/web/common", 5 | "projectType": "library", 6 | "tags": [], 7 | "targets": { 8 | "lint": { 9 | "executor": "@nx/eslint:lint" 10 | }, 11 | "test": { 12 | "executor": "@nx/jest:jest", 13 | "outputs": [ 14 | "{workspaceRoot}/coverage/{projectRoot}" 15 | ], 16 | "options": { 17 | "jestConfig": "apps/demo-app/web/common/jest.config.ts" 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /apps/demo-app/web/common/settings/index.ts: -------------------------------------------------------------------------------- 1 | import type { AuthSettings } from '@badisi/auth-js'; 2 | 3 | export interface LibraryImplementation { 4 | label: string; 5 | demoUrl: string; 6 | version: string; 7 | } 8 | 9 | export interface LibrarySettingsDefinitionItem { 10 | _sortIndex?: number; 11 | name: keyof LS; 12 | label: string; 13 | type: 'string' | 'boolean' | 'list' | 'json'; 14 | placeholder?: string; 15 | required?: boolean; 16 | values?: { label: string; value: unknown; }[]; 17 | } 18 | 19 | export interface Settings { 20 | name: string; 21 | otherSettings?: { 22 | apiUrl?: string; 23 | apiHeaders?: string; 24 | queryParams?: string; 25 | roles?: string; 26 | }; 27 | librarySettings: LS; 28 | } 29 | 30 | export interface DemoAppSettings { 31 | currentTabIndex: number; 32 | currentSettingsIndex: number; 33 | settings: Settings[]; 34 | } 35 | 36 | export { DemoAppSettingsService } from './demo-app-settings.service'; 37 | -------------------------------------------------------------------------------- /apps/demo-app/web/common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "forceConsistentCasingInFileNames": true, 5 | "strict": true, 6 | "noImplicitOverride": true, 7 | "noPropertyAccessFromIndexSignature": true, 8 | "noImplicitReturns": true, 9 | "noFallthroughCasesInSwitch": true, 10 | "resolveJsonModule": true, 11 | "esModuleInterop": true 12 | }, 13 | "files": [], 14 | "include": [], 15 | "references": [ 16 | { 17 | "path": "./tsconfig.lib.json" 18 | }, 19 | { 20 | "path": "./tsconfig.spec.json" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /apps/demo-app/web/common/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../../dist/out-tsc", 5 | "declaration": true, 6 | "types": [] 7 | }, 8 | "include": [ 9 | "**/*.ts" 10 | ], 11 | "exclude": [ 12 | "jest.config.ts", 13 | "**/*.spec.ts", 14 | "**/*.test.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /apps/demo-app/web/common/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": [ 7 | "jest", 8 | "node" 9 | ] 10 | }, 11 | "include": [ 12 | "jest.config.ts", 13 | "**/*.test.ts", 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/.browserslistrc: -------------------------------------------------------------------------------- 1 | last 2 Chrome versions 2 | last 1 Firefox version 3 | last 2 Edge major versions 4 | Safari >= 16 5 | last 2 iOS major versions 6 | last 2 ChromeAndroid versions 7 | Firefox ESR 8 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/demo-app/web/ngx-auth/public/favicon.ico -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { RouterOutlet } from '@angular/router'; 3 | 4 | @Component({ 5 | standalone: true, 6 | selector: 'app-root', 7 | templateUrl: './app.component.html', 8 | imports: [RouterOutlet] 9 | }) 10 | export class AppComponent { } 11 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | import { provideHttpClient } from '@angular/common/http'; 2 | import type { ApplicationConfig } from '@angular/core'; 3 | import { provideRouter, withRouterConfig } from '@angular/router'; 4 | 5 | import { routes } from './app.routes'; 6 | 7 | export const appConfig: ApplicationConfig = { 8 | providers: [ 9 | provideHttpClient(), 10 | provideRouter(routes, withRouterConfig({ onSameUrlNavigation: 'reload' })) 11 | ] 12 | }; 13 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; 2 | import { Component, NgModule } from '@angular/core'; 3 | import { BrowserModule } from '@angular/platform-browser'; 4 | import { RouterModule } from '@angular/router'; 5 | 6 | import { routes } from './app.routes'; 7 | 8 | @Component({ 9 | selector: 'app-root', 10 | templateUrl: './app.component.html', 11 | standalone: false 12 | }) 13 | export class AppComponent {} 14 | 15 | @NgModule({ 16 | imports: [RouterModule.forRoot(routes)], 17 | exports: [RouterModule] 18 | }) 19 | export class AppRoutingModule {} 20 | 21 | @NgModule({ 22 | declarations: [ 23 | AppComponent 24 | ], 25 | imports: [ 26 | BrowserModule, 27 | AppRoutingModule 28 | ], 29 | providers: [ 30 | provideHttpClient(withInterceptorsFromDi()) 31 | ], 32 | bootstrap: [AppComponent] 33 | }) 34 | export class AppModule {} 35 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/src/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | import type { Routes } from '@angular/router'; 2 | 3 | import { routes as demoRoutes } from './demo/demo.routes'; 4 | 5 | export const routes: Routes = [ 6 | { path: '', children: demoRoutes }, 7 | { path: '**', pathMatch: 'full', redirectTo: '' } 8 | ]; 9 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/src/app/demo/components/page/page.component.html: -------------------------------------------------------------------------------- 1 |

{{ title }}

2 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/src/app/demo/components/page/page.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | height: 100%; 6 | color: #bdbdbd; 7 | } 8 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/src/app/demo/components/page/page.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject, OnInit } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | 4 | @Component({ 5 | standalone: true, 6 | selector: 'app-page', 7 | templateUrl: './page.component.html', 8 | styleUrls: ['./page.component.scss'] 9 | }) 10 | export class PageComponent implements OnInit { 11 | public title = ''; 12 | 13 | private route = inject(ActivatedRoute); 14 | 15 | public ngOnInit(): void { 16 | this.title = this.route.snapshot.data['title'] as string; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/src/app/demo/demo.component.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | 16 | 17 | 18 | 19 | 20 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/src/app/demo/demo.component.ts: -------------------------------------------------------------------------------- 1 | import { AsyncPipe } from '@angular/common'; 2 | import { HttpClient, HttpHeaders } from '@angular/common/http'; 3 | import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, inject, ViewChild, ViewEncapsulation } from '@angular/core'; 4 | import { FormsModule } from '@angular/forms'; 5 | import { Params, Router, RouterOutlet } from '@angular/router'; 6 | import { AuthService } from '@badisi/ngx-auth'; 7 | import { DemoAppPlaygroundElement, globalStyle } from 'demo-app-common'; 8 | 9 | @Component({ 10 | standalone: true, 11 | selector: 'app-demo', 12 | templateUrl: './demo.component.html', 13 | styles: [globalStyle], 14 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 15 | imports: [AsyncPipe, FormsModule, RouterOutlet], 16 | encapsulation: ViewEncapsulation.ShadowDom 17 | }) 18 | export class DemoComponent { 19 | @ViewChild('demoAppPlayground') 20 | private demoAppPlaygroundEl!: ElementRef; 21 | 22 | protected authService = inject(AuthService); 23 | private httpClient = inject(HttpClient); 24 | private router = inject(Router); 25 | 26 | // --- HANDLER(s) --- 27 | 28 | public callPrivateApi(event: Event): void { 29 | const { url, headers } = (event as CustomEvent).detail as { 30 | url: string; 31 | headers?: Record; 32 | }; 33 | 34 | if (url) { 35 | const demoPlayground = this.demoAppPlaygroundEl.nativeElement; 36 | this.httpClient 37 | .get(url, headers ? { headers: new HttpHeaders(headers) } : {}) 38 | .subscribe({ 39 | next: data => { demoPlayground.setApiStatus(data, false); }, 40 | error: (error: unknown) => { demoPlayground.setApiStatus(error, true); } 41 | }); 42 | } 43 | } 44 | 45 | public async navigate(url: string, event: Event): Promise { 46 | const { queryParams } = (event as CustomEvent).detail as { 47 | queryParams?: Params; 48 | }; 49 | await this.router.navigate([url], { queryParams }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/src/app/demo/demo.routes.ts: -------------------------------------------------------------------------------- 1 | import type { Routes } from '@angular/router'; 2 | import { authGuard } from '@badisi/ngx-auth'; 3 | import { rolesValidator } from 'demo-app-common'; 4 | 5 | import { DemoComponent } from './demo.component'; 6 | 7 | const rolesGuard = authGuard({ validator: rolesValidator() }); 8 | 9 | export const routes: Routes = [ 10 | { 11 | path: '', 12 | component: DemoComponent, 13 | children: [ 14 | { 15 | path: 'forbidden', 16 | loadComponent: () => import('./components/page/page.component').then(m => m.PageComponent), 17 | runGuardsAndResolvers: 'always', 18 | data: { 19 | title: 'ACCESS FORBIDDEN' 20 | } 21 | }, 22 | { 23 | path: 'public', 24 | loadComponent: () => import('./components/page/page.component').then(m => m.PageComponent), 25 | runGuardsAndResolvers: 'always', 26 | data: { 27 | title: 'PUBLIC CONTENT' 28 | } 29 | }, 30 | { 31 | path: 'private', 32 | loadComponent: () => import('./components/page/page.component').then(m => m.PageComponent), 33 | runGuardsAndResolvers: 'always', 34 | canMatch: [authGuard()], 35 | canActivate: [authGuard()], 36 | canActivateChild: [authGuard()], 37 | data: { 38 | title: 'PRIVATE CONTENT' 39 | } 40 | }, 41 | { 42 | path: 'protected', 43 | loadComponent: () => import('./components/page/page.component').then(m => m.PageComponent), 44 | runGuardsAndResolvers: 'always', 45 | canMatch: [rolesGuard], 46 | canActivate: [rolesGuard], 47 | canActivateChild: [rolesGuard], 48 | data: { 49 | title: 'PROTECTED CONTENT' 50 | } 51 | } 52 | ] 53 | } 54 | ]; 55 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Playground | Ngx-auth 6 | 7 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/src/main.ts: -------------------------------------------------------------------------------- 1 | import { isDevMode } from '@angular/core'; 2 | import { bootstrapApplication, platformBrowser } from '@angular/platform-browser'; 3 | import { initAuth, provideAuth } from '@badisi/ngx-auth'; 4 | import { DemoAppSettingsService } from 'demo-app-common'; 5 | 6 | import { AppComponent } from './app/app.component'; 7 | import { AppModule } from './app/app.module'; 8 | 9 | const USE_STANDALONE = true; 10 | 11 | void (async (): Promise => { 12 | window.appSettings = new DemoAppSettingsService(isDevMode()); 13 | 14 | const el = document.createElement('div'); 15 | el.innerHTML = 'Loading...'; 16 | document.body.appendChild(el); 17 | 18 | try { 19 | const authProvider = await initAuth(window.appSettings.getCurrentSettings().librarySettings); 20 | 21 | el.replaceWith(document.createElement('app-root')); 22 | 23 | // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition 24 | if (USE_STANDALONE) { 25 | const { appConfig } = await import('./app/app.config'); 26 | appConfig.providers.push(provideAuth(authProvider)); 27 | bootstrapApplication(AppComponent, appConfig) 28 | .catch((err: unknown) => { console.error(err); }); 29 | } else { 30 | platformBrowser([authProvider]) 31 | .bootstrapModule(AppModule) 32 | .catch((err: unknown) => { console.error(err); }); 33 | } 34 | } catch (err: unknown) { 35 | const message = (err instanceof Error) ? err.message : String(err); 36 | el.innerHTML = `${message}
`; 37 | document.body.querySelector('#loginButton')?.addEventListener( 38 | 'click', () => { location.reload(); }, { once: true } 39 | ); 40 | console.error(err); 41 | } 42 | })(); 43 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | html, 4 | body { 5 | height: 100%; 6 | } 7 | 8 | body { 9 | margin: var(--safe-area-inset-top) 0 var(--safe-area-inset-bottom) 0; 10 | font-family: 11 | system-ui, 12 | -apple-system, 13 | 'Inter', 14 | sans-serif; 15 | background-color: #fafafa; 16 | } 17 | 18 | :root { 19 | /* iOS Safari 11.2, Safari 11 */ 20 | @supports (top: constant(safe-area-inset-top)) { 21 | --safe-area-inset-top: constant(safe-area-inset-top); 22 | --safe-area-inset-bottom: constant(safe-area-inset-bottom); 23 | } 24 | 25 | /* iOS Safari 11.4+, Safari 11.1+, Chrome 69+, Opera 56+ */ 26 | @supports (top: env(safe-area-inset-top)) { 27 | --safe-area-inset-top: env(safe-area-inset-top); 28 | --safe-area-inset-bottom: env(safe-area-inset-bottom); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../../dist/out-tsc", 5 | "types": [ 6 | "../../../../libs/auth-js/@types/mobile" 7 | ] 8 | }, 9 | "files": [ 10 | "src/main.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | "src/**/*.ts" 5 | ], 6 | "compilerOptions": {} 7 | } 8 | -------------------------------------------------------------------------------- /apps/demo-app/web/ngx-auth/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "esModuleInterop": true, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "resolveJsonModule": true 12 | }, 13 | "files": [], 14 | "include": [], 15 | "references": [ 16 | { 17 | "path": "./tsconfig.editor.json" 18 | }, 19 | { 20 | "path": "./tsconfig.app.json" 21 | }, 22 | { 23 | "path": "./tsconfig.spec.json" 24 | } 25 | ], 26 | "angularCompilerOptions": { 27 | "enableI18nLegacyMessageIdFormat": false, 28 | "strictInjectionParameters": true, 29 | "strictInputAccessModifiers": true, 30 | "strictTemplates": true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /apps/demo-app/web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-app-web", 3 | "private": true, 4 | "license": "GPL-3.0-only", 5 | "scripts": { 6 | "start:auth-js": "nx run demo-app-auth-js:serve", 7 | "start:auth-vue": "nx run demo-app-auth-vue:serve", 8 | "start:ngx-auth": "nx run demo-app-ngx-auth:serve", 9 | "lint": "nx run-many --target=lint --projects=demo-app-common,demo-app-auth-js,demo-app-ngx-auth,demo-app-auth-vue", 10 | "build:auth-js": "nx run demo-app-auth-js:build", 11 | "build:auth-vue": "nx run demo-app-auth-vue:build", 12 | "build:ngx-auth": "cd ../../../ && nx run demo-app-ngx-auth:build" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /apps/demo-e2e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-e2e", 3 | "private": true, 4 | "license": "GPL-3.0-only", 5 | "type": "module", 6 | "scripts": { 7 | "start": "NODE_TLS_REJECT_UNAUTHORIZED=0 wdio run wdio.config.ts --watch=false --debug=true --headless=false", 8 | "watch": "NODE_TLS_REJECT_UNAUTHORIZED=0 wdio run wdio.config.ts --watch=true --debug=true --headless=false", 9 | "ci": "wdio run wdio.config.ts --watch=false --debug=false --headless=true" 10 | }, 11 | "devDependencies": { 12 | "@types/jasmine": "^5.1.8", 13 | "@wdio/cli": "^9.16.2", 14 | "@wdio/jasmine-framework": "^9.16.2", 15 | "@wdio/local-runner": "^9.16.2", 16 | "@wdio/spec-reporter": "^9.16.2", 17 | "puppeteer-core": "^24.11.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/demo-e2e/src/pageobjects/idp-page.model.ts: -------------------------------------------------------------------------------- 1 | export abstract class IdpPage { 2 | protected username = 'admin'; 3 | protected password = 'Pa55w0rd'; 4 | 5 | public abstract readonly name: string; 6 | public abstract readonly url: string; 7 | public abstract get usernameInput(): ChainablePromiseElement; 8 | public abstract get passwordInput(): ChainablePromiseElement; 9 | 10 | public abstract openUserAccount(): Promise; 11 | public abstract authenticate(): Promise; 12 | public abstract logout(): Promise; 13 | } 14 | -------------------------------------------------------------------------------- /apps/demo-e2e/src/pageobjects/keycloak.page.ts: -------------------------------------------------------------------------------- 1 | import { $, browser } from '@wdio/globals'; 2 | import type { ChainablePromiseElement } from 'webdriverio'; 3 | 4 | import { IdpPage } from './idp-page.model'; 5 | 6 | class KeyCloakPage extends IdpPage { 7 | public readonly name = 'Keycloak'; 8 | public readonly url = 'http://localhost:8080'; 9 | public readonly accountUrl = `${this.url}/auth/realms/demo/account`; 10 | public get usernameInput(): ChainablePromiseElement { return $('input#username'); } 11 | public get passwordInput(): ChainablePromiseElement { return $('input#password'); } 12 | public get submitButton(): ChainablePromiseElement { return $('input#kc-login'); } 13 | public get logoutButton(): ChainablePromiseElement { return $('button#landingSignOutButton'); } 14 | public get spinnerScreen(): ChainablePromiseElement { return $('#spinner_screen'); } 15 | 16 | public async openUserAccount(): Promise { 17 | await browser.url(this.accountUrl); 18 | await browser.waitUntil( 19 | async () => (!(await this.spinnerScreen.isDisplayed())), 20 | { timeout: 5000, timeoutMsg: 'Expected Keycloak loading screen to hide' } 21 | ); 22 | } 23 | 24 | public async authenticate(): Promise { 25 | await this.usernameInput.setValue(this.username); 26 | await this.passwordInput.setValue(this.password); 27 | await this.submitButton.click(); 28 | } 29 | 30 | public async logout(): Promise { 31 | if (await this.logoutButton.isDisplayed()) { 32 | await this.logoutButton.click(); 33 | } 34 | } 35 | } 36 | 37 | export default new KeyCloakPage(); 38 | -------------------------------------------------------------------------------- /apps/demo-e2e/src/polyfills/puppeteer.ts: -------------------------------------------------------------------------------- 1 | import { browser } from '@wdio/globals'; 2 | import type { HTTPResponse, Page } from 'puppeteer-core'; 3 | import type { MockFilterOptions, WaitForOptions } from 'webdriverio'; 4 | 5 | declare global { 6 | // eslint-disable-next-line @typescript-eslint/no-namespace 7 | namespace WebdriverIO { 8 | interface Browser { 9 | getPage: () => Promise; 10 | waitForNavigation: () => Promise; 11 | } 12 | interface Mock { 13 | waitForResponse: ({ timeout }?: WaitForOptions) => Promise; 14 | } 15 | } 16 | } 17 | 18 | type MockFunction = (url: string, filterOptions?: MockFilterOptions) => Promise; 19 | 20 | // @ts-expect-error Webdriverio wrongly typed the origCommand and expect it to be `() => MockFunction` instead of `MockFunction` 21 | browser.overwriteCommand('mock', async (origCommand: MockFunction, url: string, _filterOptions?: MockFilterOptions): Promise => { 22 | const currentPage = await browser.getPage(); 23 | /** 24 | * BiDi seems very unstable if many mocks are used and it slowed everything down. 25 | * So if original mock's methods are not used we can get rid of them to improve performances. 26 | */ 27 | // const mock = await origCommand(url, filterOptions); 28 | const mock = {} as unknown as WebdriverIO.Mock; 29 | mock.waitForResponse = async (options?: WaitForOptions): Promise => { 30 | // eslint-disable-next-line no-nested-ternary 31 | const pattern = (typeof url === 'object') ? url : (url.startsWith('http') ? new URLPattern(url) : new URLPattern({ pathname: url })); 32 | return await currentPage.waitForResponse(resp => pattern.test(resp.url()), { timeout: options?.timeout }); 33 | } 34 | return mock; 35 | }); 36 | 37 | browser.addCommand('waitForNavigation', async (): Promise => { 38 | const currentUrl = await browser.getUrl(); 39 | await browser.waitUntil(async () => (await browser.getUrl()) !== currentUrl); 40 | return await browser.getUrl(); 41 | }); 42 | 43 | browser.addCommand('getPage', async (): Promise => { 44 | if (!('page' in browser.__propertiesObject__)) { 45 | const puppeteerBrowser = await browser.getPuppeteer(); 46 | const pages = await puppeteerBrowser.pages(); 47 | const controledPageUrl = await browser.getUrl(); 48 | const page = pages.find(p => p.url() === controledPageUrl); 49 | if (!page) { 50 | throw new Error('Error: not able to find the current page using Puppeteer'); 51 | } 52 | browser.__propertiesObject__['page'] = { value: page }; 53 | } 54 | return browser.__propertiesObject__['page'].value; 55 | }); 56 | -------------------------------------------------------------------------------- /apps/demo-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.strict.json", 3 | "compilerOptions": { 4 | "moduleResolution": "node", 5 | "module": "ESNext", 6 | "target": "es2022", 7 | "lib": [ 8 | "es2020", 9 | "dom" 10 | ], 11 | "types": [ 12 | "node", 13 | "jasmine", 14 | "@wdio/globals/types", 15 | "expect-webdriverio/jasmine", 16 | "@wdio/jasmine-framework" 17 | ], 18 | "noEmit": true, 19 | "skipLibCheck": true, 20 | "isolatedModules": true, 21 | "resolveJsonModule": true, 22 | "allowImportingTsExtensions": true, 23 | "allowSyntheticDefaultImports": true 24 | }, 25 | "include": [ 26 | "src", 27 | "wdio.config.ts" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /apps/demo-e2e/wdio.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/naming-convention */ 2 | 3 | import type { Options } from '@wdio/types'; 4 | 5 | const argv = process.argv.slice(2).reverse(); 6 | const getArgValue = (argName: string): unknown => { 7 | const itemIndex = argv.findIndex(arg => arg.includes(`--${argName}`)); 8 | const equalIndex = argv[itemIndex]?.indexOf('='); 9 | if (equalIndex && equalIndex !== -1) { 10 | return argv[itemIndex].substring(equalIndex + 1); 11 | } else if (!argv[itemIndex - 1].startsWith('--')) { 12 | return argv[itemIndex - 1]; 13 | } 14 | return (itemIndex !== -1) ? 'true' : undefined; 15 | }; 16 | 17 | const debug = getArgValue('debug') === 'true'; 18 | const headless = getArgValue('headless') === 'true'; 19 | 20 | /** 21 | * Configuration file documentation 22 | * https://webdriver.io/docs/configurationfile/ 23 | */ 24 | export const config: Options.Testrunner & { capabilities: unknown; } = { 25 | // ==================== 26 | // Runner Configuration 27 | // ==================== 28 | runner: 'local', 29 | tsConfigPath: './tsconfig.json', 30 | // ================== 31 | // Specify Test Files 32 | // ================== 33 | specs: [ 34 | './src/specs/**/*.ts' 35 | ], 36 | filesToWatch: [ 37 | './src/**/*.ts' 38 | ], 39 | // ============ 40 | // Capabilities 41 | // ============ 42 | maxInstances: debug ? 1 : 100, 43 | capabilities: [{ 44 | browserName: 'chrome', 45 | browserVersion: 'stable', 46 | acceptInsecureCerts: true, 47 | 'goog:chromeOptions': { 48 | args: [ 49 | ...(headless ? ['--headless', '--disable-gpu', '--disable-dev-shm-usage'] : []), 50 | ...(debug ? ['--auto-open-devtools-for-tabs'] : []) 51 | ] 52 | } 53 | }], 54 | // =================== 55 | // Test Configurations 56 | // =================== 57 | logLevel: debug ? 'debug' : 'warn', // trace | debug | info | warn | error | silent 58 | bail: 0, 59 | baseUrl: 'http://localhost', 60 | waitforTimeout: 10000, 61 | connectionRetryTimeout: 120000, 62 | connectionRetryCount: 3, 63 | services: [], 64 | framework: 'jasmine', 65 | reporters: ['spec'], 66 | jasmineOpts: { 67 | defaultTimeoutInterval: debug ? (24 * 60 * 60 * 1000) : 60000 68 | } 69 | }; 70 | -------------------------------------------------------------------------------- /apps/demo-idp/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | keycloak: 3 | container_name: badisi-auth-js-demo-idp 4 | image: quay.io/keycloak/keycloak:legacy 5 | environment: 6 | KEYCLOAK_USER: admin 7 | KEYCLOAK_PASSWORD: Pa55w0rd 8 | # KEYCLOAK_LOGLEVEL: DEBUG 9 | # WILDFLY_LOGLEVEL: DEBUG 10 | KEYCLOAK_IMPORT: /tmp/realm-config/demo-realm.json 11 | volumes: 12 | - ./demo-realm.json:/tmp/realm-config/demo-realm.json 13 | # - ./:/tmp/realm-config 14 | ports: 15 | - 8080:8080 16 | -------------------------------------------------------------------------------- /apps/demo-idp/export-demo-realm.sh: -------------------------------------------------------------------------------- 1 | docker exec -it badisi-auth-js-demo-idp /opt/jboss/keycloak/bin/standalone.sh \ 2 | -Djboss.socket.binding.port-offset=100 -Dkeycloak.migration.action=export \ 3 | -Dkeycloak.migration.provider=singleFile \ 4 | -Dkeycloak.migration.realmName=demo \ 5 | -Dkeycloak.migration.usersExportStrategy=REALM_FILE \ 6 | -Dkeycloak.migration.file=/tmp/realm-config/demo-realm-exported.json 7 | -------------------------------------------------------------------------------- /apps/demo-idp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-idp", 3 | "private": true, 4 | "license": "GPL-3.0-only", 5 | "scripts": { 6 | "start": "docker compose --file='docker-compose.yml' up" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /apps/website/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /apps/website/docs/api/angular/auth-guard.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: AuthGuard 3 | --- 4 | 5 | :::note 6 | Coming soon.. 7 | ::: 8 | -------------------------------------------------------------------------------- /apps/website/docs/api/angular/auth-interceptor.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: AuthInterceptor 3 | --- 4 | 5 | :::note 6 | Coming soon.. 7 | ::: 8 | -------------------------------------------------------------------------------- /apps/website/docs/api/angular/auth-service.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: AuthService 3 | --- 4 | 5 | :::note 6 | Coming soon.. 7 | ::: 8 | -------------------------------------------------------------------------------- /apps/website/docs/api/mobile.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Mobile 3 | --- 4 | 5 | :::note 6 | Coming soon.. 7 | ::: 8 | -------------------------------------------------------------------------------- /apps/website/docs/api/vanilla-js/auth-manager.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: AuthManager 3 | --- 4 | 5 | :::note 6 | Coming soon.. 7 | ::: 8 | -------------------------------------------------------------------------------- /apps/website/docs/getting-started/configuration.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Configuration 3 | --- 4 | 5 | import Tabs from '@theme/Tabs'; 6 | import TabItem from '@theme/TabItem'; 7 | 8 | 9 | :::note 10 | Draft document.. 11 | ::: 12 |
13 | 14 | 15 | 16 | 17 | ```js 18 | import { initAuth } from '@badisi/auth-js'; 19 | 20 | await initAuth(settings: AuthSettings); 21 | ``` 22 | 23 | 24 | 25 | 26 | ```ts 27 | import { initAuth } from '@badisi/ngx-auth'; 28 | 29 | await initAuth(settings: AuthSettings); 30 | ``` 31 | 32 | 33 | 34 | 35 | 36 | ## Global 37 | 38 | #### `authorityUrl*` 39 | > **type**: string
40 | > **required** 41 | 42 | #### `clientId*` 43 | > **type**: string
44 | > **required** 45 | 46 | #### `loginRequired` 47 | > **type**: boolean
48 | > **default**: true 49 | 50 | #### `retrieveUserSession` 51 | > **type**: boolean
52 | > **default**: true 53 | 54 | #### `loadUserInfo` 55 | > **type**: boolean
56 | > **default**: false 57 | 58 | #### `automaticSilentRenew` 59 | > **type**: boolean
60 | > **default**: true 61 | 62 | #### `desktopNavigationType` 63 | > **type**: enum - *DesktopNavigation.(REDIRECT, POPUP)*
64 | > **default**: REDIRECT 65 | 66 | #### `scope` 67 | > **type**: string
68 | > **default**: "openid profile email phone" 69 | 70 | #### `logLevel` 71 | > **type**: enum - *Log.(NONE, ERROR, WARN, INFO, DEBUG)*
72 | > **default**: NONE 73 | 74 | #### `internal` 75 | > **type**: UserManagerSettings
76 | 77 | 78 | ## Angular 79 | 80 | #### `automaticInjectToken` 81 | > **type**: boolean or custom object
82 | > **default**: any hostname or pathname that starts with 'api' 83 | 84 | ```ts title="Custom object example" 85 | automaticInjectToken: { 86 | include: (url: string): boolean => url?.includes('user'), 87 | exclude: [ 88 | '/public-api', 89 | /^\/my-custom-api\/.*$/gm 90 | ] 91 | } 92 | ``` 93 | 94 | #### `automaticLoginOn401` 95 | > **type**: boolean
96 | > **default**: true 97 | 98 | #### `authGuardRedirectUrl` 99 | > **type**: string
100 | 101 | 102 | ## Mobile 103 | 104 | #### `mobileScheme` 105 | > **type**: string
106 | -------------------------------------------------------------------------------- /apps/website/docs/getting-started/intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | --- 4 | 5 | :::note 6 | Coming soon.. 7 | ::: 8 | -------------------------------------------------------------------------------- /apps/website/docs/getting-started/mobile.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Mobile 3 | --- 4 | 5 | ### Installation 6 | 7 | :::note 8 | Coming soon.. 9 | ::: 10 | -------------------------------------------------------------------------------- /apps/website/docs/getting-started/playground.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Playground 3 | --- 4 | 5 | :::note 6 | Draft document.. 7 | ::: 8 | 9 |
10 | 11 | Url: demo site 12 | 13 | ```js title="Auth0/Zitadel - demo account" 14 | Username: demo 15 | Password: Pa55w0rd! 16 | ``` 17 | -------------------------------------------------------------------------------- /apps/website/docs/getting-started/providers.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Providers 3 | --- 4 | 5 | :::note 6 | Draft document.. 7 | ::: 8 |
9 | 10 | Authentication providers *(ie. Keycloak, Auth0, etc..)* should be configured this way: 11 | 12 | #### Allowed Web Origins 13 | ``` 14 | http://localhost:4200 15 | ``` 16 | 17 | #### Allowed Callback URLs 18 | ``` 19 | http://localhost:4200/?oidc-callback=login 20 | http://localhost:4200/oidc/callback/popup_redirect.html 21 | http://localhost:4200/oidc/callback/silent_redirect.html 22 | demo-app://localhost/?oidc-callback=login (for mobile) 23 | ``` 24 | 25 | #### Allowed Logout URLs 26 | ``` 27 | http://localhost:4200/?oidc-callback=logout 28 | http://localhost:4200/oidc/callback/popup_redirect.html 29 | demo-app://localhost/?oidc-callback=logout (for mobile) 30 | 31 | ``` 32 | 33 | #### Grants 34 | ``` 35 | Authorization Code 36 | Refresh Token 37 | ``` 38 | -------------------------------------------------------------------------------- /apps/website/docs/getting-started/usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Usage 3 | --- 4 | 5 | :::note 6 | Coming soon.. 7 | ::: 8 | -------------------------------------------------------------------------------- /apps/website/docs/getting-started/vanilla-js.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: VanillaJS 3 | --- 4 | 5 | import Tabs from '@theme/Tabs'; 6 | import TabItem from '@theme/TabItem'; 7 | 8 | 9 | This guide explains how to set up your Vanilla javascript project to begin using [`@badisi/auth-js`][auth-js]. 10 | 11 | :::info Before using this library 12 | Make sure you properly configured your 👉 [Authentication Provider](providers). 13 | ::: 14 | 15 | 16 | ### Installation 17 | 18 | 1. Install the library from the **NPM repository** 19 | 20 | 21 | 22 | 23 | ```shell 24 | npm install @badisi/auth-js --save 25 | ``` 26 | 27 | 28 | 29 | 30 | ```shell 31 | yarn add @badisi/auth-js 32 | ``` 33 | 34 | 35 | 36 | 37 | 2. ... 38 | 39 | :::note 40 | Coming soon.. 41 | ::: 42 | 43 | 44 | 45 | 46 | [auth-js]: https://github.com/badisi/auth-js/tree/main/libs/auth-js 47 | -------------------------------------------------------------------------------- /apps/website/docs/getting-started/vue-js.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Vue.js 3 | --- 4 | 5 | import Tabs from '@theme/Tabs'; 6 | import TabItem from '@theme/TabItem'; 7 | 8 | 9 | This guide explains how to set up your Vue.js project to begin using [`@badisi/auth-vue`][auth-vue]. 10 | 11 | :::info Before using this library 12 | Make sure you properly configured your 👉 [Authentication Provider](providers). 13 | ::: 14 | 15 | 16 | ### Installation 17 | 18 | 1. Install the library from the **NPM repository** 19 | 20 | 21 | 22 | 23 | ```shell 24 | npm install @badisi/auth-vue --save 25 | ``` 26 | 27 | 28 | 29 | 30 | ```shell 31 | yarn add @badisi/auth-vue 32 | ``` 33 | 34 | 35 | 36 | 37 | 2. ... 38 | 39 | :::note 40 | Coming soon.. 41 | ::: 42 | 43 | 44 | 45 | 46 | [auth-vue]: https://github.com/badisi/auth-js/tree/main/libs/auth-vue 47 | -------------------------------------------------------------------------------- /apps/website/docs/guides/guides.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Guides 3 | --- 4 | 5 | :::note 6 | Coming soon.. 7 | ::: 8 | -------------------------------------------------------------------------------- /apps/website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "website", 3 | "private": true, 4 | "license": "GPL-3.0-only", 5 | "scripts": { 6 | "start": "docusaurus start --host 0.0.0.0", 7 | "serve": "docusaurus serve --dir=../../dist/website", 8 | "build": "docusaurus build --out-dir=../../dist/website", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "write-translations": "docusaurus write-translations", 13 | "write-heading-ids": "docusaurus write-heading-ids" 14 | }, 15 | "dependencies": { 16 | "@docusaurus/core": "3.8.1", 17 | "@docusaurus/faster": "3.8.1", 18 | "@docusaurus/preset-classic": "3.8.1", 19 | "@docusaurus/tsconfig": "3.8.1", 20 | "@easyops-cn/docusaurus-search-local": "^0.51.1" 21 | }, 22 | "devDependencies": { 23 | "autoprefixer": "^10.4.21", 24 | "postcss": "^8.5.6", 25 | "tailwindcss": "^4.1.11", 26 | "@tailwindcss/postcss": "^4.1.11" 27 | }, 28 | "browserslist": { 29 | "production": [ 30 | ">0.5%", 31 | "not dead", 32 | "not op_mini all" 33 | ], 34 | "development": [ 35 | "last 1 chrome version", 36 | "last 1 firefox version", 37 | "last 1 safari version" 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /apps/website/sidebars.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | /** 4 | * Creating a sidebar enables you to: 5 | - create an ordered group of docs 6 | - render a sidebar for each doc of that group 7 | - provide next/previous navigation 8 | 9 | The sidebars can be generated from the filesystem, or explicitly defined here. 10 | 11 | Create as many sidebars as you want. 12 | */ 13 | 14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 15 | const sidebars = { 16 | // By default, Docusaurus generates a sidebar from the docs folder structure 17 | // tutorialSidebar: [{ type: 'autogenerated', dirName: '.' }] 18 | 19 | docsSidebar: [ 20 | { 21 | label: 'Introduction', 22 | type: 'doc', 23 | id: 'getting-started/intro' 24 | }, 25 | { 26 | label: 'Getting started', 27 | type: 'category', 28 | collapsed: false, 29 | items: [ 30 | 'getting-started/vanilla-js', 31 | 'getting-started/angular', 32 | 'getting-started/vue-js', 33 | 'getting-started/mobile', 34 | 'getting-started/providers' 35 | ] 36 | }, 37 | { 38 | label: 'Configuration', 39 | type: 'doc', 40 | id: 'getting-started/configuration' 41 | }, 42 | { 43 | label: 'Usage', 44 | type: 'doc', 45 | id: 'getting-started/usage' 46 | }, 47 | { 48 | label: 'Playground', 49 | type: 'doc', 50 | id: 'getting-started/playground' 51 | } 52 | ], 53 | 54 | guidesSidebar: [ 55 | { 56 | label: 'Guide', 57 | type: 'doc', 58 | id: 'guides/guides' 59 | } 60 | ], 61 | 62 | apisSidebar: [ 63 | { 64 | label: 'VanillaJS', 65 | type: 'category', 66 | collapsed: false, 67 | items: [ 68 | 'api/vanilla-js/auth-manager' 69 | ] 70 | }, 71 | { 72 | label: 'Angular', 73 | type: 'category', 74 | collapsed: false, 75 | items: [ 76 | 'api/angular/auth-service', 77 | 'api/angular/auth-guard', 78 | 'api/angular/auth-interceptor' 79 | ] 80 | }, 81 | { 82 | label: 'Mobile', 83 | type: 'doc', 84 | id: 'api/mobile' 85 | } 86 | ] 87 | }; 88 | 89 | export default sidebars; 90 | -------------------------------------------------------------------------------- /apps/website/src/components/Intro.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Link from '@docusaurus/Link'; 3 | import useBaseUrl from '@docusaurus/useBaseUrl'; 4 | import ShieldSvg from '@site/static/assets/svg/shield.svg'; 5 | 6 | const Intro = () => { 7 | return ( 8 |
9 |
10 | 11 | 12 |
13 |

14 | Authentication 15 |
16 | for the Web. 17 |

18 |
19 |
20 |
21 | 22 |

23 | Secure your web applications in seconds by 24 |
leveraging the latest{' '} 25 | security standards
26 | and best practices. 27 |

28 | 29 |
30 | 33 | Get Started   34 | 35 | 38 | Playground 39 | 40 |
41 |
42 |
43 | ); 44 | }; 45 | 46 | export default Intro; 47 | -------------------------------------------------------------------------------- /apps/website/src/css/not-found.css: -------------------------------------------------------------------------------- 1 | .not-found { 2 | text-align: center; 3 | } 4 | 5 | .not-found a { 6 | cursor: pointer; 7 | transition: 0.3s color; 8 | } 9 | 10 | .not-found a.github { 11 | font-weight: bold; 12 | } 13 | 14 | .not-found a.home { 15 | font-weight: 500; 16 | } 17 | -------------------------------------------------------------------------------- /apps/website/src/css/search.css: -------------------------------------------------------------------------------- 1 | [class^='navbarSearchContainer'] { 2 | padding: 0 !important; 3 | } 4 | 5 | [class^='navbarSearchContainer'] input.navbar__search-input { 6 | outline: none; 7 | height: 36px; 8 | font-size: 15px; 9 | } 10 | [data-theme='light'] [class^='navbarSearchContainer'] input.navbar__search-input { 11 | color: #1c1e21; 12 | } 13 | [data-theme='light'] [class^='navbarSearchContainer'] input.navbar__search-input::placeholder { 14 | color: #606770; 15 | } 16 | [data-theme='dark'] [class^='navbarSearchContainer'] input.navbar__search-input { 17 | color: white; 18 | } 19 | [data-theme='dark'] [class^='navbarSearchContainer'] input.navbar__search-input::placeholder { 20 | color: white; 21 | } 22 | [class^='navbarSearchContainer'] input.navbar__search-input:hover, 23 | [class^='navbarSearchContainer'] input.navbar__search-input:focus { 24 | box-shadow: inset 0 0 0 2px var(--ifm-color-primary); 25 | transition: box-shadow 150ms ease; 26 | cursor: text; 27 | } 28 | -------------------------------------------------------------------------------- /apps/website/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Layout from '@theme/Layout'; 3 | 4 | import Intro from '../components/Intro'; 5 | import Features from '../components/Features'; 6 | import Frameworks from '../components/Frameworks'; 7 | 8 | const Home = (): React.JSX.Element => { 9 | return ( 10 | 11 |
12 | 13 | 14 | 15 |
16 |
17 | ); 18 | }; 19 | 20 | export default Home; 21 | -------------------------------------------------------------------------------- /apps/website/src/theme/Navbar/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, type ReactNode } from 'react'; 2 | import Navbar from '@theme-original/Navbar'; 3 | import type NavbarType from '@theme/Navbar'; 4 | import type { WrapperProps } from '@docusaurus/types'; 5 | 6 | type Props = WrapperProps; 7 | 8 | export default function NavbarWrapper(props: Props): ReactNode { 9 | useEffect(() => { 10 | const handleScroll = () => { 11 | const nav = document.querySelector('nav.navbar'); 12 | if (nav) { 13 | if (window.scrollY > 0) { 14 | nav.classList.add('navbar--scrolled'); 15 | } else { 16 | nav.classList.remove('navbar--scrolled'); 17 | } 18 | } 19 | }; 20 | 21 | window.addEventListener('scroll', handleScroll); 22 | handleScroll(); // initial check 23 | 24 | return () => window.removeEventListener('scroll', handleScroll); 25 | }, []); 26 | 27 | return ; 28 | } 29 | -------------------------------------------------------------------------------- /apps/website/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/website/static/.nojekyll -------------------------------------------------------------------------------- /apps/website/static/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badisi/auth-js/24107615ff7481a57b992ba0de162036ca1d655a/apps/website/static/assets/favicon.ico -------------------------------------------------------------------------------- /apps/website/static/assets/svg/angular.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/website/static/assets/svg/code.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/website/static/assets/svg/globe.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/website/static/assets/svg/hexagons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /apps/website/static/assets/svg/javascript.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/website/static/assets/svg/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 🛡️ 3 | -------------------------------------------------------------------------------- /apps/website/static/assets/svg/puzzle.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/website/static/assets/svg/shield-check.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/website/static/assets/svg/shield.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/website/static/assets/svg/smartphone.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/website/static/assets/svg/thumbs-up.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/website/static/assets/svg/vue-js.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/website/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@docusaurus/tsconfig", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import hug from '@hug/eslint-config'; 2 | 3 | export default [ 4 | ...(await hug.configs.moderate), 5 | { 6 | ignores: [ 7 | '**/demo-realm.json', 8 | '**/capacitor.config.ts', 9 | '**/jest.config.ts' 10 | ] 11 | } 12 | ]; 13 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | import { getJestProjectsAsync } from '@nx/jest'; 2 | 3 | export default async () => ({ 4 | projects: await getJestProjectsAsync() 5 | }); 6 | -------------------------------------------------------------------------------- /jest.preset.js: -------------------------------------------------------------------------------- 1 | import nxPreset from '@nx/jest/preset.js'; 2 | 3 | export default nxPreset; 4 | -------------------------------------------------------------------------------- /libs/auth-js/@types/mobile/index.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/naming-convention */ 2 | 3 | import type { AppPlugin } from '@capacitor/app'; 4 | import type { BrowserPlugin } from '@capacitor/browser'; 5 | import type { CapacitorGlobal } from '@capacitor/core'; 6 | import type { PreferencesPlugin } from '@capacitor/preferences'; 7 | import type { Cordova } from '@types/Cordova'; 8 | import type { SecureStoragePluginPlugin } from 'capacitor-secure-storage-plugin'; 9 | 10 | declare global { 11 | interface Window { 12 | // Cordova 13 | cordova?: Cordova; 14 | phonegap?: unknown; 15 | PhoneGap?: unknown; 16 | handleOpenURL?: (url: string) => void; 17 | 18 | // Capacitor 19 | Capacitor?: CapacitorGlobal & { 20 | Plugins: { 21 | App: AppPlugin; 22 | Browser: BrowserPlugin; 23 | Storage?: PreferencesPlugin; // StoragePlugin was renamed PreferencesPlugin in @capacitor@4.x 24 | Preferences?: PreferencesPlugin; 25 | SecureStoragePlugin?: SecureStoragePluginPlugin; 26 | }; 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /libs/auth-js/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.1.0 (2025-04-07) 2 | 3 | ### 🚀 Features 4 | 5 | - 🔥 **interceptor:** auth interceptor is now part of `auth-js` ([265a501](https://github.com/Badisi/auth-js/commit/265a501)) 6 | - 🔥 **guard:** auth guard is now part of `auth-js` ([ce079fd](https://github.com/Badisi/auth-js/commit/ce079fd)) 7 | - **subscription:** add `once` option ([a688537](https://github.com/Badisi/auth-js/commit/a688537)) 8 | 9 | ### ❤️ Thank You 10 | 11 | - Badisi @Badisi 12 | -------------------------------------------------------------------------------- /libs/auth-js/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # @badisi/auth-js 4 | 5 | 🛡️ Authentication and authorization support for web based desktop and mobile applications. 6 | 7 | [![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)][pullrequest] 8 | [![docs site](https://img.shields.io/badge/site-docs-ed6e55)][docs-site] 9 | [![playground site](https://img.shields.io/badge/site-playground-ed6e55)][playground-site] 10 | [![license](https://img.shields.io/npm/l/@badisi/auth-js.svg?color=ff69b4)][license] 11 | 12 | [![npm version](https://img.shields.io/npm/v/@badisi/auth-js.svg?color=blue&logo=npm)][npm] 13 | [![npm downloads](https://img.shields.io/npm/dw/@badisi/auth-js.svg?color=7986CB&logo=npm)][npm-dl] 14 | [![build status](https://img.shields.io/github/actions/workflow/status/badisi/auth-js/ci_test_auth-js.yml?logo=github)][ci-tests] 15 | 16 |
17 | 18 |
19 | 20 | 21 | ## Getting started 22 | 23 | 👉 Learn about it on the 📚 [docs site][docs-site]. 24 | 25 | 🎈 Play with it on the [demo site][playground-site]. 26 | 27 | 28 | ## Development 29 | 30 | See the [developer docs][developer]. 31 | 32 | 33 | ## Contributing 34 | 35 | #### > Want to Help ? 36 | 37 | Want to file a bug, contribute some code or improve documentation ? Excellent! 38 | 39 | But please read up first on the guidelines for [contributing][contributing], and learn about submission process, coding rules and more. 40 | 41 | #### > Code of Conduct 42 | 43 | Please read and follow the [Code of Conduct][codeofconduct] and help me keep this project open and inclusive. 44 | 45 | 46 | 47 | 48 | [npm]: https://www.npmjs.com/package/@badisi/auth-js 49 | [npm-dl]: https://npmcharts.com/compare/@badisi/auth-js?minimal=true 50 | [ci-tests]: https://github.com/badisi/auth-js/actions/workflows/ci_test_auth-js.yml 51 | [pullrequest]: https://github.com/badisi/auth-js/blob/main/CONTRIBUTING.md#-submitting-a-pull-request-pr 52 | [license]: https://github.com/badisi/auth-js/blob/main/LICENSE 53 | [developer]: https://github.com/badisi/auth-js/blob/main/DEVELOPER.md 54 | [contributing]: https://github.com/badisi/auth-js/blob/main/CONTRIBUTING.md 55 | [codeofconduct]: https://github.com/badisi/auth-js/blob/main/CODE_OF_CONDUCT.md 56 | [docs-site]: https://badisi.github.io/auth-js/getting-started/vanilla-js 57 | [playground-site]: https://badisi.github.io/auth-js/demo-app/auth-js 58 | -------------------------------------------------------------------------------- /libs/auth-js/build.mjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | import cpy from 'cpy'; 4 | import { readFileSync } from 'node:fs'; 5 | import { dirname, resolve as pathResolve } from 'node:path'; 6 | import { fileURLToPath } from 'node:url'; 7 | 8 | import buildLib from '../../scripts/build-lib.mjs'; 9 | 10 | const __dirname = dirname(fileURLToPath(import.meta.url)); 11 | const pkgJson = JSON.parse(readFileSync(pathResolve(__dirname, 'package.json'), { encoding: 'utf-8' })); 12 | const distPath = pathResolve(__dirname, '../../dist/auth-js'); 13 | 14 | await buildLib({ 15 | packageName: pkgJson.name, 16 | distPath, 17 | tsconfigPath: pathResolve(__dirname, 'tsconfig.lib.json'), 18 | absWorkingDir: __dirname, 19 | entryPoints: [ 20 | { name: 'core', path: pathResolve(__dirname, 'core', 'index.ts') }, 21 | { name: 'oidc', path: pathResolve(__dirname, 'oidc', 'index.ts') } 22 | ], 23 | buildOptions: { 24 | esm: true, 25 | cjs: true, 26 | browser: 'AuthJs', 27 | externals: Object.keys({ 28 | ...pkgJson.dependencies, 29 | ...pkgJson.peerDependencies 30 | }) 31 | }, 32 | copyAssets: async () => { 33 | await cpy('libs/auth-js/oidc/assets', pathResolve(distPath, 'oidc', 'assets'), { flat: true }); 34 | await cpy('libs/auth-js/package.json', distPath, { flat: true }); 35 | await cpy('libs/auth-js/CHANGELOG.md', distPath, { flat: true }); 36 | await cpy('libs/auth-js/README.md', distPath, { flat: true }); 37 | await cpy('LICENSE', distPath, { flat: true }); 38 | await cpy('node_modules/oidc-client-ts/LICENSE', pathResolve(distPath, 'browser', 'oidc'), { 39 | rename: '3rdpartylicenses.txt', 40 | flat: true 41 | }); 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /libs/auth-js/core/auth-manager.ts: -------------------------------------------------------------------------------- 1 | import type { AuthGuardOptions } from './models/auth-guard-options.model'; 2 | import type { AuthSettings } from './models/auth-settings.model'; 3 | 4 | export abstract class AuthManager { 5 | public abstract init(settings: T): Promise; 6 | public abstract login(...args: unknown[]): Promise; 7 | public abstract logout(...args: unknown[]): Promise; 8 | public abstract getSettings(): T | undefined; 9 | public abstract isAuthenticated(): Promise; 10 | public abstract runGuard(toUrl: string, options?: AuthGuardOptions): Promise; 11 | } 12 | -------------------------------------------------------------------------------- /libs/auth-js/core/auth-subscriptions.ts: -------------------------------------------------------------------------------- 1 | import type { AuthSubscriber } from './models/auth-subscriber.model'; 2 | import type { AuthSubscriberOptions } from './models/auth-subscriber-options.model'; 3 | import type { AuthSubscription } from './models/auth-subscription.model'; 4 | 5 | /** 6 | * @internal 7 | */ 8 | interface InternalAuthSubscription { 9 | subscriber: AuthSubscriber; 10 | options?: AuthSubscriberOptions; 11 | } 12 | 13 | /** 14 | * TODO: 15 | */ 16 | export class AuthSubscriptions { 17 | #subscriptions: InternalAuthSubscription[] = []; 18 | #lastNotifiedValue?: T; 19 | 20 | public add(subscriber: AuthSubscriber, options?: AuthSubscriberOptions): AuthSubscription { 21 | const subscription = { subscriber, options }; 22 | this.#subscriptions.push(subscription); 23 | if (this.#lastNotifiedValue) { 24 | void subscriber(...this.#lastNotifiedValue); 25 | if (options?.once) { 26 | this.unsubscribe(subscription); 27 | } 28 | } 29 | return { 30 | unsubscribe: (): void => { this.unsubscribe(subscription); } 31 | }; 32 | } 33 | 34 | public notify(...args: T): void { 35 | this.#lastNotifiedValue = args; 36 | this.#subscriptions.forEach(subscription => { 37 | void subscription.subscriber(...args); 38 | if (subscription.options?.once) { 39 | this.unsubscribe(subscription); 40 | } 41 | }); 42 | } 43 | 44 | public unsubscribe(subscription?: InternalAuthSubscription): void { 45 | if (subscription) { 46 | const index = this.#subscriptions.indexOf(subscription); 47 | if (index !== -1) { 48 | this.#subscriptions.splice(index, 1); 49 | } 50 | } else { 51 | this.#subscriptions = []; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /libs/auth-js/core/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license GPL-3.0-only 3 | * Package @badisi/auth-js 4 | * Released under GNU General Public License v3.0 only 5 | * SPDX-License-Identifier: GPL-3.0-only 6 | * Copyright (C) 2018 Badisi 7 | */ 8 | 9 | export type Optional = Pick, K> & Omit; 10 | 11 | export { AuthLogger, LogLevel } from './auth-logger'; 12 | export { AuthManager } from './auth-manager'; 13 | export { AuthSubscriptions } from './auth-subscriptions'; 14 | export { AuthUtils } from './auth-utils'; 15 | export { createAuthManager } from './main'; 16 | export type { AuthGuardOptions } from './models/auth-guard-options.model'; 17 | export type { AuthGuardValidator } from './models/auth-guard-validator.model'; 18 | export type { AuthSettings } from './models/auth-settings.model'; 19 | export type { AuthSubscriber } from './models/auth-subscriber.model'; 20 | export type { AuthSubscriberOptions } from './models/auth-subscriber-options.model'; 21 | export type { AuthSubscription } from './models/auth-subscription.model'; 22 | -------------------------------------------------------------------------------- /libs/auth-js/core/main.ts: -------------------------------------------------------------------------------- 1 | import type { AuthManager } from './auth-manager'; 2 | import type { AuthSettings } from './models/auth-settings.model'; 3 | 4 | export const createAuthManager = async < 5 | S extends AuthSettings = AuthSettings, 6 | M extends AuthManager = AuthManager 7 | >(settings: S, impl: (new () => M)): Promise => { 8 | const manager = new impl(); 9 | await manager.init(settings); 10 | return manager; 11 | }; 12 | -------------------------------------------------------------------------------- /libs/auth-js/core/models/auth-guard-options.model.ts: -------------------------------------------------------------------------------- 1 | import type { AuthGuardValidator } from './auth-guard-validator.model'; 2 | 3 | export interface AuthGuardOptions { 4 | validator?: AuthGuardValidator; 5 | fallbackUrl?: string; 6 | } 7 | -------------------------------------------------------------------------------- /libs/auth-js/core/models/auth-guard-validator.model.ts: -------------------------------------------------------------------------------- 1 | import type { AccessToken, UserProfile } from '@badisi/auth-js/oidc'; 2 | 3 | export type AuthGuardValidator = 4 | (userProfile?: UserProfile, accessToken?: AccessToken) => Promise | boolean | string; 5 | -------------------------------------------------------------------------------- /libs/auth-js/core/models/auth-settings.model.ts: -------------------------------------------------------------------------------- 1 | export interface AuthSettings { 2 | loginRequired?: boolean; 3 | authGuardFallbackUrl?: string; 4 | } 5 | -------------------------------------------------------------------------------- /libs/auth-js/core/models/auth-subscriber-options.model.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * TODO: 3 | */ 4 | export interface AuthSubscriberOptions { 5 | once: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /libs/auth-js/core/models/auth-subscriber.model.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * TODO: 3 | */ 4 | export type AuthSubscriber = (...args: T) => (Promise | void); 5 | -------------------------------------------------------------------------------- /libs/auth-js/core/models/auth-subscription.model.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * TODO: 3 | */ 4 | export interface AuthSubscription { 5 | unsubscribe: () => void; 6 | } 7 | -------------------------------------------------------------------------------- /libs/auth-js/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license GPL-3.0-only 3 | * Package @badisi/auth-js 4 | * Released under GNU General Public License v3.0 only 5 | * SPDX-License-Identifier: GPL-3.0-only 6 | * Copyright (C) 2018 Badisi 7 | */ 8 | 9 | export * from './core'; 10 | -------------------------------------------------------------------------------- /libs/auth-js/jest.config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | displayName: 'auth-js', 3 | preset: '../../jest.preset.js', 4 | testEnvironment: 'jsdom', 5 | transform: { 6 | // eslint-disable-next-line @typescript-eslint/naming-convention 7 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], 8 | }, 9 | moduleFileExtensions: ['ts', 'js', 'html'], 10 | coverageDirectory: '../../coverage/libs/auth-js', 11 | }; 12 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/assets/popup_redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/assets/silent_redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/default-settings.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable camelcase, @typescript-eslint/naming-convention */ 2 | 3 | import { LogLevel } from '../core'; 4 | import type { DefaultSettings } from './models/default-settings.model'; 5 | import { DesktopNavigation } from './models/desktop-navigation.enum'; 6 | 7 | export const REDIRECT_URL_KEY = 'auth-js:oidc_manager:redirect_url'; 8 | 9 | export const DEFAULT_SETTINGS: DefaultSettings = { 10 | loginRequired: false, 11 | retrieveUserSession: true, 12 | loadUserInfo: false, 13 | automaticSilentRenew: true, 14 | desktopNavigationType: DesktopNavigation.REDIRECT, 15 | scope: 'openid profile email phone', 16 | logLevel: LogLevel.NONE, 17 | automaticLoginOn401: true, 18 | automaticInjectToken: { 19 | include: (url: string): boolean => { 20 | const res = new URL(url, 'http://default-base'); 21 | return res.hostname.startsWith('api') || res.pathname.startsWith('/api') || false; 22 | } 23 | }, 24 | internal: { 25 | response_type: 'code', 26 | redirect_uri: '?oidc-callback=login', 27 | post_logout_redirect_uri: '?oidc-callback=logout', 28 | popup_redirect_uri: 'oidc/callback/popup_redirect.html', 29 | popup_post_logout_redirect_uri: 'oidc/callback/popup_redirect.html', 30 | silent_redirect_uri: 'oidc/callback/silent_redirect.html', 31 | mobileWindowPresentationStyle: 'popover' 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license GPL-3.0-only 3 | * Package @badisi/auth-js 4 | * Released under GNU General Public License v3.0 only 5 | * SPDX-License-Identifier: GPL-3.0-only 6 | * Copyright (C) 2018 Badisi 7 | */ 8 | 9 | import { AuthLogger } from '../core'; 10 | AuthLogger.init('@badisi/auth-js'); 11 | 12 | export type { 13 | AuthGuardOptions, AuthGuardValidator, AuthSubscriber, AuthSubscriberOptions, AuthSubscription, Optional 14 | } from '../core'; 15 | export { AuthManager, AuthSubscriptions, AuthUtils, LogLevel } from '../core'; 16 | export { initOidc } from './main'; 17 | export type { AccessToken } from './models/access-token.model'; 18 | export type { LoginArgs, LogoutArgs, RenewArgs, SigninMobileArgs, SignoutMobileArgs } from './models/args.model'; 19 | export { DesktopNavigation } from './models/desktop-navigation.enum'; 20 | export type { IdToken } from './models/id-token.model'; 21 | export type { InjectToken } from './models/inject-token.model'; 22 | export type { InjectTokenPattern } from './models/inject-token-pattern.model'; 23 | export type { MobileWindowParams } from './models/mobile-window-params.model'; 24 | export type { OIDCAuthSettings } from './models/oidc-auth-settings.model'; 25 | export { UserSession } from './models/user-session.model'; 26 | export { OIDCAuthManager } from './oidc-auth-manager'; 27 | export { OIDCAuthService } from './oidc-auth-service'; 28 | export type { UserProfile } from 'oidc-client-ts'; 29 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/main.ts: -------------------------------------------------------------------------------- 1 | import { createAuthManager } from '../core'; 2 | import type { OIDCAuthSettings } from './models/oidc-auth-settings.model'; 3 | import { OIDCAuthManager } from './oidc-auth-manager'; 4 | 5 | export const initOidc = async (settings: OIDCAuthSettings): Promise => 6 | await createAuthManager(settings, OIDCAuthManager); 7 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/mobile/mobile-navigator.ts: -------------------------------------------------------------------------------- 1 | import { AuthLogger } from '@badisi/auth-js'; 2 | 3 | import type { MobileWindowParams } from '../models/mobile-window-params.model'; 4 | import { MobileWindow } from './mobile-window'; 5 | 6 | const logger = new AuthLogger('MobileNavigator'); 7 | 8 | /** 9 | * @internal 10 | */ 11 | export class MobileNavigator { 12 | public prepare(redirectUrl: string, params: MobileWindowParams): MobileWindow { 13 | logger.debug('prepare'); 14 | return new MobileWindow(redirectUrl, params); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/models/access-token.model.ts: -------------------------------------------------------------------------------- 1 | import type { JwtClaims } from 'oidc-client-ts'; 2 | 3 | export type AccessToken = string | (JwtClaims & Record); 4 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/models/args.model.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | ExtraSigninRequestArgs, ExtraSignoutRequestArgs, IFrameWindowParams, PopupWindowParams, 3 | RedirectParams 4 | } from 'oidc-client-ts'; 5 | 6 | import type { DesktopNavigation } from './desktop-navigation.enum'; 7 | import type { MobileWindowParams } from './mobile-window-params.model'; 8 | 9 | export type LoginArgs = MobileWindowParams & PopupWindowParams & RedirectParams & Omit & { 10 | redirectUrl?: string; 11 | desktopNavigationType?: DesktopNavigation; 12 | }; 13 | 14 | export type LogoutArgs = MobileWindowParams & PopupWindowParams & RedirectParams & Omit & { 15 | redirectUrl?: string; 16 | desktopNavigationType?: DesktopNavigation; 17 | }; 18 | 19 | export type RenewArgs = IFrameWindowParams & ExtraSigninRequestArgs; 20 | 21 | export type SigninMobileArgs = MobileWindowParams & ExtraSigninRequestArgs; 22 | 23 | export type SignoutMobileArgs = MobileWindowParams & ExtraSignoutRequestArgs; 24 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/models/default-settings.model.ts: -------------------------------------------------------------------------------- 1 | import type { OIDCAuthSettings, Optional } from ".."; 2 | 3 | export type DefaultSettings = 4 | Optional & 8 | Required> & 17 | { 18 | internal: 19 | OIDCAuthSettings['internal'] & 20 | Required, 21 | 'response_type' | 22 | 'redirect_uri' | 23 | 'post_logout_redirect_uri' | 24 | 'popup_redirect_uri' | 25 | 'popup_post_logout_redirect_uri' | 26 | 'silent_redirect_uri' | 27 | 'mobileWindowPresentationStyle' 28 | >> 29 | }; 30 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/models/desktop-navigation.enum.ts: -------------------------------------------------------------------------------- 1 | export enum DesktopNavigation { 2 | REDIRECT = 'REDIRECT', 3 | POPUP = 'POPUP' 4 | } 5 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/models/id-token.model.ts: -------------------------------------------------------------------------------- 1 | import type { IdTokenClaims } from 'oidc-client-ts'; 2 | 3 | export type IdToken = string | (IdTokenClaims & Record); 4 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/models/inject-token-pattern.model.ts: -------------------------------------------------------------------------------- 1 | export type InjectTokenPattern = 2 | | (string | RegExp)[] 3 | | ((url: string) => boolean); 4 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/models/inject-token.model.ts: -------------------------------------------------------------------------------- 1 | import type { InjectTokenPattern } from "./inject-token-pattern.model"; 2 | 3 | export type InjectToken = 4 | | boolean 5 | | { include?: InjectTokenPattern; exclude?: InjectTokenPattern; }; 6 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/models/mobile-window-params.model.ts: -------------------------------------------------------------------------------- 1 | export interface MobileWindowParams { 2 | /** 3 | * A hex color to which the toolbar color is set. 4 | */ 5 | mobileWindowToolbarColor?: string; 6 | 7 | /** 8 | * iOS only: The presentation style of the browser. Defaults to 'popover'. 9 | * 10 | * Ignored on other platforms. 11 | */ 12 | mobileWindowPresentationStyle?: 'fullscreen' | 'popover'; 13 | 14 | /** 15 | * iOS only: The width the browser when using presentationStyle 'popover' on iPads. 16 | * 17 | * Ignored on other platforms. 18 | */ 19 | mobileWindowWidth?: number; 20 | 21 | /** 22 | * iOS only: The height the browser when using presentationStyle 'popover' on iPads. 23 | * 24 | * Ignored on other platforms. 25 | */ 26 | mobileWindowHeight?: number; 27 | } 28 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/models/oidc-auth-settings.model.ts: -------------------------------------------------------------------------------- 1 | import type { UserManagerSettings } from 'oidc-client-ts'; 2 | 3 | import type { AuthSettings as CoreAuthSettings, LogLevel } from '../../core'; 4 | import type { DesktopNavigation } from './desktop-navigation.enum'; 5 | import type { InjectToken } from './inject-token.model'; 6 | import type { MobileWindowParams } from './mobile-window-params.model'; 7 | 8 | // TODO: check if `monitorSession` and `revokeAccessTokenOnSignout` might be useful too ? 9 | type UsefulSettings = 'scope' | 'loadUserInfo' | 'automaticSilentRenew'; 10 | 11 | export interface OIDCAuthSettings extends CoreAuthSettings, Partial> { 12 | authorityUrl: string; 13 | clientId: string; 14 | mobileScheme?: string; 15 | retrieveUserSession?: boolean; 16 | desktopNavigationType?: DesktopNavigation; 17 | logLevel?: LogLevel; 18 | automaticLoginOn401?: boolean; 19 | automaticInjectToken?: InjectToken; 20 | internal?: Partial> & MobileWindowParams; 21 | } 22 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/models/user-session.model.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/naming-convention, camelcase */ 2 | 3 | export class UserSession { 4 | public expired?: boolean = void 0; 5 | public expires_in?: number = void 0; 6 | public expires_at?: number = void 0; 7 | 8 | public static deserialize(data: unknown): UserSession { 9 | const ref: UserSession = new UserSession(); 10 | const keys = Object.keys(ref); 11 | // eslint-disable-next-line no-loops/no-loops 12 | for (const key of keys) { 13 | ref[key as keyof UserSession] = (data as Record)[key] as (keyof UserSession & undefined); 14 | } 15 | return ref; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /libs/auth-js/oidc/oidc-auth-guard.ts: -------------------------------------------------------------------------------- 1 | import { type AuthGuardOptions, type AuthGuardValidator,AuthLogger } from '../core'; 2 | import type { OIDCAuthManager } from './oidc-auth-manager'; 3 | 4 | const logger = new AuthLogger('OIDCAuthGuard'); 5 | 6 | export class OIDCAuthGuard { 7 | #manager: OIDCAuthManager; 8 | 9 | public constructor(manager: OIDCAuthManager) { 10 | this.#manager = manager; 11 | } 12 | 13 | public async validate(toUrl: string, options?: AuthGuardOptions): Promise { 14 | let notAllowedUrl = options?.fallbackUrl ?? this.#manager.getSettings().authGuardFallbackUrl; 15 | notAllowedUrl = (notAllowedUrl?.trim() !== '') ? notAllowedUrl : undefined; 16 | 17 | const isAuthenticated = await this.#manager.isAuthenticated(); 18 | if (isAuthenticated) { 19 | const isAllowed = await this.#isAllowed(options?.validator); 20 | return !isAllowed && notAllowedUrl ? notAllowedUrl : isAllowed; 21 | } else { 22 | return notAllowedUrl ?? (await this.#manager.login({ redirectUrl: toUrl })); 23 | } 24 | } 25 | 26 | // ---- HELPER(s) ---- 27 | 28 | async #isAllowed(validator?: AuthGuardValidator): Promise { 29 | if (typeof validator === 'function') { 30 | const userProfile = await this.#manager.getUserProfile(); 31 | const decodedAccessToken = await this.#manager.getAccessTokenDecoded(); 32 | return await Promise.resolve(validator(userProfile, decodedAccessToken)); 33 | // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition 34 | } else if (validator) { 35 | logger.error('`authGuardValidator` must be a function'); 36 | return false; 37 | } 38 | return true; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /libs/auth-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@badisi/auth-js", 3 | "version": "1.1.0", 4 | "description": "Authentication and authorization support for web based desktop and mobile applications.", 5 | "homepage": "https://github.com/Badisi/auth-js/tree/main/libs/auth-js", 6 | "license": "GPL-3.0-only", 7 | "author": "Badisi", 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/Badisi/auth-js.git" 11 | }, 12 | "keywords": [ 13 | "ionic", 14 | "capacitor", 15 | "cordova", 16 | "hybrid", 17 | "authentication", 18 | "authorization", 19 | "oidc", 20 | "openidconnect", 21 | "openid", 22 | "security", 23 | "identity", 24 | "oauth2", 25 | "oauth", 26 | "auth", 27 | "authn", 28 | "web", 29 | "mobile" 30 | ], 31 | "sideEffects": false, 32 | "scripts": { 33 | "lint": "nx run auth-js:lint", 34 | "test": "nx run auth-js:test", 35 | "test:ci": "nx run auth-js:test", 36 | "build": "nx run auth-js:build", 37 | "build:nx": "npm run build", 38 | "release": "node ../../scripts/release.mjs --projects=auth-js --verbose", 39 | "release:dry-run": "npm run release -- --dry-run" 40 | }, 41 | "dependencies": { 42 | "jwt-decode": "^3.1.2", 43 | "lodash-es": "^4.17.21", 44 | "oidc-client-ts": "2.4.0" 45 | }, 46 | "devDependencies": { 47 | "@types/lodash-es": "^4.17.12", 48 | "@types/cordova": "^11.0.3" 49 | }, 50 | "publishConfig": { 51 | "access": "public" 52 | }, 53 | "exports": { 54 | ".": { 55 | "types": "./core/index.d.ts", 56 | "import": "./esm/core/index.js", 57 | "require": "./cjs/core/index.js", 58 | "browser": "./browser/core/index.min.js", 59 | "default": "./esm/core/index.js" 60 | }, 61 | "./oidc": { 62 | "types": "./oidc/index.d.ts", 63 | "import": "./esm/oidc/index.js", 64 | "require": "./cjs/oidc/index.js", 65 | "browser": "./browser/oidc/index.min.js", 66 | "default": "./esm/oidc/index.js" 67 | }, 68 | "./package.json": "./package.json" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /libs/auth-js/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "auth-js", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/auth-js", 5 | "prefix": "badisi", 6 | "projectType": "library", 7 | "tags": [], 8 | "targets": { 9 | "build": { 10 | "executor": "nx:run-commands", 11 | "outputs": [ 12 | "{workspaceRoot}/dist/auth-js" 13 | ], 14 | "options": { 15 | "commands": [ 16 | "node libs/auth-js/build.mjs" 17 | ], 18 | "color": true 19 | } 20 | }, 21 | "lint": { 22 | "executor": "@nx/eslint:lint" 23 | }, 24 | "test": { 25 | "executor": "@nx/jest:jest", 26 | "outputs": [ 27 | "{workspaceRoot}/coverage/{projectRoot}" 28 | ], 29 | "options": { 30 | "jestConfig": "libs/auth-js/jest.config.ts" 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /libs/auth-js/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "forceConsistentCasingInFileNames": true, 5 | "strict": true, 6 | "noImplicitOverride": true, 7 | "noImplicitReturns": true, 8 | "noFallthroughCasesInSwitch": true, 9 | "noPropertyAccessFromIndexSignature": true 10 | }, 11 | "files": [], 12 | "include": [], 13 | "references": [ 14 | { 15 | "path": "./tsconfig.lib.json" 16 | }, 17 | { 18 | "path": "./tsconfig.spec.json" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /libs/auth-js/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "outDir": "../../dist/auth-js", 6 | "declaration": true, 7 | "emitDeclarationOnly": true, 8 | "declarationMap": false, 9 | "sourceMap": false, 10 | "types": [] 11 | }, 12 | "exclude": [ 13 | "jest.config.ts", 14 | "**/*.spec.ts", 15 | "**/*.test.ts" 16 | ], 17 | "include": [ 18 | "./@types/mobile/index.d.ts", 19 | "**/*.ts" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /libs/auth-js/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": [ 7 | "jest", 8 | "node" 9 | ] 10 | }, 11 | "include": [ 12 | "jest.config.ts", 13 | "**/*.test.ts", 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /libs/auth-vue/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 (2025-04-07) 2 | 3 | ### 🚀 Features 4 | 5 | - **vue:** add support for `Vue.js` ([27138b4](https://github.com/Badisi/auth-js/commit/27138b4)) 6 | 7 | ### 🌱 Dependencies 8 | 9 | - **auth-js**: upgraded to `v1.1.0` 10 | 11 | ### ❤️ Thank You 12 | 13 | - Badisi @Badisi 14 | -------------------------------------------------------------------------------- /libs/auth-vue/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # @badisi/auth-vue 4 | 5 | 🛡️ Authentication and authorization support for Vue.js based desktop and mobile applications. 6 | 7 | [![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)][pullrequest] 8 | [![docs site](https://img.shields.io/badge/site-docs-ed6e55)][docs-site] 9 | [![playground site](https://img.shields.io/badge/site-playground-ed6e55)][playground-site] 10 | [![license](https://img.shields.io/npm/l/@badisi/auth-vue.svg?color=ff69b4)][license] 11 | 12 | [![npm version](https://img.shields.io/npm/v/@badisi/auth-vue.svg?color=blue&logo=npm)][npm] 13 | [![npm downloads](https://img.shields.io/npm/dw/@badisi/auth-vue.svg?color=7986CB&logo=npm)][npm-dl] 14 | [![build status](https://img.shields.io/github/actions/workflow/status/badisi/auth-js/ci_test_auth-vue.yml?logo=github)][ci-tests] 15 | 16 |
17 | 18 |
19 | 20 | 21 | ## Getting started 22 | 23 | 👉 Learn about it on the 📚 [docs site][docs-site]. 24 | 25 | 🎈 Play with it on the [demo site][playground-site]. 26 | 27 | 28 | ## Development 29 | 30 | See the [developer docs][developer]. 31 | 32 | 33 | ## Contributing 34 | 35 | #### > Want to Help ? 36 | 37 | Want to file a bug, contribute some code or improve documentation ? Excellent! 38 | 39 | But please read up first on the guidelines for [contributing][contributing], and learn about submission process, coding rules and more. 40 | 41 | #### > Code of Conduct 42 | 43 | Please read and follow the [Code of Conduct][codeofconduct] and help me keep this project open and inclusive. 44 | 45 | 46 | 47 | 48 | [npm]: https://www.npmjs.com/package/@badisi/auth-vue 49 | [npm-dl]: https://npmcharts.com/compare/@badisi/auth-vue?minimal=true 50 | [ci-tests]: https://github.com/badisi/auth-js/actions/workflows/ci_test_auth-vue.yml 51 | [pullrequest]: https://github.com/badisi/auth-js/blob/main/CONTRIBUTING.md#-submitting-a-pull-request-pr 52 | [license]: https://github.com/badisi/auth-js/blob/main/LICENSE 53 | [developer]: https://github.com/badisi/auth-js/blob/main/DEVELOPER.md 54 | [contributing]: https://github.com/badisi/auth-js/blob/main/CONTRIBUTING.md 55 | [codeofconduct]: https://github.com/badisi/auth-js/blob/main/CODE_OF_CONDUCT.md 56 | [docs-site]: https://badisi.github.io/auth-js/getting-started/vue-js 57 | [playground-site]: https://badisi.github.io/auth-js/demo-app/auth-vue 58 | -------------------------------------------------------------------------------- /libs/auth-vue/build.mjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | import cpy from 'cpy'; 4 | import { readFileSync } from 'node:fs'; 5 | import { dirname, resolve as pathResolve } from 'node:path'; 6 | import { fileURLToPath } from 'node:url'; 7 | 8 | import buildLib from '../../scripts/build-lib.mjs'; 9 | 10 | const __dirname = dirname(fileURLToPath(import.meta.url)); 11 | const pkgJson = JSON.parse(readFileSync(pathResolve(__dirname, 'package.json'), { encoding: 'utf-8' })); 12 | const distPath = pathResolve(__dirname, '../../dist/auth-vue'); 13 | 14 | await buildLib({ 15 | packageName: pkgJson.name, 16 | distPath, 17 | tsconfigPath: pathResolve(__dirname, 'tsconfig.lib.json'), 18 | absWorkingDir: __dirname, 19 | entryPoints: [ 20 | { name: 'core', path: pathResolve(__dirname, 'core', 'index.ts') }], 21 | buildOptions: { 22 | esm: true, 23 | cjs: true, 24 | browser: 'AuthVue', 25 | externals: Object.keys({ 26 | ...pkgJson.dependencies, 27 | ...pkgJson.peerDependencies 28 | }) 29 | }, 30 | copyAssets: async () => { 31 | await cpy('libs/auth-js/oidc/assets', pathResolve(distPath, 'oidc', 'assets'), { flat: true }); 32 | await cpy('libs/auth-vue/package.json', distPath, { flat: true }); 33 | await cpy('libs/auth-vue/CHANGELOG.md', distPath, { flat: true }); 34 | await cpy('libs/auth-vue/README.md', distPath, { flat: true }); 35 | await cpy('LICENSE', distPath, { flat: true }); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /libs/auth-vue/core/auth.guard.ts: -------------------------------------------------------------------------------- 1 | import type { AuthGuardOptions } from '@badisi/auth-js/oidc'; 2 | 3 | import { useAuthService } from './auth.service'; 4 | 5 | export const useAuthGuard = async (toUrl: string, options?: AuthGuardOptions): Promise => 6 | useAuthService().runGuard(toUrl, options); 7 | -------------------------------------------------------------------------------- /libs/auth-vue/core/auth.provider.ts: -------------------------------------------------------------------------------- 1 | import { initOidc } from '@badisi/auth-js/oidc'; 2 | import type { App, Plugin } from 'vue'; 3 | import type { Router } from 'vue-router'; 4 | 5 | import type { AuthSettings } from '.'; 6 | import { useAuthGuard } from './auth.guard'; 7 | import { AuthService } from './auth.service'; 8 | 9 | export const initAuth = async (settings: AuthSettings): Promise => { 10 | /** 11 | * Vue do not wait for a plugin to be installed if the installation is async. 12 | * So we have to get the authManager prior of the plugin installation phase, 13 | * to make sur any code that will use it later on, will actually get it. 14 | */ 15 | const authManager = await initOidc(settings); 16 | return { 17 | install: (app: App, { router }: { router: Router; }): void => { 18 | // Effectively adding authService to every component instance 19 | const authService = new AuthService(authManager, router); 20 | app.provide('$authService', authService); 21 | app.config.globalProperties.$authService = authService; 22 | 23 | // Add global router guard 24 | router.beforeEach(async (to) => { 25 | if (to.meta.authGuard) { 26 | return await useAuthGuard( 27 | to.fullPath, 28 | (typeof to.meta.authGuard === 'object') ? to.meta.authGuard : undefined 29 | ); 30 | } 31 | return true; 32 | }); 33 | }, 34 | }; 35 | }; 36 | -------------------------------------------------------------------------------- /libs/auth-vue/core/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-duplicate-imports, @typescript-eslint/no-empty-object-type */ 2 | 3 | /** 4 | * @license GPL-3.0-only 5 | * Package @badisi/auth-vue 6 | * Released under GNU General Public License v3.0 only 7 | * SPDX-License-Identifier: GPL-3.0-only 8 | * Copyright (C) 2018 Badisi 9 | */ 10 | 11 | // Initialize the logger 12 | import { AuthLogger } from '@badisi/auth-js'; 13 | AuthLogger.init('@badisi/auth-vue'); 14 | 15 | // @badisi/auth-js re-exports renamed 16 | import type { OIDCAuthManager, OIDCAuthSettings } from '@badisi/auth-js/oidc'; 17 | export interface AuthManager extends OIDCAuthManager {}; 18 | export interface AuthSettings extends OIDCAuthSettings {}; 19 | 20 | // @badisi/auth-js re-exports 21 | export type { 22 | AccessToken, AuthGuardOptions, AuthGuardValidator, IdToken, InjectToken, InjectTokenPattern, 23 | LoginArgs, LogoutArgs, MobileWindowParams, RenewArgs, SigninMobileArgs, SignoutMobileArgs, 24 | UserProfile 25 | } from '@badisi/auth-js/oidc'; 26 | export { AuthUtils, DesktopNavigation, LogLevel, UserSession } from '@badisi/auth-js/oidc'; 27 | 28 | // Library augmentations 29 | import type { AuthService } from './auth.service'; 30 | declare module 'vue' { 31 | interface ComponentCustomProperties { 32 | $authService: AuthService; 33 | } 34 | } 35 | import type { AuthGuardOptions } from '@badisi/auth-js/oidc'; 36 | declare module 'vue-router' { 37 | export interface RouteMeta { 38 | authGuard?: boolean | AuthGuardOptions; 39 | } 40 | } 41 | 42 | // Library exports 43 | export { useAuthGuard } from './auth.guard'; 44 | export { initAuth } from './auth.provider'; 45 | export { AuthService, useAuthService } from './auth.service'; 46 | -------------------------------------------------------------------------------- /libs/auth-vue/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license GPL-3.0-only 3 | * Package @badisi/auth-vue 4 | * Released under GNU General Public License v3.0 only 5 | * SPDX-License-Identifier: GPL-3.0-only 6 | * Copyright (C) 2018 Badisi 7 | */ 8 | 9 | export * from './core'; 10 | -------------------------------------------------------------------------------- /libs/auth-vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@badisi/auth-vue", 3 | "version": "1.0.0", 4 | "description": "Authentication and authorization support for Vue.js based desktop and mobile applications.", 5 | "homepage": "https://github.com/Badisi/auth-js/tree/main/libs/auth-vue", 6 | "license": "GPL-3.0-only", 7 | "author": "Badisi", 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/Badisi/auth-js.git" 11 | }, 12 | "keywords": [ 13 | "vue", 14 | "vue.js", 15 | "ionic", 16 | "capacitor", 17 | "cordova", 18 | "hybrid", 19 | "authentication", 20 | "authorization", 21 | "oidc", 22 | "openidconnect", 23 | "openid", 24 | "security", 25 | "identity", 26 | "oauth2", 27 | "oauth", 28 | "auth", 29 | "authn", 30 | "web", 31 | "mobile" 32 | ], 33 | "scripts": { 34 | "lint": "nx run auth-vue:lint", 35 | "test": "", 36 | "test:ci": "", 37 | "build": "nx run auth-vue:build", 38 | "build:nx": "npm run build", 39 | "release": "node ../../scripts/release.mjs --projects=auth-vue --verbose", 40 | "release:dry-run": "npm run release -- --dry-run" 41 | }, 42 | "dependencies": { 43 | "@badisi/auth-js": "1.1.0" 44 | }, 45 | "peerDependencies": { 46 | "vue": ">= 3", 47 | "vue-router": ">= 4" 48 | }, 49 | "publishConfig": { 50 | "access": "public" 51 | }, 52 | "exports": { 53 | ".": { 54 | "types": "./core/index.d.ts", 55 | "import": "./esm/core/index.js", 56 | "require": "./cjs/core/index.js", 57 | "browser": "./browser/core/index.min.js", 58 | "default": "./esm/core/index.js" 59 | }, 60 | "./package.json": "./package.json" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /libs/auth-vue/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "auth-vue", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/auth-vue", 5 | "prefix": "badisi", 6 | "projectType": "library", 7 | "tags": [], 8 | "targets": { 9 | "build": { 10 | "executor": "nx:run-commands", 11 | "dependsOn": [ 12 | "^build" 13 | ], 14 | "outputs": [ 15 | "{workspaceRoot}/dist/auth-vue" 16 | ], 17 | "options": { 18 | "commands": [ 19 | "node libs/auth-vue/build.mjs" 20 | ], 21 | "color": true 22 | } 23 | }, 24 | "lint": { 25 | "executor": "@nx/eslint:lint" 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /libs/auth-vue/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "forceConsistentCasingInFileNames": true, 5 | "strict": true, 6 | "noImplicitOverride": true, 7 | "noImplicitReturns": true, 8 | "noFallthroughCasesInSwitch": true, 9 | "noPropertyAccessFromIndexSignature": true 10 | }, 11 | "files": [], 12 | "include": [], 13 | "references": [ 14 | { 15 | "path": "./tsconfig.lib.json" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /libs/auth-vue/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/auth-vue", 5 | "declaration": true, 6 | "emitDeclarationOnly": true, 7 | "declarationMap": false, 8 | "sourceMap": false, 9 | "types": [] 10 | }, 11 | "exclude": [], 12 | "include": [ 13 | "../auth-js/@types/mobile/index.d.ts", 14 | "**/*.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /libs/ngx-auth/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 4.0.0 (2025-04-07) 2 | 3 | ### ⚠️ Breaking Changes 4 | 5 | - `angular >= 15` is now required by the **library** 6 | - `angular >= 16` is now required by the **schematic** 7 | 8 | ### 🚀 Features 9 | 10 | - 🔥 **interceptor:** auth interceptor is now part of `auth-js` ([265a501](https://github.com/Badisi/auth-js/commit/265a501)) 11 | - 🔥 **guard:** auth guard is now part of `auth-js` ([ce079fd](https://github.com/Badisi/auth-js/commit/ce079fd)) 12 | - 🔥 **standalone:** add support for `standalone` ([2b98113](https://github.com/Badisi/auth-js/commit/2b98113)) 13 | - **schematics:** add support for apps that use platformBrowser ([67d7e5a](https://github.com/Badisi/auth-js/commit/67d7e5a)) 14 | 15 | ### 🌱 Dependencies 16 | 17 | - **auth-js**: upgraded to `v1.1.0` 18 | 19 | ### ❤️ Thank You 20 | 21 | - Badisi @Badisi 22 | -------------------------------------------------------------------------------- /libs/ngx-auth/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # @badisi/ngx-auth 4 | 5 | 🛡️ Authentication and authorization support for Angular based desktop and mobile applications. 6 | 7 | [![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)][pullrequest] 8 | [![docs site](https://img.shields.io/badge/site-docs-ed6e55)][docs-site] 9 | [![playground site](https://img.shields.io/badge/site-playground-ed6e55)][playground-site] 10 | [![license](https://img.shields.io/npm/l/@badisi/ngx-auth.svg?color=ff69b4)][license] 11 | 12 | [![npm version](https://img.shields.io/npm/v/@badisi/ngx-auth.svg?color=blue&logo=npm)][npm] 13 | [![npm downloads](https://img.shields.io/npm/dw/@badisi/ngx-auth.svg?color=7986CB&logo=npm)][npm-dl] 14 | [![build status](https://img.shields.io/github/actions/workflow/status/badisi/auth-js/ci_test_ngx-auth.yml?logo=github)][ci-tests] 15 | 16 |
17 | 18 |
19 | 20 | 21 | ## Getting started 22 | 23 | 👉 Learn about it on the 📚 [docs site][docs-site]. 24 | 25 | 🎈 Play with it on the [demo site][playground-site]. 26 | 27 | 28 | ## Development 29 | 30 | See the [developer docs][developer]. 31 | 32 | 33 | ## Contributing 34 | 35 | #### > Want to Help ? 36 | 37 | Want to file a bug, contribute some code or improve documentation ? Excellent! 38 | 39 | But please read up first on the guidelines for [contributing][contributing], and learn about submission process, coding rules and more. 40 | 41 | #### > Code of Conduct 42 | 43 | Please read and follow the [Code of Conduct][codeofconduct] and help me keep this project open and inclusive. 44 | 45 | 46 | 47 | 48 | [npm]: https://www.npmjs.com/package/@badisi/ngx-auth 49 | [npm-dl]: https://npmcharts.com/compare/@badisi/ngx-auth?minimal=true 50 | [ci-tests]: https://github.com/badisi/auth-js/actions/workflows/ci_test_ngx-auth.yml 51 | [pullrequest]: https://github.com/badisi/auth-js/blob/main/CONTRIBUTING.md#-submitting-a-pull-request-pr 52 | [license]: https://github.com/badisi/auth-js/blob/main/LICENSE 53 | [developer]: https://github.com/badisi/auth-js/blob/main/DEVELOPER.md 54 | [contributing]: https://github.com/badisi/auth-js/blob/main/CONTRIBUTING.md 55 | [codeofconduct]: https://github.com/badisi/auth-js/blob/main/CODE_OF_CONDUCT.md 56 | [docs-site]: https://badisi.github.io/auth-js/getting-started/angular 57 | [playground-site]: https://badisi.github.io/auth-js/demo-app/ngx-auth 58 | -------------------------------------------------------------------------------- /libs/ngx-auth/core/auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { inject } from '@angular/core'; 2 | import { 3 | type ActivatedRouteSnapshot, type CanActivateFn, type CanMatchFn, type GuardResult, type Route, Router, 4 | type RouterStateSnapshot, type UrlSegment 5 | } from '@angular/router'; 6 | import type { AuthGuardOptions } from '@badisi/auth-js/oidc'; 7 | 8 | import { AuthService } from './auth.service'; 9 | 10 | export const authGuard = (options?: AuthGuardOptions): CanMatchFn | CanActivateFn => 11 | async (_route: Route | ActivatedRouteSnapshot, segmentsOrState: UrlSegment[] | RouterStateSnapshot): Promise => { 12 | const authService = inject(AuthService); 13 | const router = inject(Router); 14 | 15 | // In case of CanMatch guard we have to extract the inflight url, otherwise use the url from the state 16 | const url = Array.isArray(segmentsOrState) ? 17 | router.getCurrentNavigation()?.extractedUrl.toString() : 18 | segmentsOrState.url; 19 | 20 | const isAllowed = await authService.runGuard(url ?? location.href, options); 21 | if (typeof isAllowed === 'string') { 22 | return router.parseUrl(isAllowed); 23 | } 24 | return isAllowed; 25 | }; 26 | -------------------------------------------------------------------------------- /libs/ngx-auth/core/auth.provider.ts: -------------------------------------------------------------------------------- 1 | import { type EnvironmentProviders, InjectionToken, makeEnvironmentProviders, type StaticProvider } from '@angular/core'; 2 | import { initOidc } from '@badisi/auth-js/oidc'; 3 | 4 | import type { AuthSettings } from '.'; 5 | 6 | export const AUTH_MANAGER = new InjectionToken('AUTH_MANAGER'); 7 | 8 | export const initAuth = async (settings: AuthSettings): Promise => ({ 9 | provide: AUTH_MANAGER, 10 | useValue: await initOidc(settings), 11 | multi: false 12 | }); 13 | 14 | export const provideAuth = (authProvider: StaticProvider): EnvironmentProviders => 15 | makeEnvironmentProviders([ 16 | authProvider 17 | ]); 18 | -------------------------------------------------------------------------------- /libs/ngx-auth/core/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-empty-object-type */ 2 | 3 | /** 4 | * @license GPL-3.0-only 5 | * Package @badisi/ngx-auth 6 | * Released under GNU General Public License v3.0 only 7 | * SPDX-License-Identifier: GPL-3.0-only 8 | * Copyright (C) 2018 Badisi 9 | */ 10 | 11 | // Initialize the logger 12 | import { AuthLogger } from '@badisi/auth-js'; 13 | AuthLogger.init('@badisi/ngx-auth'); 14 | 15 | // @badisi/auth-js re-exports renamed 16 | import type { OIDCAuthManager, OIDCAuthSettings } from '@badisi/auth-js/oidc'; 17 | export interface AuthManager extends OIDCAuthManager {}; 18 | export interface AuthSettings extends OIDCAuthSettings {}; 19 | 20 | // @badisi/auth-js re-exports 21 | export type { 22 | AccessToken, AuthGuardOptions, AuthGuardValidator, IdToken, InjectToken, InjectTokenPattern, 23 | LoginArgs, LogoutArgs, MobileWindowParams, RenewArgs, SigninMobileArgs, SignoutMobileArgs, 24 | UserProfile 25 | } from '@badisi/auth-js/oidc'; 26 | export { AuthUtils, DesktopNavigation, LogLevel, UserSession } from '@badisi/auth-js/oidc'; 27 | 28 | // Library exports 29 | export { authGuard } from './auth.guard'; 30 | export { initAuth, provideAuth } from './auth.provider'; 31 | export { AuthService } from './auth.service'; 32 | -------------------------------------------------------------------------------- /libs/ngx-auth/image/auth-image.component.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '@angular/common/http'; 2 | import { Component, ElementRef, inject, Input } from '@angular/core'; 3 | import { map } from 'rxjs/operators'; 4 | 5 | @Component({ 6 | standalone: true, 7 | selector: 'ngx-auth-img', 8 | template: '', 9 | styles: [':host { background-position: center center; background-repeat: no-repeat; background-size: cover; }'] 10 | }) 11 | // eslint-disable-next-line @angular-eslint/component-class-suffix 12 | export class AuthImage { 13 | #elementRef = inject>(ElementRef); 14 | #httpClient = inject(HttpClient); 15 | 16 | #src!: string; 17 | 18 | @Input() 19 | public set src(value: string) { 20 | if (this.#src !== value) { 21 | this.#src = value; 22 | this.refreshImage(value); 23 | } 24 | } 25 | 26 | public get src(): string { 27 | return this.#src; 28 | } 29 | 30 | // ---- HELPER(s) ---- 31 | 32 | private refreshImage(url: string): void { 33 | this.#httpClient 34 | .get(url, { responseType: 'blob' }) 35 | .pipe( 36 | map((data: Blob) => { 37 | this.#elementRef.nativeElement.style.backgroundImage = `url(${URL.createObjectURL(data)})`; 38 | }) 39 | ) 40 | .subscribe(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /libs/ngx-auth/image/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license GPL-3.0-only 3 | * Package @badisi/ngx-auth 4 | * Released under GNU General Public License v3.0 only 5 | * SPDX-License-Identifier: GPL-3.0-only 6 | * Copyright (C) 2018 Badisi 7 | */ 8 | 9 | export * from './auth-image.component'; 10 | -------------------------------------------------------------------------------- /libs/ngx-auth/image/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "./index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngx-auth/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license GPL-3.0-only 3 | * Package @badisi/ngx-auth 4 | * Released under GNU General Public License v3.0 only 5 | * SPDX-License-Identifier: GPL-3.0-only 6 | * Copyright (C) 2018 Badisi 7 | */ 8 | 9 | export * from './core'; 10 | -------------------------------------------------------------------------------- /libs/ngx-auth/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/naming-convention */ 2 | export default { 3 | displayName: 'ngx-auth', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/test-setup.ts'], 6 | coverageDirectory: '../../coverage/libs/ngx-auth', 7 | transform: { 8 | '^.+\\.(ts|mjs|js|html)$': [ 9 | 'jest-preset-angular', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | stringifyContentPathRegex: '\\.(html|svg)$' 13 | }, 14 | ], 15 | }, 16 | moduleNameMapper: { 17 | '@angular-devkit/core/src/json/schema/index': '/../../node_modules/@angular-devkit/core/src/json/schema/index.js' 18 | }, 19 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 20 | snapshotSerializers: [ 21 | 'jest-preset-angular/build/serializers/no-ng-attributes', 22 | 'jest-preset-angular/build/serializers/ng-snapshot', 23 | 'jest-preset-angular/build/serializers/html-comment', 24 | ], 25 | }; 26 | -------------------------------------------------------------------------------- /libs/ngx-auth/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-auth", 4 | "allowedNonPeerDependencies": [ 5 | "@hug/ngx-schematics-utilities", 6 | "@badisi/auth-js" 7 | ], 8 | "lib": { 9 | "entryFile": "./index.ts" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /libs/ngx-auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@badisi/ngx-auth", 3 | "version": "4.0.0", 4 | "description": "Authentication and authorization support for Angular based desktop and mobile applications.", 5 | "homepage": "https://github.com/Badisi/auth-js/tree/main/libs/ngx-auth", 6 | "license": "GPL-3.0-only", 7 | "author": "Badisi", 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/Badisi/auth-js.git" 11 | }, 12 | "keywords": [ 13 | "angular", 14 | "ionic", 15 | "capacitor", 16 | "cordova", 17 | "hybrid", 18 | "authentication", 19 | "authorization", 20 | "oidc", 21 | "openidconnect", 22 | "openid", 23 | "security", 24 | "identity", 25 | "oauth2", 26 | "oauth", 27 | "auth", 28 | "authn", 29 | "web", 30 | "mobile" 31 | ], 32 | "scripts": { 33 | "lint": "nx run ngx-auth:lint", 34 | "test": "nx run ngx-auth:test", 35 | "test:ci": "nx run ngx-auth:test", 36 | "build": "nx run ngx-auth:build-lib", 37 | "build:nx": "npm run build", 38 | "release": "node ../../scripts/release.mjs --projects=ngx-auth --verbose", 39 | "release:dry-run": "npm run release -- --dry-run" 40 | }, 41 | "dependencies": { 42 | "@hug/ngx-schematics-utilities": "^12.0.0", 43 | "@badisi/auth-js": "1.1.0", 44 | "tslib": "^2.8.1" 45 | }, 46 | "peerDependencies": { 47 | "@angular/common": ">= 15", 48 | "@angular/core": ">= 15", 49 | "@angular/router": ">= 15", 50 | "rxjs": "^6.5.3 || ^7.4.0" 51 | }, 52 | "publishConfig": { 53 | "access": "public" 54 | }, 55 | "schematics": "./schematics/collection.json", 56 | "ng-add": { 57 | "save": "dependencies" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /libs/ngx-auth/schematics/collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json", 3 | "schematics": { 4 | "ng-add": { 5 | "description": "Run ng-add schematic", 6 | "factory": "./ng-add/index", 7 | "schema": "./ng-add/schema.json" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /libs/ngx-auth/schematics/ng-add/ng-add-options.ts: -------------------------------------------------------------------------------- 1 | export class NgAddOptions { 2 | public project!: string; 3 | public authorityUrl!: string; 4 | public clientId!: string; 5 | public mobileScheme?: string; 6 | public loginRequired?: boolean; 7 | public retrieveUserSession?: boolean; 8 | public loadUserInfo?: boolean; 9 | } 10 | -------------------------------------------------------------------------------- /libs/ngx-auth/schematics/ng-add/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema", 3 | "$id": "badisi-ngx-auth-ng-add", 4 | "title": "ng-add schematic", 5 | "type": "object", 6 | "properties": { 7 | "project": { 8 | "description": "Name of the Angular project to run the schematics on.", 9 | "type": "string", 10 | "$default": { 11 | "$source": "projectName" 12 | } 13 | }, 14 | "authorityUrl": { 15 | "x-prompt": "Authority url ?", 16 | "description": "The authorization server DNS host name or IP address.", 17 | "type": "string", 18 | "minLength": 1, 19 | "format": "uri" 20 | }, 21 | "clientId": { 22 | "x-prompt": "Client id ?", 23 | "description": "The public client application's identifier assigned by the authorization server.", 24 | "type": "string", 25 | "minLength": 1 26 | }, 27 | "mobileScheme": { 28 | "x-prompt": "Custom scheme name ? (optional, only for mobile)", 29 | "description": "The custom Scheme URI's identifier assigned to the native mobile application.", 30 | "type": "string" 31 | }, 32 | "loginRequired": { 33 | "x-prompt": "Is authentication required at startup ?", 34 | "description": "Whether an authentication should be required during the initialization phase.", 35 | "type": "boolean", 36 | "default": false 37 | }, 38 | "retrieveUserSession": { 39 | "x-prompt": "Retrieve user's session at startup ?", 40 | "description": "Whether any currently opened user's session should be retrieved during the initialization phase.", 41 | "type": "boolean", 42 | "default": true 43 | }, 44 | "loadUserInfo": { 45 | "x-prompt": "Load user's info at startup ?", 46 | "description": "Whether the user's information should be loaded from the userinfo endpoint during the initialization phase.", 47 | "type": "boolean", 48 | "default": false 49 | } 50 | }, 51 | "required": [ 52 | "authorityUrl", 53 | "clientId" 54 | ], 55 | "additionalProperties": false 56 | } 57 | -------------------------------------------------------------------------------- /libs/ngx-auth/schematics/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es2018", 5 | "outDir": "../../../dist/ngx-auth/schematics", 6 | "rootDir": ".", 7 | "lib": [ 8 | "es2018", 9 | "dom" 10 | ], 11 | "module": "commonjs", 12 | "moduleResolution": "node", 13 | "declaration": true, 14 | "noEmitOnError": true, 15 | "skipDefaultLibCheck": true, 16 | "skipLibCheck": true, 17 | "sourceMap": false, 18 | "types": [ 19 | "jest", 20 | "node" 21 | ] 22 | }, 23 | "files": [], 24 | "include": [], 25 | "references": [ 26 | { 27 | "path": "./tsconfig.lib.json" 28 | }, 29 | { 30 | "path": "./tsconfig.spec.json" 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /libs/ngx-auth/schematics/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | "**/*.ts" 5 | ], 6 | "exclude": [ 7 | "**/*.spec.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /libs/ngx-auth/schematics/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "files": [], 4 | "include": [ 5 | "**/*.spec.ts" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /libs/ngx-auth/test-setup.ts: -------------------------------------------------------------------------------- 1 | import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone'; 2 | import { TextDecoder, TextEncoder } from 'node:util'; 3 | 4 | // Set up the Angular testing environment 5 | setupZoneTestEnv(); 6 | 7 | // @ts-expect-error https://mswjs.io/docs/migrations/1.x-to-2.x#requestresponsetextencoder-is-not-defined-jest 8 | globalThis.TextDecoder = TextDecoder; 9 | globalThis.TextEncoder = TextEncoder; 10 | 11 | // @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment 12 | globalThis.ngJest = { 13 | testEnvironmentOptions: { 14 | errorOnUnknownElements: true, 15 | errorOnUnknownProperties: true 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /libs/ngx-auth/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "forceConsistentCasingInFileNames": true, 5 | "strict": true, 6 | "noImplicitOverride": true, 7 | "noImplicitReturns": true, 8 | "noFallthroughCasesInSwitch": true, 9 | "noPropertyAccessFromIndexSignature": true 10 | }, 11 | "files": [], 12 | "include": [], 13 | "references": [ 14 | { 15 | "path": "./tsconfig.lib.json" 16 | }, 17 | { 18 | "path": "./tsconfig.spec.json" 19 | } 20 | ], 21 | "angularCompilerOptions": { 22 | "enableI18nLegacyMessageIdFormat": false, 23 | "strictInjectionParameters": true, 24 | "strictInputAccessModifiers": true, 25 | "strictTemplates": true 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngx-auth/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "types": [] 8 | }, 9 | "exclude": [ 10 | "test-setup.ts", 11 | "jest.config.ts", 12 | "**/*.spec.ts", 13 | "**/*.test.ts" 14 | ], 15 | "include": [ 16 | "**/*.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /libs/ngx-auth/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "sourceMap": false, 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /libs/ngx-auth/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "target": "es2018", 7 | "types": [ 8 | "jest", 9 | "node" 10 | ] 11 | }, 12 | "files": [ 13 | "test-setup.ts" 14 | ], 15 | "include": [ 16 | "jest.config.ts", 17 | "**/*.test.ts", 18 | "**/*.spec.ts", 19 | "**/*.d.ts" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.strict.json", 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": ".", 6 | "rootDir": ".", 7 | "declaration": false, 8 | "moduleResolution": "node", 9 | "emitDecoratorMetadata": true, 10 | "experimentalDecorators": true, 11 | "importHelpers": true, 12 | "target": "ES2022", 13 | "module": "ESNext", 14 | "lib": [ 15 | "ES2022", 16 | "dom" 17 | ], 18 | "skipLibCheck": true, 19 | "skipDefaultLibCheck": true, 20 | "paths": { 21 | "@badisi/auth-js": [ 22 | "libs/auth-js/core" 23 | ], 24 | "@badisi/auth-js/oidc": [ 25 | "libs/auth-js/oidc" 26 | ], 27 | "@badisi/auth-vue": [ 28 | "libs/auth-vue" 29 | ], 30 | "@badisi/ngx-auth": [ 31 | "libs/ngx-auth" 32 | ], 33 | "demo-app-common": [ 34 | "apps/demo-app/web/common" 35 | ] 36 | } 37 | }, 38 | "exclude": [ 39 | "node_modules", 40 | "tmp" 41 | ], 42 | "references": [] 43 | } 44 | -------------------------------------------------------------------------------- /tsconfig.strict.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "forceConsistentCasingInFileNames": true, 4 | "noImplicitAny": true, 5 | "noImplicitReturns": true, 6 | "noImplicitThis": true, 7 | "noFallthroughCasesInSwitch": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noUnusedLocals": true, 10 | "noUnusedParameters": true, 11 | "strict": true, 12 | "strictBindCallApply": true, 13 | "strictFunctionTypes": true, 14 | "strictNullChecks": true 15 | }, 16 | "angularCompilerOptions": { 17 | "enableI18nLegacyMessageIdFormat": false, 18 | "strictInjectionParameters": true, 19 | "strictInputAccessModifiers": true, 20 | "strictTemplates": true 21 | } 22 | } 23 | --------------------------------------------------------------------------------