├── docs
└── images
│ ├── oauth2-logo.png
│ └── nativescript-oauth-logo.png
├── .gitignore
├── demo
├── app
│ ├── App_Resources
│ │ ├── iOS
│ │ │ ├── Assets.xcassets
│ │ │ │ ├── Contents.json
│ │ │ │ ├── AppIcon.appiconset
│ │ │ │ │ ├── icon-29.png
│ │ │ │ │ ├── icon-40.png
│ │ │ │ │ ├── icon-50.png
│ │ │ │ │ ├── icon-57.png
│ │ │ │ │ ├── icon-72.png
│ │ │ │ │ ├── icon-76.png
│ │ │ │ │ ├── icon-29@2x.png
│ │ │ │ │ ├── icon-29@3x.png
│ │ │ │ │ ├── icon-40@2x.png
│ │ │ │ │ ├── icon-40@3x.png
│ │ │ │ │ ├── icon-50@2x.png
│ │ │ │ │ ├── icon-57@2x.png
│ │ │ │ │ ├── icon-60@2x.png
│ │ │ │ │ ├── icon-60@3x.png
│ │ │ │ │ ├── icon-72@2x.png
│ │ │ │ │ ├── icon-76@2x.png
│ │ │ │ │ ├── icon-83.5@2x.png
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── LaunchImage.launchimage
│ │ │ │ │ ├── Default.png
│ │ │ │ │ ├── Default@2x.png
│ │ │ │ │ ├── Default-568h@2x.png
│ │ │ │ │ ├── Default-667h@2x.png
│ │ │ │ │ ├── Default-736h@3x.png
│ │ │ │ │ ├── Default-Landscape.png
│ │ │ │ │ ├── Default-Portrait.png
│ │ │ │ │ ├── Default-Portrait@2x.png
│ │ │ │ │ ├── Default-Landscape@2x.png
│ │ │ │ │ ├── Default-Landscape@3x.png
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── LaunchScreen.Center.imageset
│ │ │ │ │ ├── LaunchScreen-Center.png
│ │ │ │ │ ├── LaunchScreen-Center@2x.png
│ │ │ │ │ └── Contents.json
│ │ │ │ └── LaunchScreen.AspectFill.imageset
│ │ │ │ │ ├── LaunchScreen-AspectFill.png
│ │ │ │ │ ├── LaunchScreen-AspectFill@2x.png
│ │ │ │ │ └── Contents.json
│ │ │ ├── build.xcconfig
│ │ │ ├── Info.plist
│ │ │ └── LaunchScreen.storyboard
│ │ └── Android
│ │ │ ├── values-v21
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ │ ├── drawable-hdpi
│ │ │ ├── icon.png
│ │ │ ├── logo.png
│ │ │ └── background.png
│ │ │ ├── drawable-ldpi
│ │ │ ├── icon.png
│ │ │ ├── logo.png
│ │ │ └── background.png
│ │ │ ├── drawable-mdpi
│ │ │ ├── icon.png
│ │ │ ├── logo.png
│ │ │ └── background.png
│ │ │ ├── drawable-xhdpi
│ │ │ ├── icon.png
│ │ │ ├── logo.png
│ │ │ └── background.png
│ │ │ ├── drawable-xxhdpi
│ │ │ ├── icon.png
│ │ │ ├── logo.png
│ │ │ └── background.png
│ │ │ ├── drawable-xxxhdpi
│ │ │ ├── icon.png
│ │ │ ├── logo.png
│ │ │ └── background.png
│ │ │ ├── values
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ │ ├── drawable-nodpi
│ │ │ └── splash_screen.xml
│ │ │ ├── app.gradle
│ │ │ └── AndroidManifest.xml
│ ├── package.json
│ ├── bundle-config.ts
│ ├── app.css
│ ├── README.md
│ ├── main-view-model.ts
│ ├── app.ts
│ ├── main-page.ts
│ └── main-page.xml
├── typings
│ ├── url.d.ts
│ └── querystring.d.ts
├── tsconfig.json
├── .vscode
│ └── launch.json
└── package.json
├── demo-angular
├── app
│ ├── App_Resources
│ │ ├── iOS
│ │ │ ├── Assets.xcassets
│ │ │ │ ├── Contents.json
│ │ │ │ ├── AppIcon.appiconset
│ │ │ │ │ ├── icon-29.png
│ │ │ │ │ ├── icon-40.png
│ │ │ │ │ ├── icon-50.png
│ │ │ │ │ ├── icon-57.png
│ │ │ │ │ ├── icon-72.png
│ │ │ │ │ ├── icon-76.png
│ │ │ │ │ ├── icon-29@2x.png
│ │ │ │ │ ├── icon-29@3x.png
│ │ │ │ │ ├── icon-40@2x.png
│ │ │ │ │ ├── icon-40@3x.png
│ │ │ │ │ ├── icon-50@2x.png
│ │ │ │ │ ├── icon-57@2x.png
│ │ │ │ │ ├── icon-60@2x.png
│ │ │ │ │ ├── icon-60@3x.png
│ │ │ │ │ ├── icon-72@2x.png
│ │ │ │ │ ├── icon-76@2x.png
│ │ │ │ │ ├── icon-83.5@2x.png
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── LaunchImage.launchimage
│ │ │ │ │ ├── Default.png
│ │ │ │ │ ├── Default@2x.png
│ │ │ │ │ ├── Default-568h@2x.png
│ │ │ │ │ ├── Default-667h@2x.png
│ │ │ │ │ ├── Default-736h@3x.png
│ │ │ │ │ ├── Default-Portrait.png
│ │ │ │ │ ├── Default-Landscape.png
│ │ │ │ │ ├── Default-Portrait@2x.png
│ │ │ │ │ ├── Default-Landscape@2x.png
│ │ │ │ │ ├── Default-Landscape@3x.png
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── LaunchScreen.Center.imageset
│ │ │ │ │ ├── LaunchScreen-Center.png
│ │ │ │ │ ├── LaunchScreen-Center@2x.png
│ │ │ │ │ └── Contents.json
│ │ │ │ └── LaunchScreen.AspectFill.imageset
│ │ │ │ │ ├── LaunchScreen-AspectFill.png
│ │ │ │ │ ├── LaunchScreen-AspectFill@2x.png
│ │ │ │ │ └── Contents.json
│ │ │ ├── build.xcconfig
│ │ │ ├── Info.plist
│ │ │ └── LaunchScreen.storyboard
│ │ └── Android
│ │ │ ├── values-v21
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ │ ├── drawable-hdpi
│ │ │ ├── icon.png
│ │ │ ├── logo.png
│ │ │ └── background.png
│ │ │ ├── drawable-ldpi
│ │ │ ├── icon.png
│ │ │ ├── logo.png
│ │ │ └── background.png
│ │ │ ├── drawable-mdpi
│ │ │ ├── icon.png
│ │ │ ├── logo.png
│ │ │ └── background.png
│ │ │ ├── drawable-xhdpi
│ │ │ ├── icon.png
│ │ │ ├── logo.png
│ │ │ └── background.png
│ │ │ ├── drawable-xxhdpi
│ │ │ ├── icon.png
│ │ │ ├── logo.png
│ │ │ └── background.png
│ │ │ ├── drawable-xxxhdpi
│ │ │ ├── icon.png
│ │ │ ├── logo.png
│ │ │ └── background.png
│ │ │ ├── values
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ │ ├── drawable-nodpi
│ │ │ └── splash_screen.xml
│ │ │ ├── app.gradle
│ │ │ └── AndroidManifest.xml
│ ├── app.component.html
│ ├── main.aot.ts
│ ├── app.module.ts
│ ├── app.css
│ ├── app.component.ts
│ ├── package.json
│ └── main.ts
├── lib
│ └── iOS
│ │ └── TNSWidgets.framework
│ │ ├── Info.plist
│ │ ├── TNSWidgets
│ │ ├── Modules
│ │ └── module.modulemap
│ │ └── Headers
│ │ ├── TNSLabel.h
│ │ ├── TNSWidgets.h
│ │ └── UIImage+TNSBlocks.h
├── tsconfig.json
└── package.json
├── .npmignore
├── typings
├── url.d.ts
└── querystring.d.ts
├── tns-oauth-webview-helper.d.ts
├── references.d.ts
├── auth-helper-custom.ts
├── tns-oauth-utils.ts
├── auth-helper-google.ts
├── auth-helper-office365.ts
├── auth-helper-facebook.ts
├── LICENSE
├── index.d.ts
├── auth-helper-linkedin.ts
├── auth-helper-uaa.ts
├── tsconfig.json
├── tns-oauth-token-cache.ts
├── tns-oauth-page-provider.ts
├── tns-oauth-webview.ts
├── package.json
├── tns-oauth-interfaces.d.ts
├── auth-helper-salesforce.ts
├── auth-helper.ts
├── tns-oauth-webview-helper.ios.ts
├── tns-oauth-webview-helper.android.ts
├── index.ts
├── README.md
└── tns-oauth.ts
/docs/images/oauth2-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/docs/images/oauth2-logo.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.js
2 | *.js.map
3 | *.log
4 | demo*/app/*.js
5 | demo*/*.d.ts
6 | demo*/platforms
7 | demo*/node_modules
8 | node_modules
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/docs/images/nativescript-oauth-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/docs/images/nativescript-oauth-logo.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/values-v21/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3d5afe
4 |
--------------------------------------------------------------------------------
/demo-angular/lib/iOS/TNSWidgets.framework/Info.plist:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/lib/iOS/TNSWidgets.framework/Info.plist
--------------------------------------------------------------------------------
/demo-angular/lib/iOS/TNSWidgets.framework/TNSWidgets:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/lib/iOS/TNSWidgets.framework/TNSWidgets
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-hdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-hdpi/logo.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-ldpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-ldpi/logo.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-mdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-mdpi/logo.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/values-v21/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3d5afe
4 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-xhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-xhdpi/logo.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-xxhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-xxhdpi/logo.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-xxxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-xxxhdpi/icon.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-xxxhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-xxxhdpi/logo.png
--------------------------------------------------------------------------------
/demo/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "android": {
3 | "v8Flags": "--expose_gc"
4 | },
5 | "main": "app.js",
6 | "name": "tns-template-hello-world-ts",
7 | "version": "2.5.0"
8 | }
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-hdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-hdpi/background.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-ldpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-ldpi/background.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-mdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-mdpi/background.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-xhdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-xhdpi/background.png
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | demo/
2 | demo-angular/
3 | node_modules/
4 | hooks/
5 | *.log
6 | *.ts
7 | *.js.map
8 | tsconfig.json
9 |
10 | !index.d.ts
11 | !tns-oauth-interfaces.d.ts
12 | !*.js
13 |
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-hdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-hdpi/logo.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-ldpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-ldpi/logo.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-mdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-mdpi/logo.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-xhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-xhdpi/logo.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-xxhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-xxhdpi/logo.png
--------------------------------------------------------------------------------
/demo-angular/lib/iOS/TNSWidgets.framework/Modules/module.modulemap:
--------------------------------------------------------------------------------
1 | framework module TNSWidgets {
2 | umbrella header "TNSWidgets.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-xxhdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-xxhdpi/background.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-xxxhdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/Android/drawable-xxxhdpi/background.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-xxxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-xxxhdpi/icon.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-xxxhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-xxxhdpi/logo.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-hdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-hdpi/background.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-ldpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-ldpi/background.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-mdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-mdpi/background.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-xhdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-xhdpi/background.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-xxhdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-xxhdpi/background.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-xxxhdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/Android/drawable-xxxhdpi/background.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png
--------------------------------------------------------------------------------
/typings/url.d.ts:
--------------------------------------------------------------------------------
1 |
2 | declare module "url" {
3 | export function Url(): void;
4 | export function parse(url: string, parseQueryString?: boolean, slashesDenoteHost?: boolean): any;
5 | }
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/demo/typings/url.d.ts:
--------------------------------------------------------------------------------
1 |
2 | declare module "url" {
3 | export function Url(): void;
4 | export function parse(url: string, parseQueryString?: boolean, slashesDenoteHost?: boolean): any;
5 | }
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png
--------------------------------------------------------------------------------
/demo-angular/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png
--------------------------------------------------------------------------------
/demo/app/bundle-config.ts:
--------------------------------------------------------------------------------
1 | if ((global).TNS_WEBPACK) {
2 | //registers tns-core-modules UI framework modules
3 | require("bundle-entry-points");
4 |
5 | //register application modules
6 | global.registerModule("main-page", () => require("./main-page"));
7 | }
8 |
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexziskind1/nativescript-oauth/HEAD/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png
--------------------------------------------------------------------------------
/tns-oauth-webview-helper.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { WebView } from 'ui/web-view';
4 |
5 | export declare class TnsOAuthWebViewHelper {
6 | constructor();
7 |
8 | static initWithWebViewAndIntercept(wv: WebView, checkCodeIntercept);
9 | }
10 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #F5F5F5
4 | #757575
5 | #33B5E5
6 | #272734
7 |
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #F5F5F5
4 | #757575
5 | #33B5E5
6 | #272734
7 |
--------------------------------------------------------------------------------
/demo-angular/app/main.aot.ts:
--------------------------------------------------------------------------------
1 | // this import should be first in order to load some required settings (like globals and reflect-metadata)
2 | import { platformNativeScript } from "nativescript-angular/platform-static";
3 |
4 | import { AppModuleNgFactory } from "./app.module.ngfactory";
5 |
6 | platformNativeScript().bootstrapModuleFactory(AppModuleNgFactory);
7 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/drawable-nodpi/splash_screen.xml:
--------------------------------------------------------------------------------
1 |
2 | -
3 |
4 |
5 | -
6 |
7 |
8 |
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/drawable-nodpi/splash_screen.xml:
--------------------------------------------------------------------------------
1 |
2 | -
3 |
4 |
5 | -
6 |
7 |
8 |
--------------------------------------------------------------------------------
/demo-angular/lib/iOS/TNSWidgets.framework/Headers/TNSLabel.h:
--------------------------------------------------------------------------------
1 | //
2 | // TNSLabel.h
3 | // TNSWidgets
4 | //
5 | // Created by Hristo Hristov on 6/9/16.
6 | // Copyright © 2016 Telerik A D. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TNSLabel : UILabel
12 |
13 | @property(nonatomic) UIEdgeInsets padding;
14 | @property(nonatomic) UIEdgeInsets borderThickness;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/references.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | //
5 | ///
6 | ///
7 | ///
8 |
--------------------------------------------------------------------------------
/demo-angular/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core";
2 | import { NativeScriptModule } from "nativescript-angular/nativescript.module";
3 |
4 | import { AppComponent } from "./app.component";
5 |
6 | @NgModule({
7 | declarations: [AppComponent],
8 | bootstrap: [AppComponent],
9 | imports: [NativeScriptModule],
10 | schemas: [NO_ERRORS_SCHEMA]
11 | })
12 | export class AppModule { }
13 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/app.gradle:
--------------------------------------------------------------------------------
1 | // Add your native dependencies here:
2 |
3 | // Uncomment to add recyclerview-v7 dependency
4 | //dependencies {
5 | // compile 'com.android.support:recyclerview-v7:+'
6 | //}
7 |
8 | android {
9 | defaultConfig {
10 | generatedDensities = []
11 | applicationId = "org.nativescript.demowtf"
12 | }
13 | aaptOptions {
14 | additionalParameters "--no-version-vectors"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchScreen-Center.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchScreen-Center@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchScreen-Center.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchScreen-Center@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchScreen-AspectFill.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchScreen-AspectFill@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/build.xcconfig:
--------------------------------------------------------------------------------
1 | // You can add custom settings here
2 | // for example you can uncomment the following line to force distribution code signing
3 | // CODE_SIGN_IDENTITY = iPhone Distribution
4 | // To build for device with XCode 8 you need to specify your development team. More info: https://developer.apple.com/library/prerelease/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html
5 | // DEVELOPMENT_TEAM = YOUR_TEAM_ID;
6 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
7 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
8 |
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchScreen-AspectFill.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchScreen-AspectFill@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/build.xcconfig:
--------------------------------------------------------------------------------
1 | // You can add custom settings here
2 | // for example you can uncomment the following line to force distribution code signing
3 | // CODE_SIGN_IDENTITY = iPhone Distribution
4 | // To build for device with Xcode 8 you need to specify your development team. More info: https://developer.apple.com/library/prerelease/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html
5 | // DEVELOPMENT_TEAM = YOUR_TEAM_ID;
6 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
7 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
8 |
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/app.gradle:
--------------------------------------------------------------------------------
1 | // Add your native dependencies here:
2 |
3 | // Uncomment to add recyclerview-v7 dependency
4 | //dependencies {
5 | // compile 'com.android.support:recyclerview-v7:+'
6 | //}
7 |
8 | android {
9 | defaultConfig {
10 | generatedDensities = []
11 | applicationId = "org.nativescript.demoangular"
12 |
13 | //override supported platforms
14 | // ndk {
15 | // abiFilters.clear()
16 | // abiFilters "armeabi-v7a"
17 | // }
18 |
19 | }
20 | aaptOptions {
21 | additionalParameters "--no-version-vectors"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/demo/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es5",
5 | "experimentalDecorators": true,
6 | "emitDecoratorMetadata": true,
7 | "noEmitHelpers": true,
8 | "noEmitOnError": true,
9 | "lib": [
10 | "es6",
11 | "dom"
12 | ],
13 | "baseUrl": ".",
14 | "paths": {
15 | "*": [
16 | "./node_modules/tns-core-modules/*",
17 | "./node_modules/*"
18 | ]
19 | }
20 | },
21 | "exclude": [
22 | "node_modules",
23 | "platforms",
24 | "**/*.aot.ts"
25 | ]
26 | }
--------------------------------------------------------------------------------
/demo-angular/lib/iOS/TNSWidgets.framework/Headers/TNSWidgets.h:
--------------------------------------------------------------------------------
1 | //
2 | // TNSWidgets.h
3 | // TNSWidgets
4 | //
5 | // Created by Panayot Cankov on 4/27/16.
6 | // Copyright © 2016 Telerik A D. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for TNSWidgets.
12 | FOUNDATION_EXPORT double TNSWidgetsVersionNumber;
13 |
14 | //! Project version string for TNSWidgets.
15 | FOUNDATION_EXPORT const unsigned char TNSWidgetsVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 | #import "UIImage+TNSBlocks.h"
20 | #import "TNSLabel.h"
21 |
--------------------------------------------------------------------------------
/demo-angular/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es5",
5 | "experimentalDecorators": true,
6 | "emitDecoratorMetadata": true,
7 | "noEmitHelpers": true,
8 | "noEmitOnError": true,
9 | "lib": [
10 | "es6",
11 | "dom",
12 | "es2015.iterable"
13 | ],
14 | "baseUrl": ".",
15 | "paths": {
16 | "*": [
17 | "./node_modules/tns-core-modules/*",
18 | "./node_modules/*"
19 | ]
20 | }
21 | },
22 | "exclude": [
23 | "node_modules",
24 | "platforms",
25 | "**/*.aot.ts"
26 | ]
27 | }
--------------------------------------------------------------------------------
/demo/app/app.css:
--------------------------------------------------------------------------------
1 | /*
2 | In NativeScript, the app.css file is where you place CSS rules that
3 | you would like to apply to your entire application. Check out
4 | http://docs.nativescript.org/ui/styling for a full list of the CSS
5 | selectors and properties you can use to style UI components.
6 |
7 | /*
8 | For example, the following CSS rule changes the font size of all UI
9 | components that have the btn class name.
10 | */
11 | .btn {
12 | font-size: 18;
13 | }
14 |
15 | /*
16 | In many cases you may want to use the NativeScript core theme instead
17 | of writing your own CSS rules. For a full list of class names in the theme
18 | refer to http://docs.nativescript.org/ui/theme.
19 | */
20 | @import 'nativescript-theme-core/css/core.light.css';
21 |
--------------------------------------------------------------------------------
/demo-angular/app/app.css:
--------------------------------------------------------------------------------
1 | /*
2 | In NativeScript, the app.css file is where you place CSS rules that
3 | you would like to apply to your entire application. Check out
4 | http://docs.nativescript.org/ui/styling for a full list of the CSS
5 | selectors and properties you can use to style UI components.
6 |
7 | /*
8 | For example, the following CSS rule changes the font size of all UI
9 | components that have the btn class name.
10 | */
11 | .btn {
12 | font-size: 18;
13 | }
14 |
15 | /*
16 | In many cases you may want to use the NativeScript core theme instead
17 | of writing your own CSS rules. For a full list of class names in the theme
18 | refer to http://docs.nativescript.org/ui/theme.
19 | */
20 | @import 'nativescript-theme-core/css/core.light.css';
21 |
--------------------------------------------------------------------------------
/auth-helper-custom.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import * as tnsOauth from './tns-oauth';
4 | import { AuthHelper } from './auth-helper';
5 | import * as TnsOAuth from './tns-oauth-interfaces';
6 |
7 | export class AuthHelperCustom extends AuthHelper implements TnsOAuth.ITnsAuthHelper {
8 |
9 | constructor(
10 | credentials: TnsOAuth.ITnsOAuthCredentials,
11 | private cookieDomains: Array,
12 | ) {
13 | super();
14 | this.credentials = {} as any;
15 | Object.assign(this.credentials, credentials);
16 | this.credentials.scope = credentials.scope.replace(/ /g, '%20');
17 | }
18 |
19 | public logout(successPage?: string): Promise {
20 | return this._logout(successPage, this.cookieDomains);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tns-oauth-utils.ts:
--------------------------------------------------------------------------------
1 | import { on, resumeEvent, suspendEvent } from 'tns-core-modules/application';
2 |
3 | export function endsWith(str, suffix) {
4 | return str.indexOf(suffix, str.length - suffix.length) !== -1;
5 | }
6 |
7 |
8 | export function nsArrayToJSArray(a) {
9 | var arr = [];
10 | if ("undefined" !== typeof a) {
11 | var count = a.count;
12 | for (var i = 0; i < count; i++) {
13 | arr.push(a.objectAtIndex(i));
14 | }
15 | }
16 | return arr;
17 | }
18 |
19 | export function newUUID(a?,b?){for(b=a='';a++<36;b+=a*51&52?(a^15?8^Math.random()*(a^20?16:4):4).toString(16):'-');return b}
20 |
21 | let appSuspending = false;
22 | on(suspendEvent, () => { appSuspending = true; });
23 | on(resumeEvent, () => { appSuspending = false; });
24 |
25 | export function isAppSuspending(): boolean {
26 | return appSuspending;
27 | }
28 |
--------------------------------------------------------------------------------
/demo/app/README.md:
--------------------------------------------------------------------------------
1 | # NativeScript TypeScript Template
2 |
3 | This template creates a NativeScript app with the NativeScript hello world example,
4 | however, in this template the example is built with TypeScript.
5 |
6 | You can create a new app that uses this template with either the `--template` option.
7 |
8 | ```
9 | tns create my-app-name --template tns-template-hello-world-ts
10 | ```
11 |
12 | Or the `--tsc` shorthand.
13 |
14 | ```
15 | tns create my-app-name --tsc
16 | ```
17 |
18 | > Note: Both commands will create a new NativeScript app that uses the latest version of this template published to [npm] (https://www.npmjs.com/package/tns-template-hello-world-ts).
19 |
20 | If you want to create a new app that uses the source of the template from the `master` branch, you can execute the following:
21 |
22 | ```
23 | tns create my-app-name --template https://github.com/NativeScript/template-hello-world-ts.git#master
24 | ```
25 |
--------------------------------------------------------------------------------
/auth-helper-google.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import * as tnsOauth from './tns-oauth';
4 | import { AuthHelper } from './auth-helper';
5 | import * as TnsOAuth from './tns-oauth-interfaces';
6 |
7 | export class AuthHelperGoogle extends AuthHelper implements TnsOAuth.ITnsAuthHelper {
8 |
9 | constructor(clientId: string, scope: Array) {
10 | super();
11 | var scopeStr = scope.join('%20');
12 | this.credentials = {
13 | authority: 'https://accounts.google.com/o',
14 | authorizeEndpoint: '/oauth2/v2/auth',
15 | tokenEndpoint: '/oauth2/v2.0/token',
16 | clientId: clientId,
17 | redirectUri: 'urn:ietf:wg:oauth:2.0:oob',
18 | scope: scopeStr
19 | };
20 | }
21 |
22 | public logout(successPage?: string): Promise {
23 | let cookieDomains = [".google.com"]; //need to double check this
24 | return this._logout(successPage, cookieDomains);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/typings/querystring.d.ts:
--------------------------------------------------------------------------------
1 | // Type definitions for query-string v3.0.0
2 | // Project: https://github.com/sindresorhus/query-string
3 | // Definitions by: Sam Verschueren
4 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
5 |
6 | declare module "querystring" {
7 | /**
8 | * Parse a query string into an object.
9 | * Leading ? or # are ignored, so you can pass location.search or location.hash directly.
10 | * @param str
11 | */
12 | export function parse(str: string): any;
13 |
14 | /**
15 | * Stringify an object into a query string, sorting the keys.
16 | *
17 | * @param obj
18 | */
19 | export function stringify(obj: any, options?: {strict: boolean}): string;
20 |
21 | /**
22 | * Extract a query string from a URL that can be passed into .parse().
23 | *
24 | * @param str
25 | */
26 | export function extract(str: string): string;
27 | }
--------------------------------------------------------------------------------
/auth-helper-office365.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import * as tnsOauth from './tns-oauth';
4 | import { AuthHelper } from './auth-helper';
5 | import * as TnsOAuth from './tns-oauth-interfaces';
6 |
7 | export class AuthHelperOffice365 extends AuthHelper implements TnsOAuth.ITnsAuthHelper {
8 |
9 | constructor(clientId: string, scope: Array) {
10 | super();
11 | var scopeStr = scope.join('%20');
12 | this.credentials = {
13 | authority: 'https://login.microsoftonline.com/common',
14 | authorizeEndpoint: '/oauth2/v2.0/authorize',
15 | tokenEndpoint: '/oauth2/v2.0/token',
16 | clientId: clientId,
17 | redirectUri: 'urn:ietf:wg:oauth:2.0:oob',
18 | scope: scopeStr
19 | };
20 | }
21 |
22 | public logout(successPage?: string): Promise {
23 | let cookieDomains = ["login.microsoftonline.com", ".live.com"];
24 | return this._logout(successPage, cookieDomains);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/demo/app/main-view-model.ts:
--------------------------------------------------------------------------------
1 | import { Observable } from 'data/observable';
2 | import * as frameModule from "ui/frame";
3 | import * as tnsOAuthModule from 'nativescript-oauth';
4 |
5 | export class HelloWorldModel extends Observable {
6 | public message: string;
7 |
8 | constructor() {
9 | super();
10 | }
11 |
12 | public onTapLogin() {
13 | tnsOAuthModule.ensureValidToken()
14 | .then((token: string) => {
15 | console.log('token: ' + token);
16 | })
17 | .catch((er) => {
18 | console.error('error logging in');
19 | console.dir(er);
20 | });
21 | }
22 |
23 | public onTapLogout() {
24 | tnsOAuthModule.logout()
25 | .then(() => console.log('logged out'))
26 | .catch((er) => {
27 | console.error('error logging out');
28 | console.dir(er);
29 | });
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/demo/typings/querystring.d.ts:
--------------------------------------------------------------------------------
1 | // Type definitions for query-string v3.0.0
2 | // Project: https://github.com/sindresorhus/query-string
3 | // Definitions by: Sam Verschueren
4 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
5 |
6 | declare module "querystring" {
7 | /**
8 | * Parse a query string into an object.
9 | * Leading ? or # are ignored, so you can pass location.search or location.hash directly.
10 | * @param str
11 | */
12 | export function parse(str: string): any;
13 |
14 | /**
15 | * Stringify an object into a query string, sorting the keys.
16 | *
17 | * @param obj
18 | */
19 | export function stringify(obj: any, options?: {strict: boolean}): string;
20 |
21 | /**
22 | * Extract a query string from a URL that can be passed into .parse().
23 | *
24 | * @param str
25 | */
26 | export function extract(str: string): string;
27 | }
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
14 |
15 |
16 |
19 |
20 |
23 |
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
14 |
15 |
16 |
19 |
20 |
23 |
--------------------------------------------------------------------------------
/demo-angular/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from "@angular/core";
2 | import * as tnsOAuthModule from 'nativescript-oauth';
3 | import * as dialogs from 'ui/dialogs';
4 |
5 | @Component({
6 | selector: "my-app",
7 | templateUrl: "app.component.html",
8 | })
9 | export class AppComponent {
10 |
11 | public onTapLogin() {
12 | tnsOAuthModule.ensureValidToken()
13 | .then((token: string) => {
14 | console.log('Token: ' + token);
15 | })
16 | .catch((er) => {
17 | console.error('error logging in');
18 | console.dir(er);
19 | });
20 | }
21 |
22 | public onTapLogout() {
23 | tnsOAuthModule.logout()
24 | .then(() => console.log('logged out'))
25 | .catch((er) => {
26 | console.error('error logging out');
27 | console.dir(er);
28 | });
29 | }
30 |
31 | public authcallback() {
32 | console.log('yay callback');
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/auth-helper-facebook.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import * as tnsOauth from './tns-oauth';
4 | import { AuthHelper } from './auth-helper';
5 | import * as TnsOAuth from './tns-oauth-interfaces';
6 |
7 | export class AuthHelperFacebook extends AuthHelper implements TnsOAuth.ITnsAuthHelper {
8 |
9 | constructor(clientId: string, clientSecret: string, scope: Array) {
10 | super();
11 | var scopeStr = scope.join('%20');
12 | this.credentials = {
13 | authority: 'https://www.facebook.com/dialog',
14 | tokenEndpointBase: 'https://graph.facebook.com',
15 | authorizeEndpoint: '/oauth',
16 | tokenEndpoint: '/v2.3/oauth/access_token',
17 | clientId: clientId,
18 | clientSecret: clientSecret,
19 | redirectUri: 'https://www.facebook.com/connect/login_success.html',
20 | scope: scopeStr
21 | };
22 | }
23 |
24 | public logout(successPage?: string): Promise {
25 | let cookieDomains = [".facebook.com"]; //need to double check this
26 | return this._logout(successPage, cookieDomains);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | nativescript-oauth
4 | Copyright (c) 2016, Alexander Ziskind
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | this software and associated documentation files (the "Software"), to deal in
8 | the Software without restriction, including without limitation the rights to
9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | the Software, and to permit persons to whom the Software is furnished to do so,
11 | subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 |
2 | import * as TnsOAuth from './tns-oauth-interfaces';
3 | export * from './tns-oauth-interfaces';
4 |
5 | export declare var instance: TnsOAuth.ITnsAuthHelper;
6 | export declare function initOffice365(options: TnsOAuth.ITnsOAuthOptionsOffice365): Promise;
7 | export declare function initFacebook(options: TnsOAuth.ITnsOAuthOptionsFacebook): Promise;
8 | export declare function initGoogle(options: TnsOAuth.ITnsOAuthOptionsGoogle): Promise;
9 | export declare function initUaa(options: TnsOAuth.ITnsOAuthOptionsUaa): Promise;
10 | export declare function initLinkedIn(options: TnsOAuth.ITnsOAuthOptionsLinkedIn): Promise;
11 | export declare function initSalesforce(options: TnsOAuth.ITnsOAuthOptionsSalesforce): Promise;
12 | export declare function initCustom(options: TnsOAuth.ITnsOAuthOptionsCustom): Promise;
13 |
14 | export declare function accessToken(): string;
15 | export declare function login(successPage?: string): Promise;
16 | export declare function logout(successPage?: string): Promise;
17 | export declare function accessTokenExpired(): boolean;
18 | export declare function ensureValidToken(): Promise;
19 |
20 |
--------------------------------------------------------------------------------
/demo-angular/lib/iOS/TNSWidgets.framework/Headers/UIImage+TNSBlocks.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+UIImage_Async.h
3 | // TKImageAsync
4 | //
5 | // Created by Panayot Cankov on 4/18/16.
6 | // Copyright © 2016 Telerik A D. All rights reserved.
7 | //
8 |
9 | @interface UIImage (TNSBlocks)
10 |
11 | /**
12 | * Similar to imageNamed: however it runs on a separate queue so the UI thread is not blocked.
13 | * It also draws the UIImage in a small thumb to force decoding potentially avoiding UI hicckups when displayed.
14 | */
15 | + (void) tns_safeDecodeImageNamed: (NSString*) name completion: (void (^) (UIImage*))callback;
16 |
17 | /**
18 | * Same as imageNamed, however calls to this method are sinchronized to be thread safe in iOS8 along with calls to tns_safeImageNamed and tns_safeDecodeImageNamed:completion:
19 | * imageNamed is thread safe in iOS 9 and later so in later versions this methods simply fallbacks to imageNamed:
20 | */
21 | + (UIImage*) tns_safeImageNamed: (NSString*) name;
22 |
23 | + (void) tns_decodeImageWithData: (NSData*) data completion: (void (^) (UIImage*))callback;
24 | + (void) tns_decodeImageWidthContentsOfFile: (NSString*) file completion: (void (^) (UIImage*))callback;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/auth-helper-linkedin.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import * as tnsOauth from './tns-oauth';
4 | import { AuthHelper } from './auth-helper';
5 | import * as TnsOAuth from './tns-oauth-interfaces';
6 |
7 | /**
8 | Contains LinkedIn connection credentials
9 | */
10 | export class AuthHelperLinkedIn extends AuthHelper implements TnsOAuth.ITnsAuthHelper {
11 | //Constructs the the object with specified id, secret and scope
12 | constructor(clientId: string, clientSecret: string, redirectUri: string, scope: Array) {
13 | super();
14 | var scopeStr = scope.join('%20');
15 | this.credentials = {
16 | authority: 'https://www.linkedin.com',
17 | tokenEndpointBase: 'https://www.linkedin.com',
18 | authorizeEndpoint: '/oauth/v2/authorization',
19 | tokenEndpoint: '/oauth/v2/accessToken',
20 | clientId: clientId,
21 | clientSecret: clientSecret,
22 | redirectUri: redirectUri,
23 | scope: scopeStr
24 | };
25 | }
26 | //Gets cookie domains for logging out
27 | public logout(successPage?: string): Promise {
28 | let cookieDomains = [".linkedin.com"];
29 | return this._logout(successPage, cookieDomains);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/demo/app/app.ts:
--------------------------------------------------------------------------------
1 | /*
2 | In NativeScript, the app.ts file is the entry point to your application.
3 | You can use this file to perform app-level initialization, but the primary
4 | purpose of the file is to pass control to the app’s first module.
5 | */
6 |
7 | import "./bundle-config";
8 | import * as app from 'application';
9 | import trace = require("trace");
10 | import * as tnsOAuthModule from 'nativescript-oauth';
11 |
12 |
13 | var o365InitOptions: tnsOAuthModule.ITnsOAuthOptionsOffice365 = {
14 | clientId: '31e1c318-a133-432f-a53b-5122ceab4c12', //client id for application (GUID)
15 | scope: ['Files.ReadWrite', 'User.ReadWrite', 'offline_access']
16 | };
17 |
18 | var facebookInitOptions: tnsOAuthModule.ITnsOAuthOptionsFacebook = {
19 | clientId: '1258457404242046',
20 | clientSecret: 'a24bae9b9e1e6104d9c684c01a96783d',
21 | scope: ['email']
22 | };
23 |
24 | //tnsOAuthModule.initOffice365(o365InitOptions);
25 | tnsOAuthModule.initFacebook(facebookInitOptions);
26 |
27 | trace.setCategories(trace.categories.All);
28 | trace.enable();
29 |
30 | app.start({ moduleName: 'main-page' });
31 |
32 | /*
33 | Do not place any code after the application has been started as it will not
34 | be executed on iOS.
35 | */
36 |
--------------------------------------------------------------------------------
/auth-helper-uaa.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import * as tnsOauth from './tns-oauth';
4 | import { AuthHelper } from './auth-helper';
5 | import * as TnsOAuth from './tns-oauth-interfaces';
6 |
7 | export class AuthHelperUaa extends AuthHelper implements TnsOAuth.ITnsAuthHelper {
8 |
9 | private _cookieDomains: string[];
10 |
11 | constructor(authority: string, redirectUri: string, clientId: string, clientSecret: string, scope: Array, cookieDomains: Array, basicAuthHeader: string) {
12 | super();
13 | var scopeStr = scope.join('%20');
14 |
15 | let uaaCreds: TnsOAuth.ITnsOAuthCredentialsUaa = {
16 | authority: authority,
17 | authorizeEndpoint: '/oauth/authorize',
18 | tokenEndpoint: '/oauth/token',
19 | clientId: clientId,
20 | clientSecret: clientSecret,
21 | redirectUri: redirectUri,
22 | scope: scopeStr,
23 | basicAuthHeader: basicAuthHeader
24 | };
25 |
26 | this.credentials = uaaCreds;
27 | this._cookieDomains = cookieDomains;
28 | }
29 |
30 | public logout(successPage?: string): Promise {
31 | let cookieDomains = this._cookieDomains;
32 | return this._logout(successPage, cookieDomains);
33 | }
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/demo-angular/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "NativeScript Application",
3 | "license": "SEE LICENSE IN ",
4 | "readme": "NativeScript Application",
5 | "repository": "",
6 | "nativescript": {
7 | "id": "org.nativescript.demoangular",
8 | "tns-ios": {
9 | "version": "3.4.1"
10 | },
11 | "tns-android": {
12 | "version": "3.4.2"
13 | }
14 | },
15 | "dependencies": {
16 | "@angular/animations": "~4.4.1",
17 | "@angular/common": "~4.4.1",
18 | "@angular/compiler": "~4.4.1",
19 | "@angular/core": "~4.4.1",
20 | "@angular/forms": "~4.4.1",
21 | "@angular/http": "~4.4.1",
22 | "@angular/platform-browser": "~4.4.1",
23 | "@angular/router": "~4.4.1",
24 | "nativescript-angular": "~4.4.0",
25 | "nativescript-oauth": "../",
26 | "nativescript-theme-core": "~1.0.2",
27 | "reflect-metadata": "~0.1.8",
28 | "rxjs": "~5.4.2",
29 | "tns-core-modules": "3.4.1",
30 | "zone.js": "~0.8.2"
31 | },
32 | "devDependencies": {
33 | "babel-traverse": "6.26.0",
34 | "babel-types": "6.26.0",
35 | "babylon": "6.18.0",
36 | "lazy": "1.0.11",
37 | "nativescript-dev-typescript": "~0.5.0",
38 | "typescript": "2.3.4"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/demo/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Launch on iOS",
6 | "type": "nativescript",
7 | "request": "launch",
8 | "platform": "ios",
9 | "appRoot": "${workspaceRoot}",
10 | "sourceMaps": true,
11 | "watch": true
12 | },
13 | {
14 | "name": "Attach on iOS",
15 | "type": "nativescript",
16 | "request": "attach",
17 | "platform": "ios",
18 | "appRoot": "${workspaceRoot}",
19 | "sourceMaps": true,
20 | "watch": false
21 | },
22 | {
23 | "name": "Launch on Android",
24 | "type": "nativescript",
25 | "request": "launch",
26 | "platform": "android",
27 | "appRoot": "${workspaceRoot}",
28 | "sourceMaps": true,
29 | "watch": true
30 | },
31 | {
32 | "name": "Attach on Android",
33 | "type": "nativescript",
34 | "request": "attach",
35 | "platform": "android",
36 | "appRoot": "${workspaceRoot}",
37 | "sourceMaps": true,
38 | "watch": false
39 | }
40 | ]
41 | }
--------------------------------------------------------------------------------
/demo/app/main-page.ts:
--------------------------------------------------------------------------------
1 | /*
2 | In NativeScript, a file with the same name as an XML file is known as
3 | a code-behind file. The code-behind is a great place to place your view
4 | logic, and to set up your page’s data binding.
5 | */
6 |
7 | import { EventData } from 'data/observable';
8 | import { Page } from 'ui/page';
9 | import { HelloWorldModel } from './main-view-model';
10 |
11 | // Event handler for Page "navigatingTo" event attached in main-page.xml
12 | export function navigatingTo(args: EventData) {
13 | /*
14 | This gets a reference this page’s UI component. You can
15 | view the API reference of the Page to see what’s available at
16 | https://docs.nativescript.org/api-reference/classes/_ui_page_.page.html
17 | */
18 | let page = args.object;
19 |
20 | /*
21 | A page’s bindingContext is an object that should be used to perform
22 | data binding between XML markup and TypeScript code. Properties
23 | on the bindingContext can be accessed using the {{ }} syntax in XML.
24 | In this example, the {{ message }} and {{ onTap }} bindings are resolved
25 | against the object returned by createViewModel().
26 |
27 | You can learn more about data binding in NativeScript at
28 | https://docs.nativescript.org/core-concepts/data-binding.
29 | */
30 | page.bindingContext = new HelloWorldModel();
31 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "noImplicitAny": false,
6 | "removeComments": true,
7 | "experimentalDecorators": true,
8 | "noLib": false,
9 | "preserveConstEnums": true,
10 | "declaration": false,
11 | "noEmitHelpers": true,
12 | "suppressImplicitAnyIndexErrors": true,
13 | "lib": [
14 | "es6",
15 | "dom"
16 | ],
17 | "baseUrl": ".",
18 | "paths": {
19 | "*": [
20 | "./node_modules/tns-core-modules/*",
21 | "./node_modules/*"
22 | ]
23 | }
24 | },
25 | "files": [
26 | "auth-helper.ts",
27 | "auth-helper-facebook.ts",
28 | "auth-helper-google.ts",
29 | "auth-helper-office365.ts",
30 | "auth-helper-uaa.ts",
31 | "auth-helper-linkedin.ts",
32 | "index.ts",
33 | "tns-oauth.ts",
34 | "tns-oauth-page-provider.ts",
35 | "tns-oauth-token-cache.ts",
36 | "tns-oauth-utils.ts",
37 | "tns-oauth-webview-helper.ios.ts",
38 | "tns-oauth-webview-helper.android.ts",
39 | "./typings/querystring.d.ts",
40 | "./typings/url.d.ts"
41 | ],
42 | "compileOnSave": false,
43 | "exclude": [
44 | "node_modules",
45 | "platforms"
46 | ]
47 | }
--------------------------------------------------------------------------------
/tns-oauth-token-cache.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import * as TnsOAuth from './tns-oauth-interfaces';
4 |
5 | import * as applicationSettingsModule from "application-settings";
6 |
7 | const TNS_OAUTH_KEY = "TNS_OAUTH_KEY";
8 |
9 | export class TnsOAuthTokenCache {
10 |
11 | public static hasToken(): boolean {
12 | return applicationSettingsModule.hasKey(TNS_OAUTH_KEY);
13 | }
14 |
15 | public static getToken(): TnsOAuth.ITnsOAuthTokenResult {
16 | if (applicationSettingsModule.hasKey(TNS_OAUTH_KEY)) {
17 | let trStr = applicationSettingsModule.getString(TNS_OAUTH_KEY);
18 | let tr = JSON.parse(trStr);
19 |
20 | if (tr.accessTokenExpiration) {
21 | tr.accessTokenExpiration = new Date(tr.accessTokenExpiration.toString());
22 | }
23 |
24 | if (tr.refreshTokenExpiration) {
25 | tr.refreshTokenExpiration = new Date(tr.refreshTokenExpiration.toString());
26 | }
27 |
28 | return tr;
29 | }
30 | else return null;
31 | }
32 |
33 | public static setToken(token: TnsOAuth.ITnsOAuthTokenResult) {
34 | applicationSettingsModule.setString(TNS_OAUTH_KEY, JSON.stringify(token));
35 | }
36 |
37 | public static removeToken() {
38 | applicationSettingsModule.remove(TNS_OAUTH_KEY);
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/tns-oauth-page-provider.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { Page } from 'ui/page';
4 | import { GridLayout } from 'ui/layouts/grid-layout';
5 | import { StackLayout } from 'ui/layouts/stack-layout';
6 | import { isAndroid } from 'tns-core-modules/platform';
7 | import { TnsOauthWebView } from './tns-oauth-webview';
8 | //import { TnsOAuthWebViewDelegateImpl } from './tns-oauth-webview';
9 | import { TnsOAuthWebViewHelper } from './tns-oauth-webview-helper';
10 |
11 |
12 | export class TnsOAuthPageProvider {
13 | private _checkCodeIntercept: (WebView, error?, url?) => boolean;
14 | private _cancelEventHandler: (error?) => void;
15 | private _authUrl: string;
16 |
17 | constructor(checkCodeIntercept, authUrl, cancelEventHandler) {
18 | this._checkCodeIntercept = checkCodeIntercept;
19 | this._cancelEventHandler = cancelEventHandler;
20 | this._authUrl = authUrl;
21 | }
22 |
23 | public loginPageFunc() {
24 | let wv = new TnsOauthWebView(this._cancelEventHandler);
25 |
26 | TnsOAuthWebViewHelper.initWithWebViewAndIntercept(wv, this._checkCodeIntercept);
27 |
28 | let grid = new GridLayout();
29 | grid.addChild(wv);
30 |
31 | let stack = new StackLayout();
32 | stack.addChild(grid);
33 |
34 | let page = new Page();
35 | page.content = stack;
36 |
37 | if (isAndroid) {
38 | page.actionBarHidden = true;
39 | }
40 |
41 | wv.src = this._authUrl;
42 |
43 | return page;
44 | };
45 | }
46 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
27 |
28 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
27 |
28 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/demo/app/main-page.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
12 |
13 |
14 |
15 |
16 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/demo-angular/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": false,
3 | "nativescript": {
4 | "id": "org.nativescript.helloworldng"
5 | },
6 | "name": "tns-template-hello-world-ng",
7 | "main": "main.js",
8 | "version": "2.4.3",
9 | "author": "Telerik ",
10 | "description": "Nativescript Angular Hello World template",
11 | "license": "BSD",
12 | "keywords": [
13 | "telerik",
14 | "mobile",
15 | "angular",
16 | "nativescript",
17 | "{N}",
18 | "tns",
19 | "appbuilder",
20 | "template"
21 | ],
22 | "repository": {
23 | "type": "git",
24 | "url": "git://github.com/NativeScript/template-hello-world-ng"
25 | },
26 | "homepage": "https://github.com/NativeScript/template-hello-world-ng",
27 | "android": {
28 | "v8Flags": "--expose_gc"
29 | },
30 | "dependencies": {
31 | "nativescript-theme-core": "^0.2.1",
32 | "nativescript-angular": "1.2.0",
33 | "@angular/core": "2.2.1",
34 | "@angular/common": "2.2.1",
35 | "@angular/compiler": "2.2.1",
36 | "@angular/http": "2.2.1",
37 | "@angular/platform-browser": "2.2.1",
38 | "@angular/platform-browser-dynamic": "2.2.1",
39 | "@angular/forms": "2.2.1",
40 | "@angular/router": "3.2.1",
41 | "rxjs": "5.0.0-beta.12",
42 | "reflect-metadata": "~0.1.8"
43 | },
44 | "devDependencies": {
45 | "zone.js": "~0.6.21",
46 | "typescript": "~2.0.10",
47 | "nativescript-dev-typescript": "^0.3.2",
48 | "nativescript-dev-android-snapshot": "^0.*.*"
49 | }
50 | }
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiresFullScreen
28 |
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiresFullScreen
28 |
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/tns-oauth-webview.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { WebView } from 'ui/web-view';
4 | import { android } from 'tns-core-modules/application';
5 | import { isAndroid } from 'tns-core-modules/platform';
6 |
7 | import { isAppSuspending } from './tns-oauth-utils';
8 |
9 | // https://developer.android.com/reference/android/view/WindowManager.LayoutParams#soft_input_adjust_resize
10 | const SOFT_INPUT_ADJUST_RESIZE = 16;
11 |
12 | export class TnsOauthWebView extends WebView {
13 | private originalSoftInputMode: number;
14 |
15 | constructor(
16 | private _cancelEventHandler: (error?) => void
17 | ) {
18 | super();
19 | }
20 |
21 | public onLoaded() {
22 | super.onLoaded();
23 | if (isAndroid) {
24 | this.android.getSettings().setBuiltInZoomControls(false);
25 | this.setAndroidSoftInputModeToResize();
26 | }
27 | }
28 |
29 | public onUnloaded() {
30 | super.onUnloaded();
31 | if (!isAppSuspending()) {
32 | this._cancelEventHandler("User cancelled.");
33 | if (isAndroid) {
34 | this.restoreAndroidSoftInputMode();
35 | }
36 | }
37 | }
38 |
39 | private setAndroidSoftInputModeToResize(): void {
40 | const window = android.foregroundActivity.getWindow();
41 | this.originalSoftInputMode = window.getAttributes().softInputMode;
42 | window.setSoftInputMode(SOFT_INPUT_ADJUST_RESIZE);
43 | }
44 |
45 | private restoreAndroidSoftInputMode(): void {
46 | const window = android.foregroundActivity.getWindow();
47 | window.setSoftInputMode(this.originalSoftInputMode);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/demo-angular/app/main.ts:
--------------------------------------------------------------------------------
1 | // this import should be first in order to load some required settings (like globals and reflect-metadata)
2 | import { platformNativeScriptDynamic } from "nativescript-angular/platform";
3 |
4 | import { AppModule } from "./app.module";
5 |
6 | import * as tnsOAuthModule from 'nativescript-oauth';
7 |
8 |
9 |
10 | var o365InitOptions: tnsOAuthModule.ITnsOAuthOptionsOffice365 = {
11 | clientId: '67e1c318-a133-432f-a53b-5122ce111111', //client id for application (GUID)
12 | scope: ['Files.ReadWrite', 'User.ReadWrite', 'offline_access']
13 | };
14 | //tnsOAuthModule.initOffice365(o365InitOptions);
15 |
16 |
17 | var facebookInitOptions: tnsOAuthModule.ITnsOAuthOptionsFacebook = {
18 | clientId: '691208554415645',
19 | clientSecret: 'd8725ac416fa1bb1917ccffd1670e3c6',
20 | scope: ['email']
21 | };
22 | tnsOAuthModule.initFacebook(facebookInitOptions);
23 |
24 |
25 |
26 | // let uaaInitOptions: tnsOAuthModule.ITnsOAuthOptionsUaa = {
27 | // authority: '',
28 | // redirectUri: '',
29 | // clientId: '',
30 | // clientSecret: '',
31 | // scope: ['uaa.resource', 'uaa.user'],
32 | // cookieDomains: [''],
33 | // basicAuthHeader: ''
34 |
35 | //};
36 |
37 | //tnsOAuthModule.initUaa(uaaInitOptions);
38 |
39 | /*
40 | var linkedInInitOptions: tnsOAuthModule.ITnsOAuthOptionsLinkedIn = {
41 | clientId: '77jymt11111111', // Add your client id
42 | clientSecret: 'ibVkPD6m11111111', // Add your client secret
43 | scope: ['r_basicprofile'], // Do not include if you want the default scopes
44 | redirectUri: 'https://localhost' // Configure your redirect URL here it must be and https or it will prevent iOS from working.
45 | };
46 | tnsOAuthModule.initLinkedIn(linkedInInitOptions);
47 | */
48 |
49 | platformNativeScriptDynamic().bootstrapModule(AppModule);
50 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/Android/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
18 |
19 |
21 |
22 |
23 |
31 |
32 |
34 |
35 |
36 |
42 |
43 |
45 |
46 |
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/Android/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
18 |
19 |
21 |
22 |
23 |
31 |
32 |
34 |
35 |
36 |
42 |
43 |
45 |
46 |
--------------------------------------------------------------------------------
/demo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "NativeScript Application",
3 | "license": "SEE LICENSE IN ",
4 | "readme": "NativeScript Application",
5 | "repository": "",
6 | "nativescript": {
7 | "id": "org.nativescript.demo",
8 | "tns-ios": {
9 | "version": "3.0.0"
10 | },
11 | "tns-android": {
12 | "version": "3.0.0"
13 | }
14 | },
15 | "scripts": {
16 | "build.plugin": "cd .. && npm run build",
17 | "demo.ios": "npm i && npm run build.plugin && tns run ios",
18 | "demo.android": "npm i && npm run build.plugin && tns run android",
19 | "ns-bundle": "ns-bundle",
20 | "publish-ios-bundle": "npm run ns-bundle --ios --publish-app",
21 | "generate-android-snapshot": "generate-android-snapshot --targetArchs arm,arm64,ia32 --install",
22 | "start-android-bundle": "npm run ns-bundle --android --run-app",
23 | "start-ios-bundle": "npm run ns-bundle --ios --run-app",
24 | "build-android-bundle": "npm run ns-bundle --android --build-app",
25 | "build-ios-bundle": "npm run ns-bundle --ios --build-app"
26 | },
27 | "dependencies": {
28 | "nativescript-oauth": "../",
29 | "nativescript-theme-core": "~1.0.2",
30 | "tns-core-modules": "~3.0.0"
31 | },
32 | "devDependencies": {
33 | "babel-traverse": "6.24.1",
34 | "babel-types": "6.24.1",
35 | "babylon": "6.17.0",
36 | "lazy": "1.0.11",
37 | "nativescript-dev-android-snapshot": "^0.*.*",
38 | "nativescript-dev-typescript": "~0.4.0",
39 | "typescript": "~2.2.1",
40 | "nativescript-dev-webpack": "0.7.3",
41 | "webpack": "~3.2.0",
42 | "webpack-bundle-analyzer": "^2.8.2",
43 | "webpack-sources": "~1.0.1",
44 | "copy-webpack-plugin": "~4.0.1",
45 | "raw-loader": "~0.5.1",
46 | "nativescript-css-loader": "~0.26.0",
47 | "resolve-url-loader": "~2.1.0",
48 | "extract-text-webpack-plugin": "~3.0.0",
49 | "awesome-typescript-loader": "~3.1.3"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nativescript-oauth",
3 | "version": "2.1.8",
4 | "description": "OAuth 2 login for NativeScript.",
5 | "main": "index.js",
6 | "nativescript": {},
7 | "scripts": {
8 | "build": "npm i && tsc",
9 | "demo.android": "npm run preparedemo && cd demo-angular && tns run android",
10 | "preparedemo": "npm run build && cd demo-angular && tns plugin remove nativescript-oauth && tns plugin add .. && tns install",
11 | "setup": "cd demo-angular && npm install && cd .. && npm run build && cd demo-angular && tns plugin add .. && cd .."
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/alexziskind1/nativescript-oauth.git"
16 | },
17 | "typescript": {
18 | "definition": "index.d.ts"
19 | },
20 | "typings": "index",
21 | "keywords": [
22 | "NativeScript",
23 | "JavaScript",
24 | "TypeScript",
25 | "Office365",
26 | "Facebook",
27 | "Azure AD",
28 | "iOS",
29 | "Android"
30 | ],
31 | "author": {
32 | "name": "Alexander Ziskind",
33 | "email": "alex@nuvious.com",
34 | "url": "http://www.nuvious.com/blog"
35 | },
36 | "contributors": [
37 | {
38 | "name": "Kevin Primm",
39 | "email": "kfprimm@gmail.com",
40 | "url": "https://github.com/kfprimm"
41 | },
42 | {
43 | "name": "Toma Nikolov",
44 | "url": "https://github.com/TomaNikolov"
45 | }
46 | ],
47 | "bugs": {
48 | "url": "https://github.com/alexziskind1/nativescript-oauth/issues"
49 | },
50 | "license": {
51 | "type": "MIT",
52 | "url": "https://github.com/alexziskind1/nativescript-oauth/blob/master/LICENSE"
53 | },
54 | "homepage": "https://github.com/alexziskind1/nativescript-oauth",
55 | "readmeFilename": "README.md",
56 | "dependencies": {
57 | "querystring": "^0.2.0",
58 | "url": "^0.11.0"
59 | },
60 | "devDependencies": {
61 | "nativescript-dev-typescript": "^0.7.1",
62 | "tns-core-modules": "4.1.0",
63 | "typescript": "^2.7.2",
64 | "tns-platform-declarations": "4.1.0"
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/tns-oauth-interfaces.d.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | export interface ITnsAuthHelper {
5 | credentials: ITnsOAuthCredentials;
6 | tokenResult: ITnsOAuthTokenResult;
7 | login: (successPage?: string) => Promise;
8 | logout: (successPage?: string) => Promise;
9 | refreshToken: () => Promise;
10 | accessTokenExpired: () => boolean;
11 | refreshTokenExpired: () => boolean;
12 | }
13 |
14 | export interface ITnsOAuthCredentials {
15 | authority: string;
16 | tokenEndpointBase?: string;
17 | authorizeEndpoint: string;
18 | tokenEndpoint: string;
19 | revokeEndpoint?: string;
20 | clientId: string;
21 | clientSecret?: string;
22 | redirectUri: string;
23 | responseType?: string;
24 | scope: string;
25 | }
26 |
27 | export interface ITnsOAuthCredentialsUaa extends ITnsOAuthCredentials {
28 | basicAuthHeader: string;
29 | }
30 |
31 | export interface ITnsOAuthTokenResult {
32 | accessToken: string;
33 | refreshToken: string;
34 | accessTokenExpiration: Date;
35 | refreshTokenExpiration: Date;
36 | }
37 |
38 | export interface ITnsOAuthOptions {
39 | clientId: string;
40 | scope: string[];
41 | }
42 |
43 | export interface ITnsOAuthOptionsOffice365 extends ITnsOAuthOptions {
44 | }
45 |
46 | export interface ITnsOAuthOptionsFacebook extends ITnsOAuthOptions {
47 | clientSecret: string;
48 | }
49 |
50 | export interface ITnsOAuthOptionsGoogle extends ITnsOAuthOptions {
51 | }
52 |
53 | export interface ITnsOAuthOptionsUaa extends ITnsOAuthOptions {
54 | authority: string;
55 | redirectUri: string;
56 | clientSecret: string;
57 | cookieDomains: string[];
58 | basicAuthHeader: string;
59 | }
60 |
61 | export interface ITnsOAuthOptionsLinkedIn extends ITnsOAuthOptions {
62 | clientSecret: string;
63 | redirectUri: string;
64 | }
65 |
66 | export interface ITnsOAuthOptionsSalesforce extends ITnsOAuthOptions {
67 | authority: string;
68 | redirectUri: string;
69 | responseType: string;
70 | }
71 |
72 | export interface ITnsOAuthOptionsCustom {
73 | credentials: ITnsOAuthCredentials;
74 | cookieDomains: Array;
75 | }
76 |
--------------------------------------------------------------------------------
/auth-helper-salesforce.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import * as URL from 'url';
4 | import * as http from 'http';
5 | import * as querystring from 'querystring';
6 | import * as tnsOauth from './tns-oauth';
7 | import { AuthHelper } from './auth-helper';
8 | import * as TnsOAuth from './tns-oauth-interfaces';
9 |
10 | /**
11 | Contains Salesforce connection credentials
12 | */
13 | export class AuthHelperSalesforce extends AuthHelper implements TnsOAuth.ITnsAuthHelper {
14 | //Constructs the the object with specified id, secret and scope
15 | constructor(
16 | authority: string,
17 | clientId: string,
18 | redirectUri: string,
19 | responseType: string,
20 | scope: Array,
21 | clientSecret?: string,
22 | ) {
23 | super();
24 | var scopeStr = scope.join('%20');
25 | this.credentials = {
26 | authority: authority,
27 | authorizeEndpoint: '/services/oauth2/authorize',
28 | tokenEndpoint: '/services/oauth2/token',
29 | revokeEndpoint: '/services/oauth2/revoke',
30 | clientId: clientId,
31 | clientSecret: clientSecret,
32 | redirectUri: redirectUri,
33 | responseType: responseType,
34 | scope: scopeStr
35 | };
36 | }
37 | //Gets cookie domains for logging out
38 | public logout(): Promise {
39 | return new Promise((resolve, reject) => {
40 | try {
41 | // call revoke token here
42 | var revoke_url = this.credentials.authority + this.credentials.revokeEndpoint;
43 | var post_headers = {
44 | // XXX: Not sure if this header is needed
45 | //'Host': URL.parse(revoke_url, true),
46 | 'Content-Type': 'application/x-www-form-urlencoded'
47 | };
48 | var post_body = querystring.stringify({token: this.tokenResult.refreshToken});
49 |
50 | http.request({
51 | url: revoke_url,
52 | method: 'POST',
53 | headers: post_headers,
54 | content: post_body
55 | }).then((response: http.HttpResponse) => {
56 | if (response.statusCode != 200) {
57 | throw new Error(`Failed logout with status ${ response.statusCode }.`);
58 | }
59 | });
60 | this.tokenResult = null;
61 | resolve();
62 | } catch (er) {
63 | reject(er);
64 | }
65 | });
66 |
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/auth-helper.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import * as tnsOauth from './tns-oauth';
4 | import * as TnsOAuth from './tns-oauth-interfaces';
5 |
6 | export class AuthHelper {
7 | public credentials: TnsOAuth.ITnsOAuthCredentials;
8 | public tokenResult: TnsOAuth.ITnsOAuthTokenResult;
9 |
10 | constructor() {
11 | this.tokenResult = tnsOauth.getTokenFromCache();
12 | }
13 |
14 | public login(successPage?: string): Promise {
15 | return new Promise((resolve, reject) => {
16 | tnsOauth.loginViaAuthorizationCodeFlow(this.credentials, successPage)
17 | .then((response: TnsOAuth.ITnsOAuthTokenResult) => {
18 | this.tokenResult = response;
19 | resolve(response.accessToken);
20 | })
21 | .catch((er) => {
22 | reject(er);
23 | });
24 | });
25 | }
26 |
27 | public refreshToken(): Promise {
28 | return new Promise((resolve, reject) => {
29 | tnsOauth.refreshToken(this.credentials)
30 | .then((response: TnsOAuth.ITnsOAuthTokenResult) => {
31 | this.tokenResult = response;
32 | resolve(response.accessToken);
33 | })
34 | .catch((er) => {
35 | reject(er);
36 | });
37 | });
38 | }
39 |
40 | public _logout(successPage?: string, cookieDomains?: string[]): Promise {
41 | return new Promise((resolve, reject) => {
42 | try {
43 | tnsOauth.logout(cookieDomains, successPage);
44 | this.tokenResult = null;
45 | resolve();
46 | } catch (er) {
47 | reject(er);
48 | }
49 | });
50 | }
51 |
52 | public accessTokenExpired(): boolean {
53 | if (this.tokenResult && this.tokenResult.accessTokenExpiration) {
54 | return this.tokenResult.accessTokenExpiration < (new Date());
55 | } else {
56 | return true;
57 | }
58 | }
59 |
60 | public refreshTokenExpired(): boolean {
61 | if (this.tokenResult && this.tokenResult.refreshTokenExpiration) {
62 | if (this.tokenResult.refreshTokenExpiration) {
63 | return this.tokenResult.refreshTokenExpiration < (new Date());
64 | } else {
65 | return false;
66 | }
67 | } else {
68 | return true;
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/tns-oauth-webview-helper.ios.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { WebView } from 'ui/web-view';
4 |
5 | export class TnsOAuthWebViewHelper extends NSObject implements WKNavigationDelegate {
6 | public static ObjCProtocols = [WKNavigationDelegate];
7 |
8 | private _owner: WeakRef;
9 | private _origDelegate: any; //UIWebViewDelegateImpl
10 | private _checkCodeIntercept: (WebView, error?, url?) => boolean;
11 |
12 | constructor() {
13 | super();
14 | }
15 |
16 | public static initWithWebViewAndIntercept(wv: WebView, checkCodeIntercept) {
17 | (wv)._delegate = TnsOAuthWebViewHelper.initWithOwner(new WeakRef(wv), checkCodeIntercept);
18 | }
19 |
20 | private static initWithOwner(owner: WeakRef, checkCodeIntercept): TnsOAuthWebViewHelper {
21 | let delegate = new TnsOAuthWebViewHelper();
22 | delegate._owner = owner;
23 | delegate._origDelegate = (owner.get())._delegate;
24 | delegate._checkCodeIntercept = checkCodeIntercept;
25 | return delegate;
26 | }
27 |
28 | public webViewShouldStartLoadWithRequestNavigationType(webView: WKWebView, request: NSURLRequest, navigationType: number) {
29 | return this._origDelegate.webViewShouldStartLoadWithRequestNavigationType(webView, request, navigationType);
30 | }
31 |
32 | public webViewDidStartLoad(webView: WKWebView) {
33 | this._origDelegate.webViewDidStartLoad(webView);
34 | }
35 |
36 | public webViewDidFinishLoad(webView: WKWebView) {
37 | this._checkCodeIntercept(webView, null);
38 | this._origDelegate.webViewDidFinishLoad(webView);
39 | }
40 |
41 | public webViewDidFailLoadWithError(webView: WKWebView, error: NSError) {
42 | this._checkCodeIntercept(webView, error);
43 | this._origDelegate.webViewDidFailLoadWithError(webView, error);
44 | }
45 |
46 |
47 | public webViewDecidePolicyForNavigationActionDecisionHandler(webView, navigationAction, decisionHandler) {
48 | //decisionHandler(WKNavigationActionPolicy.Allow);
49 | this._checkCodeIntercept(webView, null);
50 | this._origDelegate.webViewDecidePolicyForNavigationActionDecisionHandler(webView, navigationAction, decisionHandler);
51 | }
52 |
53 | public webViewDidStartProvisionalNavigation(webView, navigation) {
54 | this._origDelegate.webViewDidStartProvisionalNavigation(webView, navigation);
55 | }
56 |
57 | public webViewDidFinishNavigation(webView, navigation) {
58 | this._checkCodeIntercept(webView, null);
59 | this._origDelegate.webViewDidFinishNavigation(webView, navigation);
60 | }
61 |
62 | public webViewDidFailNavigationWithError(webView, navigation, error) {
63 | this._checkCodeIntercept(webView, error);
64 | this._origDelegate.webViewDidFailNavigationWithError(webView, navigation, error);
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "29x29",
5 | "idiom" : "iphone",
6 | "filename" : "icon-29.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "29x29",
11 | "idiom" : "iphone",
12 | "filename" : "icon-29@2x.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "icon-29@3x.png",
19 | "scale" : "3x"
20 | },
21 | {
22 | "size" : "40x40",
23 | "idiom" : "iphone",
24 | "filename" : "icon-40@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "40x40",
29 | "idiom" : "iphone",
30 | "filename" : "icon-40@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "57x57",
35 | "idiom" : "iphone",
36 | "filename" : "icon-57.png",
37 | "scale" : "1x"
38 | },
39 | {
40 | "size" : "57x57",
41 | "idiom" : "iphone",
42 | "filename" : "icon-57@2x.png",
43 | "scale" : "2x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "icon-60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "icon-60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "29x29",
59 | "idiom" : "ipad",
60 | "filename" : "icon-29.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "29x29",
65 | "idiom" : "ipad",
66 | "filename" : "icon-29@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "40x40",
71 | "idiom" : "ipad",
72 | "filename" : "icon-40.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "40x40",
77 | "idiom" : "ipad",
78 | "filename" : "icon-40@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "50x50",
83 | "idiom" : "ipad",
84 | "filename" : "icon-50.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "50x50",
89 | "idiom" : "ipad",
90 | "filename" : "icon-50@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "72x72",
95 | "idiom" : "ipad",
96 | "filename" : "icon-72.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "72x72",
101 | "idiom" : "ipad",
102 | "filename" : "icon-72@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "76x76",
107 | "idiom" : "ipad",
108 | "filename" : "icon-76.png",
109 | "scale" : "1x"
110 | },
111 | {
112 | "size" : "76x76",
113 | "idiom" : "ipad",
114 | "filename" : "icon-76@2x.png",
115 | "scale" : "2x"
116 | },
117 | {
118 | "size" : "83.5x83.5",
119 | "idiom" : "ipad",
120 | "filename" : "icon-83.5@2x.png",
121 | "scale" : "2x"
122 | }
123 | ],
124 | "info" : {
125 | "version" : 1,
126 | "author" : "xcode"
127 | }
128 | }
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "29x29",
5 | "idiom" : "iphone",
6 | "filename" : "icon-29.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "29x29",
11 | "idiom" : "iphone",
12 | "filename" : "icon-29@2x.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "icon-29@3x.png",
19 | "scale" : "3x"
20 | },
21 | {
22 | "size" : "40x40",
23 | "idiom" : "iphone",
24 | "filename" : "icon-40@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "40x40",
29 | "idiom" : "iphone",
30 | "filename" : "icon-40@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "57x57",
35 | "idiom" : "iphone",
36 | "filename" : "icon-57.png",
37 | "scale" : "1x"
38 | },
39 | {
40 | "size" : "57x57",
41 | "idiom" : "iphone",
42 | "filename" : "icon-57@2x.png",
43 | "scale" : "2x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "icon-60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "icon-60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "29x29",
59 | "idiom" : "ipad",
60 | "filename" : "icon-29.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "29x29",
65 | "idiom" : "ipad",
66 | "filename" : "icon-29@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "40x40",
71 | "idiom" : "ipad",
72 | "filename" : "icon-40.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "40x40",
77 | "idiom" : "ipad",
78 | "filename" : "icon-40@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "50x50",
83 | "idiom" : "ipad",
84 | "filename" : "icon-50.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "50x50",
89 | "idiom" : "ipad",
90 | "filename" : "icon-50@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "72x72",
95 | "idiom" : "ipad",
96 | "filename" : "icon-72.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "72x72",
101 | "idiom" : "ipad",
102 | "filename" : "icon-72@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "76x76",
107 | "idiom" : "ipad",
108 | "filename" : "icon-76.png",
109 | "scale" : "1x"
110 | },
111 | {
112 | "size" : "76x76",
113 | "idiom" : "ipad",
114 | "filename" : "icon-76@2x.png",
115 | "scale" : "2x"
116 | },
117 | {
118 | "size" : "83.5x83.5",
119 | "idiom" : "ipad",
120 | "filename" : "icon-83.5@2x.png",
121 | "scale" : "2x"
122 | }
123 | ],
124 | "info" : {
125 | "version" : 1,
126 | "author" : "xcode"
127 | }
128 | }
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "extent" : "full-screen",
5 | "idiom" : "iphone",
6 | "subtype" : "736h",
7 | "filename" : "Default-736h@3x.png",
8 | "minimum-system-version" : "8.0",
9 | "orientation" : "portrait",
10 | "scale" : "3x"
11 | },
12 | {
13 | "extent" : "full-screen",
14 | "idiom" : "iphone",
15 | "subtype" : "736h",
16 | "filename" : "Default-Landscape@3x.png",
17 | "minimum-system-version" : "8.0",
18 | "orientation" : "landscape",
19 | "scale" : "3x"
20 | },
21 | {
22 | "extent" : "full-screen",
23 | "idiom" : "iphone",
24 | "subtype" : "667h",
25 | "filename" : "Default-667h@2x.png",
26 | "minimum-system-version" : "8.0",
27 | "orientation" : "portrait",
28 | "scale" : "2x"
29 | },
30 | {
31 | "orientation" : "portrait",
32 | "idiom" : "iphone",
33 | "filename" : "Default@2x.png",
34 | "extent" : "full-screen",
35 | "minimum-system-version" : "7.0",
36 | "scale" : "2x"
37 | },
38 | {
39 | "extent" : "full-screen",
40 | "idiom" : "iphone",
41 | "subtype" : "retina4",
42 | "filename" : "Default-568h@2x.png",
43 | "minimum-system-version" : "7.0",
44 | "orientation" : "portrait",
45 | "scale" : "2x"
46 | },
47 | {
48 | "orientation" : "portrait",
49 | "idiom" : "ipad",
50 | "filename" : "Default-Portrait.png",
51 | "extent" : "full-screen",
52 | "minimum-system-version" : "7.0",
53 | "scale" : "1x"
54 | },
55 | {
56 | "orientation" : "landscape",
57 | "idiom" : "ipad",
58 | "filename" : "Default-Landscape.png",
59 | "extent" : "full-screen",
60 | "minimum-system-version" : "7.0",
61 | "scale" : "1x"
62 | },
63 | {
64 | "orientation" : "portrait",
65 | "idiom" : "ipad",
66 | "filename" : "Default-Portrait@2x.png",
67 | "extent" : "full-screen",
68 | "minimum-system-version" : "7.0",
69 | "scale" : "2x"
70 | },
71 | {
72 | "orientation" : "landscape",
73 | "idiom" : "ipad",
74 | "filename" : "Default-Landscape@2x.png",
75 | "extent" : "full-screen",
76 | "minimum-system-version" : "7.0",
77 | "scale" : "2x"
78 | },
79 | {
80 | "orientation" : "portrait",
81 | "idiom" : "iphone",
82 | "filename" : "Default.png",
83 | "extent" : "full-screen",
84 | "scale" : "1x"
85 | },
86 | {
87 | "orientation" : "portrait",
88 | "idiom" : "iphone",
89 | "filename" : "Default@2x.png",
90 | "extent" : "full-screen",
91 | "scale" : "2x"
92 | },
93 | {
94 | "orientation" : "portrait",
95 | "idiom" : "iphone",
96 | "filename" : "Default-568h@2x.png",
97 | "extent" : "full-screen",
98 | "subtype" : "retina4",
99 | "scale" : "2x"
100 | },
101 | {
102 | "orientation" : "portrait",
103 | "idiom" : "ipad",
104 | "extent" : "to-status-bar",
105 | "scale" : "1x"
106 | },
107 | {
108 | "orientation" : "portrait",
109 | "idiom" : "ipad",
110 | "filename" : "Default-Portrait.png",
111 | "extent" : "full-screen",
112 | "scale" : "1x"
113 | },
114 | {
115 | "orientation" : "landscape",
116 | "idiom" : "ipad",
117 | "extent" : "to-status-bar",
118 | "scale" : "1x"
119 | },
120 | {
121 | "orientation" : "landscape",
122 | "idiom" : "ipad",
123 | "filename" : "Default-Landscape.png",
124 | "extent" : "full-screen",
125 | "scale" : "1x"
126 | },
127 | {
128 | "orientation" : "portrait",
129 | "idiom" : "ipad",
130 | "extent" : "to-status-bar",
131 | "scale" : "2x"
132 | },
133 | {
134 | "orientation" : "portrait",
135 | "idiom" : "ipad",
136 | "filename" : "Default-Portrait@2x.png",
137 | "extent" : "full-screen",
138 | "scale" : "2x"
139 | },
140 | {
141 | "orientation" : "landscape",
142 | "idiom" : "ipad",
143 | "extent" : "to-status-bar",
144 | "scale" : "2x"
145 | },
146 | {
147 | "orientation" : "landscape",
148 | "idiom" : "ipad",
149 | "filename" : "Default-Landscape@2x.png",
150 | "extent" : "full-screen",
151 | "scale" : "2x"
152 | }
153 | ],
154 | "info" : {
155 | "version" : 1,
156 | "author" : "xcode"
157 | }
158 | }
--------------------------------------------------------------------------------
/demo-angular/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "extent" : "full-screen",
5 | "idiom" : "iphone",
6 | "subtype" : "736h",
7 | "filename" : "Default-736h@3x.png",
8 | "minimum-system-version" : "8.0",
9 | "orientation" : "portrait",
10 | "scale" : "3x"
11 | },
12 | {
13 | "extent" : "full-screen",
14 | "idiom" : "iphone",
15 | "subtype" : "736h",
16 | "filename" : "Default-Landscape@3x.png",
17 | "minimum-system-version" : "8.0",
18 | "orientation" : "landscape",
19 | "scale" : "3x"
20 | },
21 | {
22 | "extent" : "full-screen",
23 | "idiom" : "iphone",
24 | "subtype" : "667h",
25 | "filename" : "Default-667h@2x.png",
26 | "minimum-system-version" : "8.0",
27 | "orientation" : "portrait",
28 | "scale" : "2x"
29 | },
30 | {
31 | "orientation" : "portrait",
32 | "idiom" : "iphone",
33 | "filename" : "Default@2x.png",
34 | "extent" : "full-screen",
35 | "minimum-system-version" : "7.0",
36 | "scale" : "2x"
37 | },
38 | {
39 | "extent" : "full-screen",
40 | "idiom" : "iphone",
41 | "subtype" : "retina4",
42 | "filename" : "Default-568h@2x.png",
43 | "minimum-system-version" : "7.0",
44 | "orientation" : "portrait",
45 | "scale" : "2x"
46 | },
47 | {
48 | "orientation" : "portrait",
49 | "idiom" : "ipad",
50 | "filename" : "Default-Portrait.png",
51 | "extent" : "full-screen",
52 | "minimum-system-version" : "7.0",
53 | "scale" : "1x"
54 | },
55 | {
56 | "orientation" : "landscape",
57 | "idiom" : "ipad",
58 | "filename" : "Default-Landscape.png",
59 | "extent" : "full-screen",
60 | "minimum-system-version" : "7.0",
61 | "scale" : "1x"
62 | },
63 | {
64 | "orientation" : "portrait",
65 | "idiom" : "ipad",
66 | "filename" : "Default-Portrait@2x.png",
67 | "extent" : "full-screen",
68 | "minimum-system-version" : "7.0",
69 | "scale" : "2x"
70 | },
71 | {
72 | "orientation" : "landscape",
73 | "idiom" : "ipad",
74 | "filename" : "Default-Landscape@2x.png",
75 | "extent" : "full-screen",
76 | "minimum-system-version" : "7.0",
77 | "scale" : "2x"
78 | },
79 | {
80 | "orientation" : "portrait",
81 | "idiom" : "iphone",
82 | "filename" : "Default.png",
83 | "extent" : "full-screen",
84 | "scale" : "1x"
85 | },
86 | {
87 | "orientation" : "portrait",
88 | "idiom" : "iphone",
89 | "filename" : "Default@2x.png",
90 | "extent" : "full-screen",
91 | "scale" : "2x"
92 | },
93 | {
94 | "orientation" : "portrait",
95 | "idiom" : "iphone",
96 | "filename" : "Default-568h@2x.png",
97 | "extent" : "full-screen",
98 | "subtype" : "retina4",
99 | "scale" : "2x"
100 | },
101 | {
102 | "orientation" : "portrait",
103 | "idiom" : "ipad",
104 | "extent" : "to-status-bar",
105 | "scale" : "1x"
106 | },
107 | {
108 | "orientation" : "portrait",
109 | "idiom" : "ipad",
110 | "filename" : "Default-Portrait.png",
111 | "extent" : "full-screen",
112 | "scale" : "1x"
113 | },
114 | {
115 | "orientation" : "landscape",
116 | "idiom" : "ipad",
117 | "extent" : "to-status-bar",
118 | "scale" : "1x"
119 | },
120 | {
121 | "orientation" : "landscape",
122 | "idiom" : "ipad",
123 | "filename" : "Default-Landscape.png",
124 | "extent" : "full-screen",
125 | "scale" : "1x"
126 | },
127 | {
128 | "orientation" : "portrait",
129 | "idiom" : "ipad",
130 | "extent" : "to-status-bar",
131 | "scale" : "2x"
132 | },
133 | {
134 | "orientation" : "portrait",
135 | "idiom" : "ipad",
136 | "filename" : "Default-Portrait@2x.png",
137 | "extent" : "full-screen",
138 | "scale" : "2x"
139 | },
140 | {
141 | "orientation" : "landscape",
142 | "idiom" : "ipad",
143 | "extent" : "to-status-bar",
144 | "scale" : "2x"
145 | },
146 | {
147 | "orientation" : "landscape",
148 | "idiom" : "ipad",
149 | "filename" : "Default-Landscape@2x.png",
150 | "extent" : "full-screen",
151 | "scale" : "2x"
152 | }
153 | ],
154 | "info" : {
155 | "version" : 1,
156 | "author" : "xcode"
157 | }
158 | }
--------------------------------------------------------------------------------
/tns-oauth-webview-helper.android.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { WebView } from 'ui/web-view';
4 | import trace = require("trace");
5 |
6 | export class TnsOAuthWebViewHelper extends android.webkit.WebViewClient {
7 |
8 | private _view: any;
9 | private _origClient: any; //WebViewClient
10 | private _checkCodeIntercept: (WebView, error?, url?) => boolean;
11 |
12 | constructor() {
13 | super();
14 | return global.__native(this);
15 | }
16 |
17 | public static initWithWebViewAndIntercept(wv: WebView, checkCodeIntercept) {
18 | let wvCreateNv = wv.createNativeView;
19 | wv.createNativeView = () => {
20 | (wv)._webViewClient = TnsOAuthWebViewHelper.initWithView(wv, checkCodeIntercept);
21 | let nativeView = new android.webkit.WebView(wv._context);
22 | nativeView.getSettings().setJavaScriptEnabled(true);
23 | nativeView.getSettings().setBuiltInZoomControls(true);
24 | nativeView.setWebViewClient((wv)._webViewClient);
25 | (nativeView).client = (wv)._webViewClient;
26 | return nativeView;
27 | };
28 | }
29 |
30 | private static initWithView(view: WebView, checkCodeIntercept): TnsOAuthWebViewHelper {
31 | try {
32 | let client = new TnsOAuthWebViewHelper();
33 | client._view = view;
34 | client._origClient = (view)._webViewClient;
35 | client._checkCodeIntercept = checkCodeIntercept;
36 | return client;
37 | }
38 | catch (er) {
39 | console.dir(er);
40 | }
41 | }
42 |
43 | /// param url was a string before 7.1.1. It is an object after 7.1.1
44 | public shouldOverrideUrlLoading(view: android.webkit.WebView, url: any) {
45 | if (trace.isEnabled()) {
46 | trace.write("WebViewClientClass.shouldOverrideUrlLoading(" + url + ")", trace.categories.Debug);
47 | }
48 | var urlStr = '';
49 | if (typeof url === 'string') {
50 | urlStr = url;
51 | } else if (typeof url === 'object') {
52 | try {
53 | urlStr = url.getUrl().toString();
54 | }
55 | catch (ex) {
56 | return false;
57 | }
58 | } else {
59 | return false;
60 | }
61 | if (this._checkCodeIntercept(this._view, null, urlStr)) {
62 | return true;
63 | }
64 | return false;
65 | }
66 |
67 | public onPageStarted(view: android.webkit.WebView, url: string, favicon: android.graphics.Bitmap) {
68 | this._checkCodeIntercept(this._view, null, url);
69 |
70 | super.onPageStarted(view, url, favicon);
71 |
72 | if (this._view) {
73 | if (trace.isEnabled()) {
74 | trace.write("WebViewClientClass.onPageStarted(" + url + ", " + favicon + ")", trace.categories.Debug);
75 | }
76 | this._view._onLoadStarted(url, undefined);
77 | }
78 |
79 | }
80 |
81 | public onPageFinished(view: android.webkit.WebView, url: string) {
82 | super.onPageFinished(view, url);
83 |
84 | if (this._view) {
85 | if (trace.isEnabled()) {
86 | trace.write("WebViewClientClass.onPageFinished(" + url + ")", trace.categories.Debug);
87 | }
88 |
89 | this._checkCodeIntercept(this._view, null, url);
90 | this._view._onLoadFinished(url, undefined);
91 | }
92 | }
93 |
94 | public onReceivedError() {
95 | var view: android.webkit.WebView = arguments[0];
96 | if (arguments.length === 4) {
97 |
98 | var errorCode: number = arguments[1];
99 | var description: string = arguments[2];
100 | var failingUrl: string = arguments[3];
101 | this._checkCodeIntercept(this._view, null, failingUrl)
102 |
103 | super.onReceivedError(view, errorCode, description, failingUrl);
104 |
105 | if (this._view) {
106 | if (trace.isEnabled()) {
107 | trace.write("WebViewClientClass.onReceivedError(" + errorCode + ", " + description + ", " + failingUrl + ")", trace.categories.Debug);
108 | }
109 | this._view._onLoadFinished(failingUrl, description + "(" + errorCode + ")");
110 | }
111 | } else {
112 |
113 | var request: any = arguments[1];
114 | var error: any = arguments[2];
115 | this._checkCodeIntercept(this._view, error)
116 |
117 | super.onReceivedError(view, request, error);
118 |
119 | if (this._view) {
120 | if (trace.isEnabled()) {
121 | trace.write("WebViewClientClass.onReceivedError(" + error.getErrorCode() + ", " + error.getDescription() + ", " + (error.getUrl && error.getUrl()) + ")", trace.categories.Debug);
122 | }
123 | this._view._onLoadFinished(error.getUrl && error.getUrl(), error.getDescription() + "(" + error.getErrorCode() + ")");
124 | }
125 |
126 | }
127 | }
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/index.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import * as applicationModule from "application";
4 | import * as utils from "utils/utils";
5 | import { AuthHelperOffice365 } from "./auth-helper-office365";
6 | import { AuthHelperFacebook } from "./auth-helper-facebook";
7 | import { AuthHelperGoogle } from "./auth-helper-google";
8 | import { AuthHelperUaa } from "./auth-helper-uaa";
9 | import { AuthHelperLinkedIn } from "./auth-helper-linkedin";
10 | import { AuthHelperSalesforce } from "./auth-helper-salesforce";
11 | import { AuthHelperCustom } from "./auth-helper-custom";
12 |
13 | import * as TnsOAuth from "./tns-oauth-interfaces";
14 |
15 | export var instance: TnsOAuth.ITnsAuthHelper = null;
16 |
17 | export function initOffice365(
18 | options: TnsOAuth.ITnsOAuthOptionsOffice365
19 | ): Promise {
20 | console.error(
21 | "This plugin is deprecated, Please use the new nativescript-oauth2 plugin"
22 | );
23 | return new Promise(function(resolve, reject) {
24 | try {
25 | if (instance !== null) {
26 | reject("You already ran init");
27 | return;
28 | }
29 |
30 | instance = new AuthHelperOffice365(options.clientId, options.scope);
31 | resolve(instance);
32 | } catch (ex) {
33 | console.log("Error in AuthHelperOffice365.init: " + ex);
34 | reject(ex);
35 | }
36 | });
37 | }
38 |
39 | export function initFacebook(
40 | options: TnsOAuth.ITnsOAuthOptionsFacebook
41 | ): Promise {
42 | console.error(
43 | "This plugin is deprecated, Please use the new nativescript-oauth2 plugin"
44 | );
45 | return new Promise(function(resolve, reject) {
46 | try {
47 | if (instance !== null) {
48 | reject("You already ran init");
49 | return;
50 | }
51 |
52 | instance = new AuthHelperFacebook(
53 | options.clientId,
54 | options.clientSecret,
55 | options.scope
56 | );
57 | resolve(instance);
58 | } catch (ex) {
59 | console.log("Error in AuthHelperFacebook.init: " + ex);
60 | reject(ex);
61 | }
62 | });
63 | }
64 |
65 | export function initGoogle(
66 | options: TnsOAuth.ITnsOAuthOptionsGoogle
67 | ): Promise {
68 | console.error(
69 | "This plugin is deprecated, Please use the new nativescript-oauth2 plugin"
70 | );
71 | return new Promise(function(resolve, reject) {
72 | try {
73 | if (instance !== null) {
74 | reject("You already ran init");
75 | return;
76 | }
77 |
78 | instance = new AuthHelperGoogle(options.clientId, options.scope);
79 | resolve(instance);
80 | } catch (ex) {
81 | console.log("Error in AuthHelperGoogle.init: " + ex);
82 | reject(ex);
83 | }
84 | });
85 | }
86 |
87 | export function initUaa(options: TnsOAuth.ITnsOAuthOptionsUaa): Promise {
88 | console.error(
89 | "This plugin is deprecated, Please use the new nativescript-oauth2 plugin"
90 | );
91 | return new Promise(function(resolve, reject) {
92 | try {
93 | if (instance !== null) {
94 | reject("You already ran init");
95 | return;
96 | }
97 |
98 | instance = new AuthHelperUaa(
99 | options.authority,
100 | options.redirectUri,
101 | options.clientId,
102 | options.clientSecret,
103 | options.scope,
104 | options.cookieDomains,
105 | options.basicAuthHeader
106 | );
107 | resolve(instance);
108 | } catch (ex) {
109 | console.log("Error in AuthHelperUaa.init: " + ex);
110 | reject(ex);
111 | }
112 | });
113 | }
114 |
115 | export function initLinkedIn(
116 | options: TnsOAuth.ITnsOAuthOptionsLinkedIn
117 | ): Promise {
118 | console.error(
119 | "This plugin is deprecated, Please use the new nativescript-oauth2 plugin"
120 | );
121 | return new Promise(function(resolve, reject) {
122 | try {
123 | if (instance !== null) {
124 | reject("You already ran init");
125 | return;
126 | }
127 |
128 | instance = new AuthHelperLinkedIn(
129 | options.clientId,
130 | options.clientSecret,
131 | options.redirectUri,
132 | options.scope
133 | );
134 | resolve(instance);
135 | } catch (ex) {
136 | console.log("Error in AuthHelperLinkedIn.init: " + ex);
137 | reject(ex);
138 | }
139 | });
140 | }
141 |
142 | export function initSalesforce(
143 | options: TnsOAuth.ITnsOAuthOptionsSalesforce
144 | ): Promise {
145 | console.error(
146 | "This plugin is deprecated, Please use the new nativescript-oauth2 plugin"
147 | );
148 | return new Promise(function(resolve, reject) {
149 | try {
150 | if (instance !== null) {
151 | reject("You already ran init");
152 | return;
153 | }
154 |
155 | instance = new AuthHelperSalesforce(
156 | options.authority,
157 | options.clientId,
158 | options.redirectUri,
159 | options.responseType,
160 | options.scope
161 | );
162 | resolve(instance);
163 | } catch (ex) {
164 | console.log("Error in AuthHelperSalesforce.init: " + ex);
165 | reject(ex);
166 | }
167 | });
168 | }
169 |
170 | export function initCustom(
171 | options: TnsOAuth.ITnsOAuthOptionsCustom
172 | ): Promise {
173 | console.error(
174 | "This plugin is deprecated, Please use the new nativescript-oauth2 plugin"
175 | );
176 | return new Promise(function(resolve, reject) {
177 | try {
178 | if (instance !== null) {
179 | reject("You already ran init");
180 | return;
181 | }
182 |
183 | instance = new AuthHelperCustom(
184 | options.credentials,
185 | options.cookieDomains
186 | );
187 | resolve(instance);
188 | } catch (ex) {
189 | console.log("Error in AuthHelperCustom.init: " + ex);
190 | reject(ex);
191 | }
192 | });
193 | }
194 |
195 | export function accessToken(): string {
196 | return instance.tokenResult.accessToken;
197 | }
198 |
199 | export function login(successPage?: string): Promise {
200 | console.error(
201 | "This plugin is deprecated, Please use the new nativescript-oauth2 plugin"
202 | );
203 | return instance.login(successPage);
204 | }
205 | export function logout(successPage?: string): Promise {
206 | return instance.logout(successPage);
207 | }
208 | export function accessTokenExpired(): boolean {
209 | return instance.accessTokenExpired();
210 | }
211 |
212 | export function ensureValidToken(): Promise {
213 | return new Promise((resolve, reject) => {
214 | if (instance.accessTokenExpired()) {
215 | if (instance.refreshTokenExpired()) {
216 | login()
217 | .then((response: string) => {
218 | resolve(response);
219 | })
220 | .catch(er => {
221 | reject(er);
222 | });
223 | } else {
224 | instance
225 | .refreshToken()
226 | .then((result: string) => {
227 | resolve(result);
228 | })
229 | .catch(er => {
230 | reject(ErrorEvent);
231 | });
232 | }
233 | } else {
234 | resolve(accessToken());
235 | }
236 | });
237 | }
238 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OAuth 2 login plugin for NativeScript
2 |
3 | 
4 |
5 | Library for interacting with OAuth 2.0 in NativeScript applications that provides simplified client access with a OAuth providers that support the OAuth 2.0 protocol such as Microsoft Live accounts, Microsoft Graph, Office 365, Facebook, Cloud Foundry UAA instances, LinkedIn, and Google (Google is a work in progress due to some of their restrictions).
6 |
7 | **_UPDATE:_** **This plugin is deprecated and is now replaced by the new [nativescript-oauth2 plugin](https://www.npmjs.com/package/nativescript-oauth2)**
8 |
9 |
10 |
11 |
12 | Tested against Microsoft Live, Office 365, Microsoft Graph API, Facebook, LinkedIn and private instances of UAA.
13 |
14 | ## Prerequisites
15 |
16 | ### Office 365 / Microsoft Graph API
17 |
18 | For logging in with your Office 365 account, you should have an Office 365 Account admin account. If you don't have one yet, you can get a [free trial here](https://products.office.com/en-us/try).
19 |
20 | Watch a [video tutorial](https://youtu.be/nwf928oFGCM) for setting up the NativeScript OAuth plugin and registering you app with Microsoft.
21 |
22 | Register your mobile app [here](https://apps.dev.microsoft.com). This will require you to login with your Office 365 account. You can then click the big "Add an app" button and go through the steps listed there, starting with giving you app a name. On the app creation screen, you need to do 3 things:
23 |
24 | 1. Click the "Add Platform" button and select "Mobile application"
25 | 2. Copy the "Client Id" GUID from the Mobile Application section.
26 | 3. Click "Save" at the bottom.
27 |
28 | ### Facebook account
29 |
30 | For logging in with your Facebook account, you should have a Facebook developer account. If you don't have one yet, you can get one [here](https://developers.facebook.com/).
31 |
32 | Keep an eye out on my [YouTube channel](https://www.youtube.com/c/AlexanderZiskind) for a video on how to set up Facebook with with plugin.
33 |
34 | Register your mobile app by following the wizard under "My Apps" -> "Add a new app".
35 |
36 | 1. Go to https://developers.facebook.com/apps and create a new app
37 | 2. If you see the Product Setup page, select Facebook login
38 | 3. Make sure to turn ON the option "Embedded Browser OAuth Login"
39 | 4. Click Save
40 | 5. Copy the App ID and the App Secret from the Dashboard page to bootstrap your app. These will be the ClientID and CLientSecret respectively.
41 |
42 | ### LinkedIn Account
43 |
44 | For logging in with your LinkedIn account, you should have a LinkedIn developer account. If you don't have one yet, you can get one [here](https://developer.linkedin.com/).
45 |
46 | 1. Click on `My Apps` and login with your LinkedIn credentials or click on Join Now to create a new account.
47 | 2. Once logged in click on `Create Application`.
48 | 3. Fill out all fields with the app's information and Click `submit`.
49 | 4. If everything goes well you should get your app's authentication keys which consists of a client id and a client secret.
50 | 5. In this page, make sure to add an `Authorized Redirect URL`. (This can be any url starting with http:// or https://).
51 | 6. Copy the Authentication Keys and the Authorized Redirect URL.
52 |
53 | ### Cloud Foundry User Account and Authentication (UAA)
54 |
55 | You will need to have a Cloud Foundry account to deploy your instance of UAA.
56 |
57 | For more information, please refer to https://github.com/cloudfoundry/uaa
58 |
59 | ## Setup
60 |
61 | Add TypeScript to your NativeScript project if you don't already have it added. While this is not a requirement, it's highly recommended. If you want to watch a video on how to convert your existing JavaScript based NativeScript app to TypeScript, [watch it here](https://youtu.be/2JDXnduTlgs).
62 |
63 | From the command prompt go to your app's root folder and execute:
64 |
65 | ```
66 | npm install nativescript-oauth --save
67 | ```
68 |
69 | ## Usage
70 |
71 | If you want a quickstart, you can start with one of two demo apps:
72 |
73 | - [TypeScript Demo App](https://github.com/alexziskind1/nativescript-oauth/tree/master/demo)
74 | - [Angular Demo App](https://github.com/alexziskind1/nativescript-oauth/tree/master/demo-angular)
75 |
76 | ### Bootstrapping
77 |
78 | We need to do some wiring when your app starts. If you are not using Angular, open `app.ts` and add the following code before `application.start();`
79 |
80 | If you are using Angular, then open your `main.ts` file and add the following code before `platformNativeScriptDynamic().bootstrapModule(AppModule);`
81 |
82 | ##### TypeScript
83 |
84 | ```js
85 | import * as tnsOAuthModule from "nativescript-oauth";
86 | ```
87 |
88 | ###### For Office365 login, include the following lines
89 |
90 | ```js
91 | var o365InitOptions: tnsOAuthModule.ITnsOAuthOptionsOffice365 = {
92 | clientId: "e392f6aa-da5c-434d-a42d-a0e0a27d3955", //client id for application (GUID)
93 | scope: ["Files.ReadWrite", "offline_access"] //whatever other scopes you need
94 | };
95 |
96 | tnsOAuthModule.initOffice365(o365InitOptions);
97 | ```
98 |
99 | ###### For Facebook login, include the following lines
100 |
101 | ```js
102 | var facebookInitOptions: tnsOAuthModule.ITnsOAuthOptionsFacebook = {
103 | clientId: "1119818654921555",
104 | clientSecret: "bbb58f212b51e4d555bed857171c9aaa",
105 | scope: ["email"] //whatever other scopes you need
106 | };
107 |
108 | tnsOAuthModule.initFacebook(facebookInitOptions);
109 | ```
110 |
111 | ###### For UAA login, include the following lines
112 |
113 | ```js
114 | var uaaInitOptions: tnsOAuthModule.ITnsOAuthOptionsUaa = {
115 | authority: "https://my-uaa-instance.com",
116 | redirectUri: "myAppDomain://authcallback",
117 | clientId: "my-client-id",
118 | clientSecret: "my-client-secret",
119 | scope: ["uaa.resource", "uaa.user"],
120 | cookieDomains: ["myAppDomain://"],
121 | basicAuthHeader: "Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
122 | };
123 |
124 | tnsOAuthModule.initUaa(uaaInitOptions);
125 | ```
126 |
127 | ###### For LinkedIn login, include the following lines
128 |
129 | ```js
130 | var linkedInInitOptions: tnsOAuthModule.ITnsOAuthOptionsLinkedIn = {
131 | clientId: "",
132 | clientSecret: "",
133 | scope: ["r_basicprofile"] //Leave blank and the default scopes will be used
134 | };
135 |
136 | tnsOAuthModule.initLinkedIn(linkedInInitOptions);
137 | ```
138 |
139 | ###### For Custom OAuth Login, include the following lines
140 |
141 | The custom provider is intended for advanced users. It directly exposes the OAuth credentials. You can use this to connect with your own private identity server or other providers.
142 |
143 | ```js
144 | var myInitOptions : tnsOAuthModule.ITnsOAuthCredentials = {
145 | authority: 'https://my.identity-server',
146 | authorizeEndpoint: '/my/authorize/endpoint'
147 | tokenEndpoint: '/my/token/endpoint',
148 | clientId: 'myClientId',
149 | clientSecret: 'my-client-secret,
150 | redirectUri: 'myAppDomain://callback',
151 | responseType: 'my tokens',
152 | scope: 'my requested scopes',
153 | };
154 |
155 | tnsOAuthModule.initCustom({
156 | credentials: myInitOptions,
157 | cookieDomains: [ 'my.identity-server', ... ],
158 | });
159 | ```
160 |
161 | ### Logging in
162 |
163 | In your view controller or component (or wherever you will have a handler to respond to the login user action) you will reference the `nativescript-oauth` module again and call the `login` function.
164 |
165 | ```js
166 | import * as tnsOAuthModule from 'nativescript-oauth';
167 | ...
168 | tnsOAuthModule.login()
169 | .then(()=>{
170 | console.log('logged in');
171 | console.dir("accessToken " + tnsOAuthModule.accessToken());
172 | })
173 | .catch((er)=>{
174 | //do something with the error
175 | });
176 | ```
177 |
178 | When you make API calls you can use the `ensureValidToken` function, which will also ask you to authenticate, if the token is expired.
179 |
180 | ```js
181 | tnsOAuthModule
182 | .ensureValidToken()
183 | .then((token: string) => {
184 | console.log("token: " + token);
185 | })
186 | .catch(er => {
187 | //do something with the error
188 | });
189 | ```
190 |
191 | ## Contributing
192 |
193 | 1. Fork the nativescript-oauth repository on GitHub
194 | 1. Clone your fork
195 | 1. Change directory to `nativescript-oauth`
196 | 1. Run `npm install` in the root folder to install all npm packages for the plugin
197 | 1. Run `tsc` in the root folder to build the plugin TypeScript
198 | 1. Edit the `/demo/package.json` file: `"nativescript-oauth" : "../"` - this will point the demo project to use the local oauth plugin instead of the one hosted on npm.
199 | 1. Run `npm install` in the `demo` folder to install all npm packages for the demo (these are also shared by the plugin, so they are needed to build)
200 | 1. Replace the ClientId in the app.ts file of the demo with your own ClientId
201 | 1. Run the demo project
202 |
--------------------------------------------------------------------------------
/tns-oauth.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 |
4 | import * as querystring from 'querystring';
5 | import * as URL from 'url';
6 | import * as http from 'http';
7 | import * as trace from "trace";
8 | import * as frameModule from 'ui/frame';
9 | import * as platform from 'platform';
10 | import * as utils from './tns-oauth-utils';
11 | import { TnsOAuthPageProvider } from './tns-oauth-page-provider';
12 | import { TnsOAuthTokenCache } from './tns-oauth-token-cache';
13 | import * as TnsOAuthModule from './tns-oauth-interfaces';
14 |
15 | export var ACCESS_TOKEN_CACHE_KEY = 'ACCESS_TOKEN_CACHE_KEY';
16 | export var REFRESH_TOKEN_CACHE_KEY = 'REFRESH_TOKEN_CACHE_KEY';
17 |
18 |
19 | function getAuthHeaderFromCredentials(credentials: TnsOAuthModule.ITnsOAuthCredentials) {
20 | let customAuthHeader: any;
21 | if (credentials['basicAuthHeader']) {
22 | customAuthHeader = { 'Authorization': credentials['basicAuthHeader'] };
23 | }
24 |
25 | return customAuthHeader;
26 | }
27 |
28 |
29 | /**
30 | * Gets a token for a given resource.
31 | */
32 | function getTokenFromCode(credentials: TnsOAuthModule.ITnsOAuthCredentials, code: string): Promise {
33 |
34 | let customAuthHeader: any = getAuthHeaderFromCredentials(credentials);
35 |
36 | let oauth2 = new TnsOAuth(
37 | credentials.clientId,
38 | credentials.clientSecret,
39 | credentials.authority,
40 | credentials.tokenEndpointBase,
41 | credentials.authorizeEndpoint,
42 | credentials.tokenEndpoint,
43 | customAuthHeader
44 | );
45 |
46 | let oauthParams = {
47 | grant_type: 'authorization_code',
48 | redirect_uri: credentials.redirectUri,
49 | response_mode: 'form_post',
50 | nonce: utils.newUUID(),
51 | state: 'abcd'
52 | };
53 |
54 | return oauth2.getOAuthAccessToken(code, oauthParams);
55 | }
56 |
57 | /**
58 | * Gets a new access token via a previously issued refresh token.
59 | */
60 | export function getTokenFromRefreshToken(credentials: TnsOAuthModule.ITnsOAuthCredentials, refreshToken: string): Promise {
61 |
62 | let customAuthHeader: any = getAuthHeaderFromCredentials(credentials);
63 |
64 | var oauth2 = new TnsOAuth(
65 | credentials.clientId,
66 | credentials.clientSecret,
67 | credentials.authority,
68 | credentials.tokenEndpointBase,
69 | credentials.authorizeEndpoint,
70 | credentials.tokenEndpoint,
71 | customAuthHeader
72 | );
73 |
74 | let oauthParams = {
75 | grant_type: 'refresh_token',
76 | redirect_uri: credentials.redirectUri,
77 | response_mode: 'form_post',
78 | nonce: utils.newUUID(),
79 | state: 'abcd'
80 | };
81 |
82 | return oauth2.getOAuthAccessToken(refreshToken, oauthParams);
83 | }
84 |
85 | /**
86 | * Generate a fully formed uri to use for authentication based on the supplied resource argument
87 | * @return {string} a fully formed uri with which authentication can be completed
88 | */
89 | export function getAuthUrl(credentials: TnsOAuthModule.ITnsOAuthCredentials): string {
90 | return credentials.authority + credentials.authorizeEndpoint +
91 | '?client_id=' + credentials.clientId +
92 | '&response_type=code' +
93 | '&redirect_uri=' + credentials.redirectUri +
94 | '&scope=' + credentials.scope +
95 | '&response_mode=query' +
96 | '&nonce=' + utils.newUUID() +
97 | '&state=abcd';
98 | }
99 |
100 | export function getTokenFromCache() {
101 | return TnsOAuthTokenCache.getToken();
102 | }
103 |
104 | export function loginViaAuthorizationCodeFlow(credentials: TnsOAuthModule.ITnsOAuthCredentials, successPage?: string): Promise {
105 | return new Promise((resolve, reject) => {
106 | var navCount = 0;
107 |
108 | let hasCode = false;
109 |
110 | let checkCodeIntercept = (webView, error, url): boolean => {
111 | var retStr = '';
112 | try {
113 | if (error && error.userInfo && error.userInfo.allValues && error.userInfo.allValues.count > 0) {
114 | let val0 = error.userInfo.allValues[0];
115 | if (val0.absoluteString) {
116 | retStr = error.userInfo.allValues[0].absoluteString;
117 | } else if (val0.userInfo && val0.userInfo.allValues && val0.userInfo.allValues.count > 0) {
118 | retStr = val0.userInfo.allValues[0];
119 | } else {
120 | retStr = val0;
121 | }
122 | //} else if (webView.request && webView.request.URL && webView.request.URL.absoluteString) {
123 | } else if (webView && webView.URL && webView.URL.absoluteString) {
124 | retStr = webView.URL.absoluteString;
125 | } else if (url) {
126 | retStr = url;
127 | }
128 | }
129 | catch (ex) {
130 | reject('Failed to resolve return URL');
131 | }
132 |
133 | if (retStr != '') {
134 | let parsedRetStr = URL.parse(retStr);
135 | if (parsedRetStr.query) {
136 | let qsObj = querystring.parse(parsedRetStr.query);
137 | let codeStr = qsObj['code'] ? qsObj['code'] : qsObj['xsrfsign'];
138 | let errSubCode = qsObj['error_subcode'];
139 | if (codeStr && !hasCode) {
140 | hasCode = true;
141 | try {
142 | getTokenFromCode(credentials, codeStr)
143 | .then((response: TnsOAuthModule.ITnsOAuthTokenResult) => {
144 | TnsOAuthTokenCache.setToken(response);
145 | if (successPage && navCount === 0) {
146 | let navEntry: frameModule.NavigationEntry = {
147 | moduleName: successPage,
148 | clearHistory: true
149 | };
150 | frameModule.topmost().navigate(navEntry);
151 | } else {
152 | frameModule.topmost().goBack();
153 | }
154 | navCount++;
155 | resolve(response);
156 | })
157 | .catch((er) => {
158 | reject(er);
159 | });
160 |
161 | } catch (er) {
162 | console.error('getOAuthAccessToken error occurred...');
163 | console.dir(er);
164 | reject(er);
165 | }
166 | return true;
167 | } else {
168 | if (errSubCode) {
169 | if (errSubCode == 'cancel') {
170 | frameModule.topmost().goBack();
171 | }
172 | }
173 | }
174 | }
175 | }
176 | return false;
177 | };
178 |
179 | console.log('LOGIN PAGE URL = ' + getAuthUrl(credentials));
180 | let authPage = new TnsOAuthPageProvider(checkCodeIntercept, getAuthUrl(credentials), reject);
181 | frameModule.topmost().navigate(() => { return authPage.loginPageFunc() });
182 | });
183 | }
184 |
185 | export function refreshToken(credentials: TnsOAuthModule.ITnsOAuthCredentials): Promise {
186 | return new Promise((resolve, reject) => {
187 | try {
188 | let oldTokenResult = TnsOAuthTokenCache.getToken();
189 |
190 | getTokenFromRefreshToken(credentials, oldTokenResult.refreshToken)
191 | .then((response: TnsOAuthModule.ITnsOAuthTokenResult) => {
192 | TnsOAuthTokenCache.setToken(response);
193 | resolve(response);
194 | })
195 | .catch((er) => {
196 | reject(er);
197 | });
198 | } catch (er) {
199 | console.error('refreshToken error occurred...');
200 | console.dir(er);
201 | reject(er);
202 | }
203 | });
204 | }
205 |
206 | export function logout(cookieDomains: string[], successPage?: string) {
207 | if (platform.isIOS) {
208 | let cookieArr = utils.nsArrayToJSArray(NSHTTPCookieStorage.sharedHTTPCookieStorage.cookies);
209 | for (var i = 0; i < cookieArr.length; i++) {
210 | var cookie: NSHTTPCookie = cookieArr[i];
211 | for (var j = 0; j < cookieDomains.length; j++) {
212 | if (utils.endsWith(cookie.domain, cookieDomains[j])) {
213 | NSHTTPCookieStorage.sharedHTTPCookieStorage.deleteCookie(cookie);
214 | }
215 | }
216 | }
217 | } else if (platform.isAndroid) {
218 | let cookieManager = android.webkit.CookieManager.getInstance();
219 | if ((cookieManager).removeAllCookies) {
220 | let cm23 = cookieManager;
221 | cm23.removeAllCookies(null);
222 | cm23.flush();
223 | } else if (cookieManager.removeAllCookie) {
224 | cookieManager.removeAllCookie();
225 | cookieManager.removeSessionCookie();
226 | }
227 | }
228 |
229 |
230 | TnsOAuthTokenCache.removeToken();
231 |
232 | if (successPage) {
233 | let navEntry: frameModule.NavigationEntry = {
234 | moduleName: successPage,
235 | clearHistory: true
236 | };
237 | frameModule.topmost().navigate(navEntry);
238 | }
239 | }
240 |
241 | class TnsOAuth {
242 | private _clientId: string;
243 | private _clientSecret: string;
244 | private _baseSite: string;
245 | private _baseSiteToken: string;
246 | private _authorizeUrl: string;
247 | private _accessTokenUrl: string;
248 | private _accessTokenName: string;
249 | private _authMethod: string;
250 | private _customHeaders: any;
251 | private _useAuthorizationHeaderForGET: boolean;
252 |
253 | constructor(clientId: string,
254 | clientSecret: string,
255 | baseSite: string,
256 | baseSiteToken: string,
257 | authorizePath: string,
258 | accessTokenPath: string,
259 | customHeaders?: any) {
260 | this._clientId = clientId;
261 | this._clientSecret = clientSecret;
262 | this._baseSite = baseSite;
263 | this._baseSiteToken = baseSiteToken;
264 | this._authorizeUrl = authorizePath || "/oauth/authorize";
265 | this._accessTokenUrl = accessTokenPath || "/oauth/access_token";
266 | this._accessTokenName = "access_token";
267 | this._authMethod = "Bearer";
268 | this._customHeaders = customHeaders || {};
269 | this._useAuthorizationHeaderForGET = false;
270 | }
271 |
272 | get accessTokenUrl(): string {
273 | if (this._baseSiteToken && this._baseSiteToken != '') {
274 | return this._baseSiteToken + this._accessTokenUrl;
275 | } else {
276 | return this._baseSite + this._accessTokenUrl; /* + "?" + querystring.stringify(params); */
277 | }
278 | }
279 |
280 | // This 'hack' method is required for sites that don't use
281 | // 'access_token' as the name of the access token (for requests).
282 | // ( http://tools.ietf.org/html/draft-ietf-oauth-v2-16#section-7 )
283 | // it isn't clear what the correct value should be atm, so allowing
284 | // for specific (temporary?) override for now.
285 | public setAccessTokenName(name) {
286 | this._accessTokenName = name;
287 | }
288 |
289 | // Sets the authorization method for Authorization header.
290 | // e.g. Authorization: Bearer # "Bearer" is the authorization method.
291 | public setAuthMethod(authMethod) {
292 | this._authMethod = authMethod;
293 | };
294 |
295 | // If you use the OAuth2 exposed 'get' method (and don't construct your own _request call )
296 | // this will specify whether to use an 'Authorize' header instead of passing the access_token as a query parameter
297 | public useAuthorizationHeaderforGET(useIt) {
298 | this._useAuthorizationHeaderForGET = useIt;
299 | }
300 |
301 | // Build the authorization header. In particular, build the part after the colon.
302 | // e.g. Authorization: Bearer # Build "Bearer "
303 | public buildAuthHeader(token) {
304 | return this._authMethod + ' ' + token;
305 | };
306 |
307 | public getAuthorizeUrl(params) {
308 | var params = params || {};
309 | params['client_id'] = this._clientId;
310 | return this._baseSite + this._authorizeUrl + "?" + querystring.stringify(params);
311 | }
312 |
313 | public getOAuthAccessToken(code, params): Promise {
314 | var params = params || {};
315 | params['client_id'] = this._clientId;
316 | if (this._clientSecret && this._clientSecret != '') {
317 | params['client_secret'] = this._clientSecret;
318 | }
319 |
320 | var codeParam = (params.grant_type === 'refresh_token') ? 'refresh_token' : 'code';
321 | params[codeParam] = code;
322 |
323 | var post_data = querystring.stringify(params);
324 | var post_headers = {
325 | 'Content-Type': 'application/x-www-form-urlencoded'
326 | };
327 |
328 | return new Promise((resolve, reject) => {
329 | this._request("POST", this.accessTokenUrl, post_headers, post_data, null)
330 | .then((response: http.HttpResponse) => {
331 | var results;
332 | try {
333 | // As of http://tools.ietf.org/html/draft-ietf-oauth-v2-07
334 | // responses should be in JSON
335 | results = response.content.toJSON();
336 | }
337 | catch (e) {
338 | // .... However both Facebook + Github currently use rev05 of the spec
339 | // and neither seem to specify a content-type correctly in their response headers :(
340 | // clients of these services will suffer a *minor* performance cost of the exception
341 | // being thrown
342 | results = querystring.parse(response.content.toString());
343 | }
344 | let access_token = results["access_token"];
345 | let refresh_token = results["refresh_token"];
346 | let expires_in = results["expires_in"];
347 | delete results["refresh_token"];
348 |
349 | let expSecs = Math.floor(parseFloat(expires_in));
350 | let expDate = new Date();
351 | expDate.setSeconds(expDate.getSeconds() + expSecs);
352 |
353 | let tokenResult: TnsOAuthModule.ITnsOAuthTokenResult = {
354 | accessToken: access_token,
355 | refreshToken: refresh_token,
356 | accessTokenExpiration: expDate,
357 | refreshTokenExpiration: expDate
358 | };
359 |
360 | resolve(tokenResult);
361 | })
362 | .catch((er) => {
363 | reject(er);
364 | });
365 | });
366 | }
367 |
368 | private _request(method, url, headers, post_body, access_token): Promise {
369 | var parsedUrl = URL.parse(url, true);
370 |
371 | var realHeaders = {};
372 | for (var key in this._customHeaders) {
373 | realHeaders[key] = this._customHeaders[key];
374 | }
375 | if (headers) {
376 | for (var key in headers) {
377 | realHeaders[key] = headers[key];
378 | }
379 | }
380 | realHeaders['Host'] = parsedUrl.host;
381 |
382 | if (access_token && !('Authorization' in realHeaders)) {
383 | if (!parsedUrl.query) {
384 | parsedUrl.query = {};
385 | }
386 | parsedUrl.query[this._accessTokenName] = access_token;
387 | }
388 |
389 | var queryStr = querystring.stringify(parsedUrl.query);
390 | if (queryStr) {
391 | queryStr = "?" + queryStr;
392 | }
393 | var options = {
394 | host: parsedUrl.hostname,
395 | port: parsedUrl.port,
396 | path: parsedUrl.pathname + queryStr,
397 | method: method,
398 | headers: realHeaders
399 | };
400 |
401 | return this._executeRequest(options, url, post_body);
402 | }
403 |
404 | private _executeRequest(options, url, post_body): Promise {
405 | var promise = http.request({
406 | url: url,
407 | method: options.method,
408 | headers: options.headers,
409 | content: post_body
410 | });
411 | return promise;
412 | }
413 | }
414 |
--------------------------------------------------------------------------------