diff --git a/README.md b/README.md
index 5c7bd7d9..e39e8e01 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,7 @@
- [@nstudio/nativescript-airship-hms](packages/nativescript-airship-hms/README.md)
- [@nstudio/nativescript-appcues](packages/nativescript-appcues/README.md)
- [@nstudio/nativescript-aptabase](packages/nativescript-aptabase/README.md)
+- [@nstudio/nativescript-auth0](packages/nativescript-auth0/README.md)
- [@nstudio/nativescript-barcodescanner](packages/nativescript-barcodescanner/README.md)
- [@nstudio/nativescript-blur](packages/nativescript-blur/README.md)
- [@nstudio/nativescript-camera-plus](packages/nativescript-camera-plus/README.md)
diff --git a/apps/demo-angular/package.json b/apps/demo-angular/package.json
index deb16b9c..9404f951 100644
--- a/apps/demo-angular/package.json
+++ b/apps/demo-angular/package.json
@@ -2,7 +2,7 @@
"main": "./src/main.ts",
"dependencies": {
"@nativescript/core": "file:../../node_modules/@nativescript/core",
- "@nstudio/nativescript-loading-indicator": "file:../../dist/packages/nativescript-loading-indicator",
+ "@nstudio/nativescript-auth0": "file:../../dist/packages/nativescript-auth0",
"@nstudio/nativescript-airship": "file:../../dist/packages/nativescript-airship",
"@nstudio/nativescript-airship-adm": "file:../../dist/packages/nativescript-airship-adm",
"@nstudio/nativescript-airship-fcm": "file:../../dist/packages/nativescript-airship-fcm",
@@ -23,6 +23,7 @@
"@nstudio/nativescript-freshchat": "file:../../dist/packages/nativescript-freshchat",
"@nstudio/nativescript-input-mask": "file:../../dist/packages/nativescript-input-mask",
"@nstudio/nativescript-intercom": "file:../../dist/packages/nativescript-intercom",
+ "@nstudio/nativescript-loading-indicator": "file:../../dist/packages/nativescript-loading-indicator",
"@nstudio/nativescript-onfido": "file:../../dist/packages/nativescript-onfido",
"@nstudio/nativescript-persona": "file:../../dist/packages/nativescript-persona",
"@nstudio/nativescript-plaid": "file:../../dist/packages/nativescript-plaid",
diff --git a/apps/demo-angular/src/app-routing.module.ts b/apps/demo-angular/src/app-routing.module.ts
index c6bd5f41..3ba3e16e 100644
--- a/apps/demo-angular/src/app-routing.module.ts
+++ b/apps/demo-angular/src/app-routing.module.ts
@@ -4,36 +4,37 @@ import { NativeScriptRouterModule } from '@nativescript/angular';
import { HomeComponent } from './home.component';
const routes: Routes = [
- { path: '', redirectTo: '/home', pathMatch: 'full' },
- { path: 'home', component: HomeComponent },
- { path: 'nativescript-airship', loadChildren: () => import('./plugin-demos/nativescript-airship.module').then(m => m.NativescriptAirshipModule) },
- { path: 'nativescript-airship-adm', loadChildren: () => import('./plugin-demos/nativescript-airship-adm.module').then(m => m.NativescriptAirshipAdmModule) },
- { path: 'nativescript-airship-fcm', loadChildren: () => import('./plugin-demos/nativescript-airship-fcm.module').then(m => m.NativescriptAirshipFcmModule) },
- { path: 'nativescript-airship-hms', loadChildren: () => import('./plugin-demos/nativescript-airship-hms.module').then(m => m.NativescriptAirshipHmsModule) },
- { path: 'nativescript-appcues', loadChildren: () => import('./plugin-demos/nativescript-appcues.module').then(m => m.NativescriptAppcuesModule) },
- { path: 'nativescript-aptabase', loadChildren: () => import('./plugin-demos/nativescript-aptabase.module').then(m => m.NativescriptAptabaseModule) },
- { path: 'nativescript-barcodescanner', loadChildren: () => import('./plugin-demos/nativescript-barcodescanner.module').then(m => m.NativescriptBarcodescannerModule) },
- { path: 'nativescript-blur', loadChildren: () => import('./plugin-demos/nativescript-blur.module').then(m => m.NativescriptBlurModule) },
- { path: 'nativescript-camera-plus', loadChildren: () => import('./plugin-demos/nativescript-camera-plus.module').then(m => m.NativescriptCameraPlusModule) },
- { path: 'nativescript-cardview', loadChildren: () => import('./plugin-demos/nativescript-cardview.module').then(m => m.NativescriptCardviewModule) },
- { path: 'nativescript-carousel', loadChildren: () => import('./plugin-demos/nativescript-carousel.module').then(m => m.NativescriptCarouselModule) },
- { path: 'nativescript-checkbox', loadChildren: () => import('./plugin-demos/nativescript-checkbox.module').then(m => m.NativescriptCheckboxModule) },
- { path: 'nativescript-dynatrace', loadChildren: () => import('./plugin-demos/nativescript-dynatrace.module').then(m => m.NativescriptDynatraceModule) },
- { path: 'nativescript-embrace', loadChildren: () => import('./plugin-demos/nativescript-embrace.module').then(m => m.NativescriptEmbraceModule) },
- { path: 'nativescript-exoplayer', loadChildren: () => import('./plugin-demos/nativescript-exoplayer.module').then(m => m.NativescriptExoplayerModule) },
- { path: 'nativescript-fancyalert', loadChildren: () => import('./plugin-demos/nativescript-fancyalert.module').then(m => m.NativescriptFancyalertModule) },
- { path: 'nativescript-filterable-listpicker', loadChildren: () => import('./plugin-demos/nativescript-filterable-listpicker.module').then(m => m.NativescriptFilterableListpickerModule) },
- { path: 'nativescript-freshchat', loadChildren: () => import('./plugin-demos/nativescript-freshchat.module').then(m => m.NativescriptFreshchatModule) },
- { path: 'nativescript-input-mask', loadChildren: () => import('./plugin-demos/nativescript-input-mask.module').then(m => m.NativescriptInputMaskModule) },
- { path: 'nativescript-intercom', loadChildren: () => import('./plugin-demos/nativescript-intercom.module').then(m => m.NativescriptIntercomModule) },
- { path: 'nativescript-loading-indicator', loadChildren: () => import('./plugin-demos/nativescript-loading-indicator.module').then(m => m.NativescriptLoadingIndicatorModule) },
- { path: 'nativescript-onfido', loadChildren: () => import('./plugin-demos/nativescript-onfido.module').then(m => m.NativescriptOnfidoModule) },
- { path: 'nativescript-persona', loadChildren: () => import('./plugin-demos/nativescript-persona.module').then(m => m.NativescriptPersonaModule) },
- { path: 'nativescript-plaid', loadChildren: () => import('./plugin-demos/nativescript-plaid.module').then(m => m.NativescriptPlaidModule) },
- { path: 'nativescript-qr', loadChildren: () => import('./plugin-demos/nativescript-qr.module').then(m => m.NativescriptQrModule) },
- { path: 'nativescript-tracking-transparency', loadChildren: () => import('./plugin-demos/nativescript-tracking-transparency.module').then(m => m.NativescriptTrackingTransparencyModule) },
- { path: 'nativescript-walletconnect', loadChildren: () => import('./plugin-demos/nativescript-walletconnect.module').then(m => m.NativescriptWalletconnectModule) },
- { path: 'nativescript-web-server', loadChildren: () => import('./plugin-demos/nativescript-web-server.module').then(m => m.NativescriptWebServerModule) }
+ { path: '', redirectTo: '/home', pathMatch: 'full' },
+ { path: 'home', component: HomeComponent },
+ { path: 'nativescript-airship', loadChildren: () => import('./plugin-demos/nativescript-airship.module').then((m) => m.NativescriptAirshipModule) },
+ { path: 'nativescript-airship-adm', loadChildren: () => import('./plugin-demos/nativescript-airship-adm.module').then((m) => m.NativescriptAirshipAdmModule) },
+ { path: 'nativescript-airship-fcm', loadChildren: () => import('./plugin-demos/nativescript-airship-fcm.module').then((m) => m.NativescriptAirshipFcmModule) },
+ { path: 'nativescript-airship-hms', loadChildren: () => import('./plugin-demos/nativescript-airship-hms.module').then((m) => m.NativescriptAirshipHmsModule) },
+ { path: 'nativescript-appcues', loadChildren: () => import('./plugin-demos/nativescript-appcues.module').then((m) => m.NativescriptAppcuesModule) },
+ { path: 'nativescript-aptabase', loadChildren: () => import('./plugin-demos/nativescript-aptabase.module').then((m) => m.NativescriptAptabaseModule) },
+ { path: 'nativescript-auth0', loadChildren: () => import('./plugin-demos/nativescript-auth0.module').then((m) => m.NativescriptAuth0Module) },
+ { path: 'nativescript-barcodescanner', loadChildren: () => import('./plugin-demos/nativescript-barcodescanner.module').then((m) => m.NativescriptBarcodescannerModule) },
+ { path: 'nativescript-blur', loadChildren: () => import('./plugin-demos/nativescript-blur.module').then((m) => m.NativescriptBlurModule) },
+ { path: 'nativescript-camera-plus', loadChildren: () => import('./plugin-demos/nativescript-camera-plus.module').then((m) => m.NativescriptCameraPlusModule) },
+ { path: 'nativescript-cardview', loadChildren: () => import('./plugin-demos/nativescript-cardview.module').then((m) => m.NativescriptCardviewModule) },
+ { path: 'nativescript-carousel', loadChildren: () => import('./plugin-demos/nativescript-carousel.module').then((m) => m.NativescriptCarouselModule) },
+ { path: 'nativescript-checkbox', loadChildren: () => import('./plugin-demos/nativescript-checkbox.module').then((m) => m.NativescriptCheckboxModule) },
+ { path: 'nativescript-dynatrace', loadChildren: () => import('./plugin-demos/nativescript-dynatrace.module').then((m) => m.NativescriptDynatraceModule) },
+ { path: 'nativescript-embrace', loadChildren: () => import('./plugin-demos/nativescript-embrace.module').then((m) => m.NativescriptEmbraceModule) },
+ { path: 'nativescript-exoplayer', loadChildren: () => import('./plugin-demos/nativescript-exoplayer.module').then((m) => m.NativescriptExoplayerModule) },
+ { path: 'nativescript-fancyalert', loadChildren: () => import('./plugin-demos/nativescript-fancyalert.module').then((m) => m.NativescriptFancyalertModule) },
+ { path: 'nativescript-filterable-listpicker', loadChildren: () => import('./plugin-demos/nativescript-filterable-listpicker.module').then((m) => m.NativescriptFilterableListpickerModule) },
+ { path: 'nativescript-freshchat', loadChildren: () => import('./plugin-demos/nativescript-freshchat.module').then((m) => m.NativescriptFreshchatModule) },
+ { path: 'nativescript-input-mask', loadChildren: () => import('./plugin-demos/nativescript-input-mask.module').then((m) => m.NativescriptInputMaskModule) },
+ { path: 'nativescript-intercom', loadChildren: () => import('./plugin-demos/nativescript-intercom.module').then((m) => m.NativescriptIntercomModule) },
+ { path: 'nativescript-loading-indicator', loadChildren: () => import('./plugin-demos/nativescript-loading-indicator.module').then((m) => m.NativescriptLoadingIndicatorModule) },
+ { path: 'nativescript-onfido', loadChildren: () => import('./plugin-demos/nativescript-onfido.module').then((m) => m.NativescriptOnfidoModule) },
+ { path: 'nativescript-persona', loadChildren: () => import('./plugin-demos/nativescript-persona.module').then((m) => m.NativescriptPersonaModule) },
+ { path: 'nativescript-plaid', loadChildren: () => import('./plugin-demos/nativescript-plaid.module').then((m) => m.NativescriptPlaidModule) },
+ { path: 'nativescript-qr', loadChildren: () => import('./plugin-demos/nativescript-qr.module').then((m) => m.NativescriptQrModule) },
+ { path: 'nativescript-tracking-transparency', loadChildren: () => import('./plugin-demos/nativescript-tracking-transparency.module').then((m) => m.NativescriptTrackingTransparencyModule) },
+ { path: 'nativescript-walletconnect', loadChildren: () => import('./plugin-demos/nativescript-walletconnect.module').then((m) => m.NativescriptWalletconnectModule) },
+ { path: 'nativescript-web-server', loadChildren: () => import('./plugin-demos/nativescript-web-server.module').then((m) => m.NativescriptWebServerModule) },
];
@NgModule({
diff --git a/apps/demo-angular/src/home.component.ts b/apps/demo-angular/src/home.component.ts
index 0ca7b493..70dfc9e7 100644
--- a/apps/demo-angular/src/home.component.ts
+++ b/apps/demo-angular/src/home.component.ts
@@ -6,89 +6,92 @@ import { Component } from '@angular/core';
})
export class HomeComponent {
demos = [
- {
- name: 'nativescript-airship'
- },
- {
- name: 'nativescript-airship-adm'
- },
- {
- name: 'nativescript-airship-fcm'
- },
- {
- name: 'nativescript-airship-hms'
- },
- {
- name: 'nativescript-appcues'
- },
- {
- name: 'nativescript-aptabase'
- },
- {
- name: 'nativescript-barcodescanner'
- },
- {
- name: 'nativescript-blur'
- },
- {
- name: 'nativescript-camera-plus'
- },
- {
- name: 'nativescript-cardview'
- },
- {
- name: 'nativescript-carousel'
- },
- {
- name: 'nativescript-checkbox'
- },
- {
- name: 'nativescript-dynatrace'
- },
- {
- name: 'nativescript-embrace'
- },
- {
- name: 'nativescript-exoplayer'
- },
- {
- name: 'nativescript-fancyalert'
- },
- {
- name: 'nativescript-filterable-listpicker'
- },
- {
- name: 'nativescript-freshchat'
- },
- {
- name: 'nativescript-input-mask'
- },
- {
- name: 'nativescript-intercom'
- },
- {
- name: 'nativescript-loading-indicator'
- },
- {
- name: 'nativescript-onfido'
- },
- {
- name: 'nativescript-persona'
- },
- {
- name: 'nativescript-plaid'
- },
- {
- name: 'nativescript-qr'
- },
- {
- name: 'nativescript-tracking-transparency'
- },
- {
- name: 'nativescript-walletconnect'
- },
- {
- name: 'nativescript-web-server'
- }
-];
-}
\ No newline at end of file
+ {
+ name: 'nativescript-airship',
+ },
+ {
+ name: 'nativescript-airship-adm',
+ },
+ {
+ name: 'nativescript-airship-fcm',
+ },
+ {
+ name: 'nativescript-airship-hms',
+ },
+ {
+ name: 'nativescript-appcues',
+ },
+ {
+ name: 'nativescript-aptabase',
+ },
+ {
+ name: 'nativescript-auth0',
+ },
+ {
+ name: 'nativescript-barcodescanner',
+ },
+ {
+ name: 'nativescript-blur',
+ },
+ {
+ name: 'nativescript-camera-plus',
+ },
+ {
+ name: 'nativescript-cardview',
+ },
+ {
+ name: 'nativescript-carousel',
+ },
+ {
+ name: 'nativescript-checkbox',
+ },
+ {
+ name: 'nativescript-dynatrace',
+ },
+ {
+ name: 'nativescript-embrace',
+ },
+ {
+ name: 'nativescript-exoplayer',
+ },
+ {
+ name: 'nativescript-fancyalert',
+ },
+ {
+ name: 'nativescript-filterable-listpicker',
+ },
+ {
+ name: 'nativescript-freshchat',
+ },
+ {
+ name: 'nativescript-input-mask',
+ },
+ {
+ name: 'nativescript-intercom',
+ },
+ {
+ name: 'nativescript-loading-indicator',
+ },
+ {
+ name: 'nativescript-onfido',
+ },
+ {
+ name: 'nativescript-persona',
+ },
+ {
+ name: 'nativescript-plaid',
+ },
+ {
+ name: 'nativescript-qr',
+ },
+ {
+ name: 'nativescript-tracking-transparency',
+ },
+ {
+ name: 'nativescript-walletconnect',
+ },
+ {
+ name: 'nativescript-web-server',
+ },
+ ];
+}
diff --git a/apps/demo-angular/src/plugin-demos/nativescript-auth0.component.html b/apps/demo-angular/src/plugin-demos/nativescript-auth0.component.html
new file mode 100644
index 00000000..029420fb
--- /dev/null
+++ b/apps/demo-angular/src/plugin-demos/nativescript-auth0.component.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/apps/demo-angular/src/plugin-demos/nativescript-auth0.component.ts b/apps/demo-angular/src/plugin-demos/nativescript-auth0.component.ts
new file mode 100644
index 00000000..3e778a52
--- /dev/null
+++ b/apps/demo-angular/src/plugin-demos/nativescript-auth0.component.ts
@@ -0,0 +1,17 @@
+import { Component, NgZone } from '@angular/core';
+import { DemoSharedNativescriptAuth0 } from '@demo/shared';
+import {} from '@nstudio/nativescript-auth0';
+
+@Component({
+ selector: 'demo-nativescript-auth0',
+ templateUrl: 'nativescript-auth0.component.html',
+})
+export class NativescriptAuth0Component {
+ demoShared: DemoSharedNativescriptAuth0;
+
+ constructor(private _ngZone: NgZone) {}
+
+ ngOnInit() {
+ this.demoShared = new DemoSharedNativescriptAuth0();
+ }
+}
diff --git a/apps/demo-angular/src/plugin-demos/nativescript-auth0.module.ts b/apps/demo-angular/src/plugin-demos/nativescript-auth0.module.ts
new file mode 100644
index 00000000..6a2a174f
--- /dev/null
+++ b/apps/demo-angular/src/plugin-demos/nativescript-auth0.module.ts
@@ -0,0 +1,10 @@
+import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
+import { NativeScriptCommonModule, NativeScriptRouterModule } from '@nativescript/angular';
+import { NativescriptAuth0Component } from './nativescript-auth0.component';
+
+@NgModule({
+ imports: [NativeScriptCommonModule, NativeScriptRouterModule.forChild([{ path: '', component: NativescriptAuth0Component }])],
+ declarations: [NativescriptAuth0Component],
+ schemas: [NO_ERRORS_SCHEMA],
+})
+export class NativescriptAuth0Module {}
diff --git a/apps/demo-angular/tsconfig.json b/apps/demo-angular/tsconfig.json
index a87eb737..123763f5 100644
--- a/apps/demo-angular/tsconfig.json
+++ b/apps/demo-angular/tsconfig.json
@@ -34,7 +34,8 @@
"@nstudio/nativescript-freshchat": ["../../packages/nativescript-freshchat/index.d.ts"],
"@nstudio/nativescript-persona": ["../../packages/nativescript-persona/index.d.ts"],
"@nstudio/nativescript-walletconnect": ["../../packages/nativescript-walletconnect/index.d.ts"],
- "@nstudio/nativescript-web-server": ["../../packages/nativescript-web-server/index.d.ts"]
+ "@nstudio/nativescript-web-server": ["../../packages/nativescript-web-server/index.d.ts"],
+ "@nstudio/nativescript-auth0": ["../../packages/nativescript-auth0/index.d.ts"]
}
},
"files": ["./references.d.ts", "./src/main.ts", "./src/polyfills.ts"],
diff --git a/apps/demo/package.json b/apps/demo/package.json
index 66209af2..8469c22d 100644
--- a/apps/demo/package.json
+++ b/apps/demo/package.json
@@ -3,7 +3,7 @@
"description": "NativeScript Application",
"dependencies": {
"@nativescript/core": "file:../../node_modules/@nativescript/core",
- "@nstudio/nativescript-loading-indicator": "file:../../packages/nativescript-loading-indicator",
+ "@nstudio/nativescript-auth0": "file:../../packages/nativescript-auth0",
"@nstudio/nativescript-airship": "file:../../packages/nativescript-airship",
"@nstudio/nativescript-airship-adm": "file:../../packages/nativescript-airship-adm",
"@nstudio/nativescript-airship-fcm": "file:../../packages/nativescript-airship-fcm",
@@ -24,6 +24,7 @@
"@nstudio/nativescript-freshchat": "file:../../packages/nativescript-freshchat",
"@nstudio/nativescript-input-mask": "file:../../packages/nativescript-input-mask",
"@nstudio/nativescript-intercom": "file:../../packages/nativescript-intercom",
+ "@nstudio/nativescript-loading-indicator": "file:../../packages/nativescript-loading-indicator",
"@nstudio/nativescript-onfido": "file:../../packages/nativescript-onfido",
"@nstudio/nativescript-persona": "file:../../packages/nativescript-persona",
"@nstudio/nativescript-plaid": "file:../../packages/nativescript-plaid",
diff --git a/apps/demo/src/main-page.xml b/apps/demo/src/main-page.xml
index 93e68642..28590642 100644
--- a/apps/demo/src/main-page.xml
+++ b/apps/demo/src/main-page.xml
@@ -11,6 +11,7 @@
+
diff --git a/apps/demo/src/plugin-demos/nativescript-auth0.ts b/apps/demo/src/plugin-demos/nativescript-auth0.ts
new file mode 100644
index 00000000..92277875
--- /dev/null
+++ b/apps/demo/src/plugin-demos/nativescript-auth0.ts
@@ -0,0 +1,10 @@
+import { Observable, EventData, Page } from '@nativescript/core';
+import { DemoSharedNativescriptAuth0 } from '@demo/shared';
+import {} from '@nstudio/nativescript-auth0';
+
+export function navigatingTo(args: EventData) {
+ const page = args.object;
+ page.bindingContext = new DemoModel();
+}
+
+export class DemoModel extends DemoSharedNativescriptAuth0 {}
diff --git a/apps/demo/src/plugin-demos/nativescript-auth0.xml b/apps/demo/src/plugin-demos/nativescript-auth0.xml
new file mode 100644
index 00000000..9188de99
--- /dev/null
+++ b/apps/demo/src/plugin-demos/nativescript-auth0.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/demo/tsconfig.json b/apps/demo/tsconfig.json
index 4d424a40..010a4490 100644
--- a/apps/demo/tsconfig.json
+++ b/apps/demo/tsconfig.json
@@ -36,7 +36,8 @@
"@nstudio/nativescript-freshchat": ["../../packages/nativescript-freshchat/index.d.ts"],
"@nstudio/nativescript-persona": ["../../packages/nativescript-persona/index.d.ts"],
"@nstudio/nativescript-walletconnect": ["../../packages/nativescript-walletconnect/index.d.ts"],
- "@nstudio/nativescript-web-server": ["../../packages/nativescript-web-server/index.d.ts"]
+ "@nstudio/nativescript-web-server": ["../../packages/nativescript-web-server/index.d.ts"],
+ "@nstudio/nativescript-auth0": ["../../packages/nativescript-auth0/index.d.ts"]
}
}
}
diff --git a/packages/nativescript-auth0/.eslintrc.json b/packages/nativescript-auth0/.eslintrc.json
new file mode 100644
index 00000000..be41074b
--- /dev/null
+++ b/packages/nativescript-auth0/.eslintrc.json
@@ -0,0 +1,18 @@
+{
+ "extends": ["../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*", "node_modules/**/*"],
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.js", "*.jsx"],
+ "rules": {}
+ }
+ ]
+}
diff --git a/packages/nativescript-auth0/README.md b/packages/nativescript-auth0/README.md
new file mode 100644
index 00000000..def53165
--- /dev/null
+++ b/packages/nativescript-auth0/README.md
@@ -0,0 +1,23 @@
+# @nstudio/nativescript-auth0
+
+```javascript
+npm install @nstudio/nativescript-auth0
+```
+
+## Usage
+
+```ts
+import { Auth0 } from '@nstudio/nativescript-auth0';
+
+const auth0Client = new Auth0({
+ clientId: '',
+ domain: ''
+});
+
+const credentials = await auth0Client.webAuth.start();
+console.log(credentials) // tokens!
+```
+
+## License
+
+Apache License Version 2.0
diff --git a/packages/nativescript-auth0/common.ts b/packages/nativescript-auth0/common.ts
new file mode 100644
index 00000000..0051a162
--- /dev/null
+++ b/packages/nativescript-auth0/common.ts
@@ -0,0 +1,3 @@
+import { Observable } from '@nativescript/core';
+
+export class NativescriptAuth0Common extends Observable {}
diff --git a/packages/nativescript-auth0/index.android.ts b/packages/nativescript-auth0/index.android.ts
new file mode 100644
index 00000000..2dc3b6b2
--- /dev/null
+++ b/packages/nativescript-auth0/index.android.ts
@@ -0,0 +1,462 @@
+import { Utils } from '@nativescript/core';
+
+declare const kotlin: any;
+export class Credentials {
+ static fromNative(credentials: com.auth0.android.result.Credentials): Credentials {
+ if (credentials instanceof com.auth0.android.result.Credentials) {
+ const ret = new Credentials();
+ ret.credentials = credentials;
+ return ret;
+ }
+ return null;
+ }
+
+ private credentials: com.auth0.android.result.Credentials;
+
+ constructor(info?: { accessToken?: string; tokenType?: string; idToken?: string; refreshToken?: string; expiresIn?: Date; scope?: string; recoveryCode: string }) {
+ if (info) {
+ let date: number;
+ if (info.expiresIn && info.expiresIn instanceof Date) {
+ date = info.expiresIn.getTime();
+ } else {
+ date = Date.now() + 86400 * 1000;
+ }
+
+ this.credentials = io.nstudio.plugins.auth0.Auth0.createCredentials(info.accessToken ?? null, info.tokenType ?? null, info.idToken ?? null, info.refreshToken ?? null, date, info.scope ?? null, info.recoveryCode ?? null);
+ }
+ }
+
+ get native() {
+ return this.credentials;
+ }
+
+ get accessToken(): string {
+ return this.credentials.getAccessToken();
+ }
+
+ get expiresIn(): number {
+ return this.credentials.getExpiresAt().getTime() - Date.now();
+ }
+
+ get expiresAt(): Date {
+ return new Date(this.credentials.getExpiresAt().getTime());
+ }
+
+ get idToken(): string {
+ return this.credentials.getIdToken();
+ }
+
+ get recoveryCode(): string {
+ return this.credentials.getRecoveryCode();
+ }
+
+ get refreshToken(): string {
+ return this.credentials.getRefreshToken();
+ }
+
+ get scope(): string {
+ return this.credentials.getScope();
+ }
+
+ get tokenType(): string {
+ return this.credentials.getType();
+ }
+
+ toJSON() {
+ const redacted = '';
+ return {
+ accessToken: redacted,
+ expiresIn: this.expiresIn,
+ idToken: redacted,
+ recoveryCode: this.recoveryCode,
+ refreshToken: this.refreshToken ? redacted : null,
+ scope: this.scope,
+ tokenType: this.tokenType ? redacted : null,
+ };
+ }
+}
+
+export class CredentialsManager {
+ static fromNative(manager: io.nstudio.plugins.auth0.CredentialsManager): CredentialsManager {
+ if (manager instanceof io.nstudio.plugins.auth0.CredentialsManager) {
+ const ret = new CredentialsManager();
+ ret.credentialsManager = manager;
+ return ret;
+ }
+ return null;
+ }
+
+ private credentialsManager: io.nstudio.plugins.auth0.CredentialsManager;
+
+ get native() {
+ return this.credentialsManager;
+ }
+
+ clear() {
+ this.credentialsManager.clear();
+ }
+
+ credentials(scope?: string, minTtl?: number, parameters?: Record, forceRefresh?: boolean): Promise {
+ return new Promise((resolve, reject) => {
+ this.credentialsManager.credentials(
+ scope ?? null,
+ minTtl ?? 0,
+ Utils.dataSerialize(parameters ?? {}),
+ forceRefresh ?? false,
+ new kotlin.jvm.functions.Function2({
+ invoke: (credentials: com.auth0.android.result.Credentials, error: java.lang.Throwable) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve(Credentials.fromNative(credentials));
+ }
+ },
+ })
+ );
+ });
+ }
+
+ store(credentials: Credentials) {
+ this.credentialsManager.store(credentials.native);
+ }
+
+ hasValidCredentials(minTtl?: number): boolean {
+ return this.credentialsManager.hasValid(minTtl ?? 0);
+ }
+}
+
+export class WebAuth {
+ static fromNative(auth: io.nstudio.plugins.auth0.WebAuth): WebAuth {
+ if (auth instanceof io.nstudio.plugins.auth0.WebAuth) {
+ const ret = new WebAuth();
+ ret.webAuth = auth;
+ return ret;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.webAuth;
+ }
+
+ private webAuth: io.nstudio.plugins.auth0.WebAuth;
+
+ useHTTPS(): this {
+ return this;
+ }
+
+ start(options?: { scheme?: string; scope?: string; audience?: string; redirectUrl?: string }) {
+ return new Promise((resolve, reject) => {
+ this.webAuth.start(
+ Utils.android.getCurrentActivity(),
+ options?.scheme ?? null,
+ options.scope ?? null,
+ options?.audience ?? null,
+ options?.redirectUrl ?? null,
+ new kotlin.jvm.functions.Function2({
+ invoke: (credentials: com.auth0.android.result.Credentials, error: java.lang.Throwable) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve(Credentials.fromNative(credentials));
+ }
+ },
+ })
+ );
+ });
+ }
+
+ clear(options?: { scheme?: string; federated?: boolean; returnToUrl?: string }) {
+ return new Promise((resolve, reject) => {
+ this.webAuth.clearSession(
+ Utils.android.getCurrentActivity(),
+ options?.scheme ?? null,
+ options?.federated ?? false,
+ options?.returnToUrl ?? null,
+ new kotlin.jvm.functions.Function1({
+ invoke: (error: java.lang.Throwable) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve();
+ }
+ },
+ })
+ );
+ });
+ }
+}
+
+export class JWT {
+ static fromNative(jwt: io.nstudio.plugins.auth0.DecodedJWT): JWT {
+ if (jwt instanceof io.nstudio.plugins.auth0.DecodedJWT) {
+ const ret = new JWT();
+ ret.jwt = jwt;
+ return ret;
+ }
+ return null;
+ }
+
+ private jwt: io.nstudio.plugins.auth0.DecodedJWT;
+
+ get native() {
+ return this.jwt;
+ }
+
+ get identifier() {
+ return this.jwt.getIdentifier();
+ }
+
+ get subject() {
+ return this.jwt.getSubject();
+ }
+
+ get issuer() {
+ return this.jwt.getIssuer();
+ }
+
+ get audience() {
+ return Utils.dataDeserialize(this.jwt.getAudience());
+ }
+
+ get issuedAt() {
+ const issuedAt = this.jwt.getIssuedAt();
+ if (issuedAt) {
+ return new Date(issuedAt.getTime());
+ }
+ return null;
+ }
+
+ get expiresAt() {
+ const expiresAt = this.jwt.getExpiresAt();
+ if (expiresAt) {
+ return new Date(expiresAt.getTime());
+ }
+ return null;
+ }
+
+ get notBefore() {
+ const nb = this.jwt.getNotBefore();
+ if (nb) {
+ return new Date(nb.getTime());
+ }
+ return null;
+ }
+
+ get body() {
+ return Utils.dataDeserialize(this.jwt.getBody());
+ }
+
+ toJSON() {
+ return {
+ identifier: this.identifier,
+ subject: this.subject,
+ issuer: this.issuer,
+ audience: this.audience,
+ issuedAt: this.issuedAt,
+ expiresAt: this.expiresAt,
+ notBefore: this.notBefore,
+ body: this.body,
+ };
+ }
+}
+
+export function decodeJWT(token: string): JWT {
+ return JWT.fromNative(io.nstudio.plugins.auth0.Auth0.decodeJWT(token));
+}
+
+export class UserInfo {
+ static fromNative(userInfo: com.auth0.android.result.UserProfile): UserInfo {
+ if (userInfo instanceof com.auth0.android.result.UserProfile) {
+ const ret = new UserInfo();
+ ret.userInfo = userInfo;
+ return ret;
+ }
+ return null;
+ }
+ private userInfo: com.auth0.android.result.UserProfile;
+
+ get native() {
+ return this.userInfo;
+ }
+
+ get address() {
+ // todo
+ return [];
+ }
+
+ get birthdate(): string {
+ return null;
+ }
+
+ get customClaims(): Record {
+ return {};
+ }
+
+ get email(): string {
+ return null;
+ }
+
+ get emailVerified(): boolean {
+ const verified = this.userInfo.isEmailVerified();
+
+ return verified.booleanValue?.() || (verified as never);
+ }
+
+ get familyName(): string {
+ return this.userInfo.getFamilyName();
+ }
+
+ get gender(): string {
+ return null;
+ }
+
+ get givenName(): string {
+ return this.userInfo.getGivenName();
+ }
+
+ get locale(): string {
+ return null;
+ }
+
+ get middleName(): string {
+ return null;
+ }
+
+ get name(): string {
+ return this.userInfo.getName();
+ }
+
+ get nickname(): string {
+ return this.userInfo.getNickname();
+ }
+
+ get phoneNumber(): string {
+ return null;
+ }
+
+ get phoneNumberVerified(): boolean {
+ return false; // todo
+ }
+
+ get picture(): string | null {
+ return this.userInfo.getPictureURL();
+ }
+
+ get preferredUsername(): string {
+ return null;
+ }
+
+ get profile(): string | null {
+ return null;
+ }
+
+ get sub(): string {
+ return null;
+ }
+
+ get updatedAt(): Date {
+ return null;
+ }
+
+ get website(): string | null {
+ return null;
+ }
+
+ get zoneinfo(): string {
+ return null;
+ }
+}
+
+export class Authentication {
+ static fromNative(auth: io.nstudio.plugins.auth0.Authentication): Authentication {
+ if (auth instanceof io.nstudio.plugins.auth0.Authentication) {
+ const ret = new Authentication();
+ ret.authentication = auth;
+ return ret;
+ }
+ return null;
+ }
+
+ private authentication: io.nstudio.plugins.auth0.Authentication;
+
+ get native() {
+ return this.authentication;
+ }
+
+ userInfo(options: { accessToken: string; headers?: Record }) {
+ return new Promise((resolve, reject) => {
+ this.authentication.userInfo(
+ options.accessToken,
+ Utils.dataSerialize(options.headers ?? {}),
+ new kotlin.jvm.functions.Function2({
+ invoke: (userInfo: com.auth0.android.result.UserProfile, error: java.lang.Throwable) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve(UserInfo.fromNative(userInfo));
+ }
+ },
+ })
+ );
+ });
+ }
+
+ refreshToken(options: { refreshToken: string; scope?: string; audience: string; headers?: Record }) {
+ return new Promise((resolve, reject) => {
+ this.authentication.refreshToken(
+ options.refreshToken,
+ options.scope ?? null,
+ options?.audience ?? null,
+ Utils.dataSerialize(options.headers ?? {}),
+ new kotlin.jvm.functions.Function2({
+ invoke: (credentials: com.auth0.android.result.Credentials, error: java.lang.Throwable) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve(Credentials.fromNative(credentials));
+ }
+ },
+ })
+ );
+ });
+ }
+
+ revoke(options: { refreshToken: string; headers?: Record }) {
+ return new Promise((resolve, reject) => {
+ this.authentication.revoke(
+ options.refreshToken,
+ Utils.dataSerialize(options.headers ?? {}),
+ new kotlin.jvm.functions.Function1({
+ invoke: (error: java.lang.Throwable) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve();
+ }
+ },
+ })
+ );
+ });
+ }
+}
+
+export class Auth0 {
+ readonly clientId: string;
+ readonly domain: string;
+ readonly webAuth: WebAuth;
+ readonly auth: Authentication;
+ readonly credentialsManager: CredentialsManager;
+
+ constructor(options: { clientId: string; domain: string }) {
+ this.clientId = options.clientId;
+ this.domain = options.domain;
+
+ this.webAuth = WebAuth.fromNative(io.nstudio.plugins.auth0.Auth0.webAuth(this.clientId, this.domain));
+ const authentication = io.nstudio.plugins.auth0.Auth0.authentication(this.clientId, this.domain);
+
+ this.auth = Authentication.fromNative(authentication);
+
+ this.credentialsManager = CredentialsManager.fromNative(io.nstudio.plugins.auth0.Auth0.credentialsManager(Utils.android.getApplicationContext(), authentication));
+ }
+}
diff --git a/packages/nativescript-auth0/index.d.ts b/packages/nativescript-auth0/index.d.ts
new file mode 100644
index 00000000..e19ecd0e
--- /dev/null
+++ b/packages/nativescript-auth0/index.d.ts
@@ -0,0 +1,131 @@
+export class Credentials {
+ constructor(info?: { accessToken?: string; tokenType?: string; idToken?: string; refreshToken?: string; expiresIn?: Date; scope?: string; recoveryCode: string });
+
+ readonly native;
+
+ readonly accessToken: string;
+
+ readonly expiresIn: number;
+
+ readonly expiresAt: Date | null;
+
+ readonly idToken: string;
+
+ readonly recoveryCode: string;
+
+ readonly refreshToken: string;
+
+ readonly scope: string;
+
+ readonly tokenType: string;
+}
+
+export class CredentialsManager {
+ readonly native;
+
+ clear();
+
+ credentials(scope?: string, minTtl?: number, parameters?: Record, forceRefresh?: boolean): Promise;
+
+ store(credentials: Credentials);
+
+ hasValidCredentials(minTtl?: number): boolean;
+}
+
+export class WebAuth {
+ readonly native;
+
+ useHTTPS(): this;
+
+ start(options?: { scheme?: string; scope?: string; audience?: string; redirectUrl?: string }): Promise;
+
+ clear(options?: { scheme?: string; federated?: boolean; returnToUrl?: string }): Promise;
+}
+
+export class JWT {
+ readonly native;
+
+ readonly identifier: string;
+
+ readonly subject: string;
+
+ readonly issuer: string;
+
+ readonly audience: string;
+
+ readonly issuedAt: Date | null;
+
+ readonly expiresAt: Date | null;
+
+ readonly notBefore: Date | null;
+
+ readonly body: Record;
+}
+
+export function decodeJWT(token: string): JWT;
+
+export class UserInfo {
+ readonly native;
+
+ readonly address;
+
+ readonly birthdate: string;
+
+ readonly customClaims: Record;
+
+ readonly email: string | null;
+
+ readonly emailVerified: boolean;
+
+ readonly familyName: string;
+
+ readonly gender: string | null;
+
+ readonly givenName: string;
+
+ readonly locale: string | null;
+
+ readonly middleName: string | null;
+
+ readonly name: string;
+
+ readonly nickname: string;
+
+ readonly phoneNumber: string | null;
+
+ readonly phoneNumberVerified: boolean;
+
+ readonly picture: string | null;
+
+ readonly preferredUsername: string | null;
+
+ readonly profile: string | null;
+
+ readonly sub: string | null;
+
+ readonly updatedAt: Date;
+
+ readonly website: string | null;
+
+ readonly zoneinfo: string | null;
+}
+
+export class Authentication {
+ readonly native;
+
+ userInfo(options: { accessToken: string; headers?: Record }): Promise;
+
+ refreshToken(options: { refreshToken: string; scope?: string; audience: string; headers?: Record }): Promise;
+
+ revoke(options: { refreshToken: string; headers?: Record }): Promise;
+}
+
+export class Auth0 {
+ readonly clientId: string;
+ readonly domain: string;
+ readonly webAuth: WebAuth;
+ readonly auth: Authentication;
+ readonly credentialsManager: CredentialsManager;
+
+ constructor(options: { clientId: string; domain: string });
+}
diff --git a/packages/nativescript-auth0/index.ios.ts b/packages/nativescript-auth0/index.ios.ts
new file mode 100644
index 00000000..4a050748
--- /dev/null
+++ b/packages/nativescript-auth0/index.ios.ts
@@ -0,0 +1,407 @@
+import { Device, Utils } from '@nativescript/core';
+import { isRealDevice } from '@nativescript/core/utils';
+
+export class Credentials {
+ static fromNative(credentials: NSCAuth0Credentials): Credentials {
+ if (credentials instanceof NSCAuth0Credentials) {
+ const ret = new Credentials();
+ ret.credentials = credentials;
+ return ret;
+ }
+ return null;
+ }
+
+ private credentials: NSCAuth0Credentials;
+
+ constructor(info?: { accessToken?: string; tokenType?: string; idToken?: string; refreshToken?: string; expiresIn?: Date; scope?: string; recoveryCode: string }) {
+ if (info) {
+ this.credentials = NSCAuth0Credentials.alloc().init(info.accessToken ?? null, info.tokenType ?? null, info.idToken ?? null, info.refreshToken ?? null, info.expiresIn ?? null, info.scope ?? null, info.recoveryCode ?? null);
+ }
+ }
+
+ get native() {
+ return this.credentials;
+ }
+
+ get accessToken(): string {
+ return this.credentials.accessToken;
+ }
+
+ get expiresIn(): Date {
+ return this.credentials.expiresIn;
+ }
+
+ get idToken(): string {
+ return this.credentials.idToken;
+ }
+
+ get recoveryCode(): string {
+ return this.credentials.recoveryCode;
+ }
+
+ get refreshToken(): string {
+ return this.credentials.refreshToken;
+ }
+
+ get scope(): string {
+ return this.credentials.scope;
+ }
+
+ get tokenType(): string {
+ return this.credentials.tokenType;
+ }
+
+ toJSON() {
+ const redacted = '';
+ return {
+ accessToken: redacted,
+ expiresIn: this.expiresIn,
+ idToken: redacted,
+ recoveryCode: this.recoveryCode,
+ refreshToken: this.refreshToken ? redacted : null,
+ scope: this.scope,
+ tokenType: this.tokenType ? redacted : null,
+ };
+ }
+}
+
+export class CredentialsManager {
+ static fromNative(manager: NSCAuth0CredentialsManager): CredentialsManager {
+ if (manager instanceof NSCAuth0CredentialsManager) {
+ const ret = new CredentialsManager();
+ ret.credentialsManager = manager;
+ return ret;
+ }
+ return null;
+ }
+
+ private credentialsManager: NSCAuth0CredentialsManager;
+
+ get native() {
+ return this.credentialsManager;
+ }
+
+ clear() {
+ this.credentialsManager.clear();
+ }
+
+ credentials(scope?: string, minTtl?: number, parameters?: Record, forceRefresh?: boolean): Promise {
+ return new Promise((resolve, reject) => {
+ this.credentialsManager.credentials(scope ?? null, minTtl ?? 0, Utils.dataSerialize(parameters ?? {}), forceRefresh ?? false, (credentials, error) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve(Credentials.fromNative(credentials));
+ }
+ });
+ });
+ }
+
+ store(credentials: Credentials) {
+ this.credentialsManager.store(credentials.native);
+ }
+
+ hasValidCredentials(minTtl?: number): boolean {
+ return this.credentialsManager.hasValid(minTtl ?? 0);
+ }
+}
+
+export class WebAuth {
+ static fromNative(auth: NSCAuth0WebAuth): WebAuth {
+ if (auth instanceof NSCAuth0WebAuth) {
+ const ret = new WebAuth();
+ ret.webAuth = auth;
+ return ret;
+ }
+ return null;
+ }
+
+ get native() {
+ return this.webAuth;
+ }
+
+ private webAuth: NSCAuth0WebAuth;
+
+ useHTTPS(): this {
+ this.webAuth.useHTTPS();
+ return this;
+ }
+
+ start(options?: { scheme?: string; scope?: string; audience?: string; redirectUrl?: string }) {
+ return new Promise((resolve, reject) => {
+ this.webAuth.start(options?.scope, options?.audience, (credentials, error) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve(Credentials.fromNative(credentials));
+ }
+ });
+ });
+ }
+
+ clear(options?: { scheme?: string; federated?: boolean; returnToUrl?: string }) {
+ return new Promise((resolve, reject) => {
+ this.webAuth.clearSessionWithFederated(options?.federated ?? false, (error) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve();
+ }
+ });
+ });
+ }
+}
+
+export class JWT {
+ static fromNative(jwt: NSCAuth0DecodedJWT): JWT {
+ if (jwt instanceof NSCAuth0DecodedJWT) {
+ const ret = new JWT();
+ ret.jwt = jwt;
+ return ret;
+ }
+ return null;
+ }
+
+ private jwt: NSCAuth0DecodedJWT;
+
+ get native() {
+ return this.jwt;
+ }
+
+ get identifier() {
+ return this.jwt.identifier;
+ }
+
+ get subject() {
+ return this.jwt.subject;
+ }
+
+ get issuer() {
+ return this.jwt.issuer;
+ }
+
+ get audience() {
+ return Utils.dataDeserialize(this.jwt.audience);
+ }
+
+ get issuedAt() {
+ return this.jwt.issuedAt;
+ }
+
+ get expiresAt() {
+ return this.jwt.expiresAt;
+ }
+
+ get notBefore() {
+ return this.jwt.notBefore;
+ }
+
+ get body() {
+ return Utils.dataDeserialize(this.jwt.body);
+ }
+
+ toJSON() {
+ return {
+ identifier: this.identifier,
+ subject: this.subject,
+ issuer: this.issuer,
+ audience: this.audience,
+ issuedAt: this.issuedAt,
+ expiresAt: this.expiresAt,
+ notBefore: this.notBefore,
+ body: this.body,
+ };
+ }
+}
+
+export function decodeJWT(token: string): JWT {
+ return JWT.fromNative(NSCAuth0.decodeJWTError(token));
+}
+
+export class UserInfo {
+ static fromNative(userInfo: NSCAuth0UserInfo): UserInfo {
+ if (userInfo instanceof NSCAuth0UserInfo) {
+ const ret = new UserInfo();
+ ret.userInfo = userInfo;
+ return ret;
+ }
+ return null;
+ }
+ private userInfo: NSCAuth0UserInfo;
+
+ get native() {
+ return this.userInfo;
+ }
+
+ get address() {
+ return Utils.dataDeserialize(this.userInfo.address);
+ }
+
+ get birthdate(): string {
+ return this.userInfo.birthdate;
+ }
+
+ get customClaims(): Record {
+ return Utils.dataDeserialize(this.userInfo.customClaims);
+ }
+
+ get email(): string {
+ return this.userInfo.email;
+ }
+
+ get emailVerified(): boolean {
+ return this.userInfo.emailVerified;
+ }
+
+ get familyName(): string {
+ return this.userInfo.familyName;
+ }
+
+ get gender(): string {
+ return this.userInfo.gender;
+ }
+
+ get givenName(): string {
+ return this.userInfo.givenName;
+ }
+
+ get locale(): string {
+ return this.userInfo.locale.languageCode;
+ }
+
+ get middleName(): string {
+ return this.userInfo.middleName;
+ }
+
+ get name(): string {
+ return this.userInfo.name;
+ }
+
+ get nickname(): string {
+ return this.userInfo.nickname;
+ }
+
+ get phoneNumber(): string {
+ return this.userInfo.phoneNumber;
+ }
+
+ get phoneNumberVerified(): boolean {
+ return this.userInfo.phoneNumberVerified;
+ }
+
+ get picture(): string | null {
+ const picture = this.userInfo.picture;
+ if (picture) {
+ return picture.absoluteString;
+ }
+ return null;
+ }
+
+ get preferredUsername(): string {
+ return this.userInfo.preferredUsername;
+ }
+
+ get profile(): string | null {
+ const profile = this.userInfo.profile;
+ if (profile) {
+ return profile.absoluteString;
+ }
+ return null;
+ }
+
+ get sub(): string {
+ return this.userInfo.sub;
+ }
+
+ get updatedAt(): Date {
+ return this.userInfo.updatedAt;
+ }
+
+ get website(): string | null {
+ const website = this.userInfo.website;
+ if (website) {
+ return website.absoluteString;
+ }
+ return null;
+ }
+
+ get zoneinfo(): string {
+ return this.userInfo.zoneinfo.name;
+ }
+}
+
+export class Authentication {
+ static fromNative(auth: NSCAuth0Authentication): Authentication {
+ if (auth instanceof NSCAuth0Authentication) {
+ const ret = new Authentication();
+ ret.authentication = auth;
+ return ret;
+ }
+ return null;
+ }
+
+ private authentication: NSCAuth0Authentication;
+
+ get native() {
+ return this.authentication;
+ }
+
+ userInfo(options: { accessToken: string; headers?: Record }) {
+ return new Promise((resolve, reject) => {
+ this.authentication.userInfo(options.accessToken, Utils.dataSerialize(options.headers ?? {}), (userInfo, error) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve(UserInfo.fromNative(userInfo));
+ }
+ });
+ });
+ }
+
+ refreshToken(options: { refreshToken: string; audience?: string; scope?: string; headers?: Record }) {
+ return new Promise((resolve, reject) => {
+ this.authentication.refreshToken(options.refreshToken, options.scope ?? null, options.audience ?? null, Utils.dataSerialize(options.headers ?? {}), (credentials, error) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve(Credentials.fromNative(credentials));
+ }
+ });
+ });
+ }
+
+ revoke(options: { refreshToken: string; headers?: Record }) {
+ return new Promise((resolve, reject) => {
+ this.authentication.revoke(options.refreshToken, Utils.dataSerialize(options.headers ?? {}), (error) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve();
+ }
+ });
+ });
+ }
+}
+
+export class Auth0 {
+ readonly clientId: string;
+ readonly domain: string;
+ readonly webAuth: WebAuth;
+ readonly auth: Authentication;
+ readonly credentialsManager: CredentialsManager;
+
+ constructor(options: { clientId: string; domain: string }) {
+ this.clientId = options.clientId;
+ this.domain = options.domain;
+
+ const sessionConfig = parseFloat(Device.sdkVersion) >= 18.0 && !isRealDevice() ? NSURLSessionConfiguration.ephemeralSessionConfiguration : NSURLSessionConfiguration.defaultSessionConfiguration;
+
+ const session = NSURLSession.sessionWithConfiguration(sessionConfig);
+
+ this.webAuth = WebAuth.fromNative(NSCAuth0.webAuthWithClientIdDomainSession(this.clientId, this.domain, session));
+ const authentication = NSCAuth0.authenticationWithClientIdDomainSession(this.clientId, this.domain, session);
+
+ this.auth = Authentication.fromNative(authentication);
+ this.credentialsManager = CredentialsManager.fromNative(NSCAuth0.credentialsManagerWithAuthentication(authentication));
+ }
+}
diff --git a/packages/nativescript-auth0/nativescript.config.ts b/packages/nativescript-auth0/nativescript.config.ts
new file mode 100644
index 00000000..574cc007
--- /dev/null
+++ b/packages/nativescript-auth0/nativescript.config.ts
@@ -0,0 +1,15 @@
+import { NativeScriptConfig } from '@nativescript/core';
+
+export default {
+ ios: {
+ discardUncaughtJsExceptions: false,
+ SPMPackages: [
+ {
+ name: 'Auth0',
+ libs: ['Auth0'],
+ repositoryURL: 'https://github.com/auth0/Auth0.swift',
+ version: '2.15.1',
+ },
+ ],
+ },
+} as NativeScriptConfig;
diff --git a/packages/nativescript-auth0/package.json b/packages/nativescript-auth0/package.json
new file mode 100644
index 00000000..79727621
--- /dev/null
+++ b/packages/nativescript-auth0/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "@nstudio/nativescript-auth0",
+ "version": "0.0.5",
+ "description": "Auth0 for NativeScript",
+ "main": "index",
+ "types": "index.d.ts",
+ "nativescript": {
+ "platforms": {
+ "ios": "6.0.0",
+ "android": "6.0.0"
+ }
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/nstudio/nativescript-plugins.git"
+ },
+ "keywords": [
+ "NativeScript",
+ "JavaScript",
+ "TypeScript",
+ "iOS",
+ "Android",
+ "Auth0"
+ ],
+ "author": {
+ "name": "nStudio",
+ "email": "team@nstudio.io"
+ },
+ "bugs": {
+ "url": "https://github.com/nstudio/nativescript-plugins/issues"
+ },
+ "license": "Apache-2.0",
+ "homepage": "https://github.com/nstudio/nativescript-plugins",
+ "readmeFilename": "README.md",
+ "bootstrapper": "@nativescript/plugin-seed"
+}
diff --git a/packages/nativescript-auth0/platforms/android/include.gradle b/packages/nativescript-auth0/platforms/android/include.gradle
new file mode 100644
index 00000000..8499c01f
--- /dev/null
+++ b/packages/nativescript-auth0/platforms/android/include.gradle
@@ -0,0 +1,3 @@
+dependencies {
+ implementation 'com.auth0.android:auth0:3.8.0'
+}
\ No newline at end of file
diff --git a/packages/nativescript-auth0/platforms/android/java/io/nstudio/plugins/auth0/Auth0.kt b/packages/nativescript-auth0/platforms/android/java/io/nstudio/plugins/auth0/Auth0.kt
new file mode 100644
index 00000000..3bb642ea
--- /dev/null
+++ b/packages/nativescript-auth0/platforms/android/java/io/nstudio/plugins/auth0/Auth0.kt
@@ -0,0 +1,99 @@
+package io.nstudio.plugins.auth0
+
+
+import android.content.Context
+import com.auth0.android.authentication.AuthenticationAPIClient
+import com.auth0.android.result.Credentials
+import java.util.Date
+
+class Auth0(val auth0: com.auth0.android.Auth0) {
+ fun authentication(): Authentication {
+ return Authentication(AuthenticationAPIClient(auth0))
+ }
+
+ fun webAuth(): WebAuth {
+ return WebAuth(auth0)
+ }
+
+
+ companion object {
+ @JvmStatic
+ fun getInstance(context: Context): Auth0 {
+ return Auth0(com.auth0.android.Auth0.getInstance(context))
+ }
+
+ @JvmStatic
+ fun authentication(context: Context): Authentication {
+ return Authentication(AuthenticationAPIClient(com.auth0.android.Auth0.getInstance(context)))
+ }
+
+ @JvmStatic
+ fun authentication(clientId: String, domain: String): Authentication {
+ return Authentication(
+ AuthenticationAPIClient(
+ com.auth0.android.Auth0.getInstance(
+ clientId,
+ domain
+ )
+ )
+ )
+ }
+
+ @JvmStatic
+ fun credentialsManager(context: Context, authentication: Authentication): CredentialsManager {
+ val storage = com.auth0.android.authentication.storage.SharedPreferencesStorage(context)
+ return CredentialsManager(
+ com.auth0.android.authentication.storage.CredentialsManager(
+ authentication.authentication,
+ storage
+ )
+ )
+ }
+
+ @JvmStatic
+ fun webAuth(context: Context): WebAuth {
+ return WebAuth(com.auth0.android.Auth0.getInstance(context))
+ }
+
+ @JvmStatic
+ fun webAuth(clientId: String, domain: String): WebAuth {
+ return WebAuth(
+ com.auth0.android.Auth0.getInstance(
+ clientId,
+ domain
+ )
+ )
+ }
+
+ @JvmStatic
+ fun decodeJWT(token: String): DecodedJWT {
+ return DecodedJWT(token)
+ }
+
+ @JvmStatic
+ fun createCredentials(
+ accessToken: String?,
+ tokenType: String?,
+ idToken: String?,
+ refreshToken: String?,
+ expiresIn: Long,
+ scope: String?,
+ recoveryCode: String
+ ): Credentials {
+ val credentials = Credentials(
+ idToken ?: "",
+ accessToken ?: "",
+ tokenType ?: "",
+ refreshToken,
+ Date(expiresIn),
+ scope
+ )
+
+ val field = credentials::class.java.getDeclaredField("recoveryCode")
+ field.isAccessible = true
+ field.set(credentials, recoveryCode)
+
+ return credentials
+ }
+ }
+}
diff --git a/packages/nativescript-auth0/platforms/android/java/io/nstudio/plugins/auth0/Authentication.kt b/packages/nativescript-auth0/platforms/android/java/io/nstudio/plugins/auth0/Authentication.kt
new file mode 100644
index 00000000..c9d8b888
--- /dev/null
+++ b/packages/nativescript-auth0/platforms/android/java/io/nstudio/plugins/auth0/Authentication.kt
@@ -0,0 +1,92 @@
+package io.nstudio.plugins.auth0
+
+import com.auth0.android.authentication.AuthenticationException
+import com.auth0.android.callback.Callback
+import com.auth0.android.result.Credentials
+import com.auth0.android.result.UserProfile
+
+class Authentication(val authentication: com.auth0.android.authentication.AuthenticationAPIClient) {
+ fun signup(
+ email: String,
+ password: String,
+ username: String? = null,
+ connection: String,
+ userMetadata: Map? = null,
+ callback: (Credentials?, Exception?) -> Void
+ ) {
+ authentication.signUp(email, password, username, connection, userMetadata).start(object :
+ Callback {
+ override fun onFailure(error: AuthenticationException) {
+ callback(null, error)
+ }
+
+ override fun onSuccess(result: Credentials) {
+ callback(result, null)
+ }
+ })
+ }
+
+ fun revoke(refreshToken: String, headers: Map?, callback: (Exception?) -> Void) {
+ val request = authentication.revokeToken(refreshToken)
+ headers?.let {
+ for ((key, value) in it) {
+ request.addHeader(key, value)
+ }
+ }
+ request.start(object : Callback {
+ override fun onFailure(error: AuthenticationException) {
+ callback(error)
+ }
+
+ override fun onSuccess(result: Void?) {
+ callback(null)
+ }
+ })
+ }
+
+ fun userInfo(
+ token: String,
+ headers: Map?,
+ callback: (UserProfile?, Exception?) -> Void
+ ) {
+ val request = authentication.userInfo(token)
+ headers?.let {
+ for ((key, value) in it) {
+ request.addHeader(key, value)
+ }
+ }
+ request.start(object : Callback {
+ override fun onFailure(error: AuthenticationException) {
+ callback(null, error)
+ }
+
+ override fun onSuccess(result: UserProfile) {
+ callback(result, null)
+ }
+ })
+ }
+
+ fun refreshToken(
+ refreshToken: String,
+ scope: String?,
+ audience: String?,
+ headers: Map?,
+ callback: (Credentials?, Exception?) -> Void
+ ) {
+ val request = authentication.renewAuth(refreshToken, audience, scope)
+ headers?.let {
+ for ((key, value) in it) {
+ request.addHeader(key, value)
+ }
+ }
+ request.start(object : Callback {
+ override fun onFailure(error: AuthenticationException) {
+ callback(null, error)
+ }
+
+ override fun onSuccess(result: Credentials) {
+ callback(result, null)
+ }
+ })
+ }
+}
diff --git a/packages/nativescript-auth0/platforms/android/java/io/nstudio/plugins/auth0/CredentialsManager.kt b/packages/nativescript-auth0/platforms/android/java/io/nstudio/plugins/auth0/CredentialsManager.kt
new file mode 100644
index 00000000..a3ac3169
--- /dev/null
+++ b/packages/nativescript-auth0/platforms/android/java/io/nstudio/plugins/auth0/CredentialsManager.kt
@@ -0,0 +1,63 @@
+package io.nstudio.plugins.auth0
+
+import com.auth0.android.authentication.storage.CredentialsManagerException
+import com.auth0.android.callback.Callback
+import com.auth0.android.result.Credentials
+import com.auth0.android.result.UserProfile
+
+
+class CredentialsManager(val credentialsManager: com.auth0.android.authentication.storage.CredentialsManager) {
+
+ fun credentials(
+ scope: String?,
+ minTtl: Int = 0,
+ parameters: Map = mapOf(),
+ forceRefresh: Boolean = false,
+ callback: (Credentials?, Exception?) -> Void
+ ) {
+ credentialsManager.getCredentials(scope, minTtl, parameters, forceRefresh, object :
+ Callback {
+ override fun onFailure(error: CredentialsManagerException) {
+ callback(null, error)
+ }
+
+ override fun onSuccess(result: Credentials) {
+ callback(result, null)
+ }
+ })
+ }
+
+ fun hasValid(minTtL: Long = 0): Boolean {
+ return credentialsManager.hasValidCredentials(minTtL)
+ }
+
+ fun user(callback: (UserProfile?, Exception?) -> Void) {
+ credentialsManager.getCredentials(object : Callback {
+ override fun onFailure(error: CredentialsManagerException) {
+ callback(null, error)
+ }
+
+ override fun onSuccess(result: Credentials) {
+ callback(result.user, null)
+ }
+ })
+ }
+
+ fun clear(): Boolean {
+ credentialsManager.clearCredentials()
+ return true
+ }
+
+ fun store(credentials: Credentials): Boolean {
+ try {
+ credentialsManager.saveCredentials(credentials)
+ return true
+ } catch (e: Exception) {
+ return false
+ }
+ }
+
+ fun canRenew(): Boolean {
+ return credentialsManager.hasValidCredentials()
+ }
+}
diff --git a/packages/nativescript-auth0/platforms/android/java/io/nstudio/plugins/auth0/DecodedJWT.kt b/packages/nativescript-auth0/platforms/android/java/io/nstudio/plugins/auth0/DecodedJWT.kt
new file mode 100644
index 00000000..0fbca54b
--- /dev/null
+++ b/packages/nativescript-auth0/platforms/android/java/io/nstudio/plugins/auth0/DecodedJWT.kt
@@ -0,0 +1,392 @@
+package io.nstudio.plugins.auth0
+
+import android.util.Base64
+import android.util.Log
+import androidx.annotation.VisibleForTesting
+import com.auth0.android.result.Credentials
+import com.auth0.android.result.UserIdentity
+import com.auth0.android.result.UserProfile
+import com.google.gson.Gson
+import com.google.gson.GsonBuilder
+import com.google.gson.JsonDeserializationContext
+import com.google.gson.JsonDeserializer
+import com.google.gson.JsonElement
+import com.google.gson.JsonParseException
+import com.google.gson.TypeAdapter
+import com.google.gson.TypeAdapterFactory
+import com.google.gson.reflect.TypeToken
+import com.google.gson.stream.JsonReader
+import com.google.gson.stream.JsonWriter
+import java.io.IOException
+import java.lang.reflect.Field
+import java.lang.reflect.Type
+import java.math.BigInteger
+import java.security.KeyFactory
+import java.security.NoSuchAlgorithmException
+import java.security.PublicKey
+import java.security.spec.InvalidKeySpecException
+import java.security.spec.RSAPublicKeySpec
+import java.text.SimpleDateFormat
+import java.util.Date
+import java.util.Locale
+
+// Copy of com.auth0.android.request.internal.Jwt
+class DecodedJWT(token: String) {
+ internal class JwksDeserializer : JsonDeserializer