UNPKG

nativescript-social-login-v2

Version:
461 lines (356 loc) 14.2 kB
[![npm](https://img.shields.io/npm/v/nativescript-social-login.svg)](https://www.npmjs.com/package/nativescript-social-login) [![npm](https://img.shields.io/npm/dt/nativescript-social-login.svg?label=npm%20downloads)](https://www.npmjs.com/package/nativescript-social-login) # NativeScript Social Login [NativeScript](https://www.nativescript.org/) module for social (token based) log-ins. [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WBLVWQKHLH3JG) ## Implementations | Provider | Android | iOS | | ---- | ---- | ---- | | Google | Yes | Yes | | Facebook | Yes | Yes | | Twitter | No | No | ## License [MIT license](https://raw.githubusercontent.com/mkloubert/nativescript-social-login/master/LICENSE) ## Documentation The full documentation can be found on [readme.io](https://nativescript-sociallogin.readme.io/). ## Changes ### v1.4.x to 1.5.x #### Google * Implemented login on iOS ### v1.3.x to 1.4.x #### Facebook * Implemented login on iOS ### v1.2.x to 1.3.x #### Google * The default value for `ILoginConfiguration.google.isRequestAuthCode` is `(false)` now. This behavior will not be changed in the future again! ## Installation Run ```bash tns plugin add nativescript-social-login ``` inside your app project to install the module. ### Android #### AndroidManifest.xml ##### Permissions ```xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <!-- ... --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- ... --> </manifest> ``` ##### Strings ```xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="facebook_app_id">{{ YOUR_FACEBOOK_APP_ID }}</string> <string name="fb_login_protocol_scheme">fb{{ YOUR_FACEBOOK_APP_ID }}</string> </resources> ``` ### Setup Android Google Sign in for Debug Builds 1. You need the *SHA1* value associated with the `debug.keystore` in your local android setup on your machine. For example, the following command is what you might run on a Windows machine: ``` shell keytool -list -v -keystore C:/users/brad.martin/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android ``` The path will change according to the path on your machine. The android debug builds are signed with this default `debug.keystore` located on your machine. So when you run the debug build on a device Google will allow the authentication with the running .apk since it has the SHA1 for the debug.keystore the debug app is built with. 2. Create an app [here](https://developers.google.com/mobile/add?platform=android&cntapi=signin&cntapp=Default%20Demo%20App&cntpkg=com.google.samples.quickstart.signin&cnturl=https:%2F%2Fdevelopers.google.com%2Fidentity%2Fsign-in%2Fandroid%2Fstart%3Fconfigured%3Dtrue&cntlbl=Continue%20with%20Try%20Sign-In) on Google Developer site. - Enter the App name. This can be anything but it will display to the user who is authenticating. - Enter the android package name. The `package` name is the android app name which is in the *package.json* under the `nativescript` object as the `id` property. - Next configure the Google services. - Select `Google Sign-In` - Enter your Signing Certificate SHA-1. This is the SHA1 value you get from the first step when running the `keytool` command. - Enable Google Sign-In - If only enabling Google Sign-In you do not need the configuration file inside your application. 3. Run the app and `loginWithGoogle()` should return the data associated with the google account that was selected. ### iOS #### GoogleService-Info.plist You should generate a `GoogleService-Info.plist` file for your application and add it to `/app/App_Resources/iOS` folder. You can get this file and find more info here - https://developers.google.com/identity/sign-in/ios/start-integrating #### Info.plist Add the following to your Info.plist file located in app/App_Resources/iOS ```xml <!-- FACEBOOK AND GOOGLE LOGIN --> <key>CFBundleURLTypes</key> <array> <!-- GOOGLE START --> <dict> <key>CFBundleTypeRole</key> <string>Editor</string> <key>CFBundleURLSchemes</key> <array> <string>{YOUR_GOOGLE_REVERSED_CLIENT_ID}</string> <!-- It shoud look like this: com.googleusercontent.apps.123123123-172648sdfsd76f8s7d6f8sd --> <!-- Get it from your GoogleService-Info.plist --> <!-- Read more - https://developers.google.com/identity/sign-in/ios/start-integrating --> </array> </dict> <!-- GOOGLE END --> <!-- FACEBOOK START --> <dict> <key>CFBundleURLSchemes</key> <array> <string>fb{YOUR_FACEBOOK_APP_ID_HERE}</string> </array> </dict> </array> <key>CFBundleVersion</key> <string>1.0</string> <key>FacebookAppID</key> <string>{YOUR_FACEBOOK_APP_ID_HERE}</string> <key>FacebookDisplayName</key> <string>FacebookLoginDemo</string> <!-- FACEBOOK END --> ``` https://developers.facebook.com/docs/ios #### Application main file Add this to the file where you start the application. Add the following code just before `application.start({ /* */ });` or `platformNativeScriptDynamic().bootstrapModule(/* */)` if you use Angular: ##### TypeScript ```typescript if (application.ios) { class MyDelegate extends UIResponder implements UIApplicationDelegate { public static ObjCProtocols = [UIApplicationDelegate]; applicationDidFinishLaunchingWithOptions(application: UIApplication, launchOptions: NSDictionary): boolean { let gglDelegate = false; try { const errorRef = new interop.Reference(); GGLContext.sharedInstance().configureWithError(errorRef); const signIn = GIDSignIn.sharedInstance(); gglDelegate = true; } catch (error) { console.log(error); } const fcbDelegate = FBSDKApplicationDelegate.sharedInstance().applicationDidFinishLaunchingWithOptions(application, launchOptions); // facebook login delegate return gglDelegate || fcbDelegate; } applicationOpenURLSourceApplicationAnnotation(application, url, sourceApplication, annotation) { const fcbDelegate = FBSDKApplicationDelegate.sharedInstance().applicationOpenURLSourceApplicationAnnotation(application, url, sourceApplication, annotation); // facebook login delegate const gglDelegate = GIDSignIn.sharedInstance().handleURLSourceApplicationAnnotation(url, sourceApplication, annotation); // google login delegate return fcbDelegate || gglDelegate; } } application.ios.delegate = MyDelegate; } ``` ##### JavaScript ```javascript if (application.ios) { var MyDelegate = (function (_super) { __extends(MyDelegate, _super); function MyDelegate() { return _super !== null && _super.apply(this, arguments) || this; } MyDelegate.prototype.applicationDidFinishLaunchingWithOptions = function (application, launchOptions) { var gglDelegate = false; try { var errorRef = new interop.Reference(); GGLContext.sharedInstance().configureWithError(errorRef); var signIn = GIDSignIn.sharedInstance(); gglDelegate = true; } catch (error) { console.log(error); } var fcbDelegate = FBSDKApplicationDelegate.sharedInstance().applicationDidFinishLaunchingWithOptions(application, launchOptions); // facebook login delegate return gglDelegate || fcbDelegate; }; MyDelegate.prototype.applicationOpenURLSourceApplicationAnnotation = function (application, url, sourceApplication, annotation) { var fcbDelegate = FBSDKApplicationDelegate.sharedInstance().applicationOpenURLSourceApplicationAnnotation(application, url, sourceApplication, annotation); // facebook login delegate var gglDelegate = GIDSignIn.sharedInstance().handleURLSourceApplicationAnnotation(url, sourceApplication, annotation); // google login delegate return fcbDelegate || gglDelegate; }; return MyDelegate; }(UIResponder)); MyDelegate.ObjCProtocols = [UIApplicationDelegate]; application.ios.delegate = MyDelegate; } ``` ## Usage ### Include Include the module in your code-behind: ```typescript import SocialLogin = require("nativescript-social-login"); ``` ### Initialize ```typescript import Application = require("application"); import SocialLogin = require("nativescript-social-login"); if (Application.android) { Application.android.on(Application.AndroidApplication.activityCreatedEvent, (event) => { let result = SocialLogin.init({ activity: event.activity, }); }); } ``` The `init()` function receives an (optional) object with the following structure: ```typescript interface ILoginConfiguration { /** * The underlying custom activity to use. */ activity?: android.app.Activity; /** * Facebook specific configuration. */ facebook?: { /** * Initialize Facebook or not. Default: (true) */ initialize?: boolean; /** * Should Logout current Facebook session or not. Default: (false) */ clearSession?: boolean; } /** * Google specific configuration. */ google?: { /** * Initialize Google or not. Default: (true) */ initialize?: boolean; /** * The server client ID for requesting server auth token. */ serverClientId?: string; /** * If true, it will request for offline auth code which server can use for fetching or refreshing auth tokens. * It will be set in authCode property of result object. * * If false (default), it will request for token id. it will be set in authToken property of result object. */ isRequestAuthCode?: boolean; } /** * Fallback action for the result of the underlying activity. */ onActivityResult?: (requestCode: number, resultCode: number, data: any) => void; } ``` The `result` object that is returned by `init()` has the following structure: ```typescript interface IInitializationResult { facebook: { error: any, isInitialized: boolean, }, google: { error: any, isInitialized: boolean, }, twitter: { error: any, isInitialized: boolean, } } ``` The `isInitialized` can be `(true)` for succeeded, `(false)` for failed, `(undefined)` for "not supported" and `(null)` for providers that have been skipped. The `error` properties are only defined if an exception was thrown while initialization. ### Login If you want to use a login functions you have to submit a callback that receives an object with the following structure: ```typescript interface ILoginResult { /** * Gets the auth token (if requested). */ authToken?: string; /** * Offline auth code used by servers to request new auth tokens. */ authCode?: string; /** * Gets the result code. */ code: LoginResultType; /** * The display name. */ displayName?: string; /** * First name of the user. */ firstName?: string; /** * Last name of the user. */ lastName?: string; /** * Gets the error (if defined). */ error?: any; /** * The ID of the user. */ id?: string; /** * The photo URL. */ photo?: string; /** * Gets the underlying provider. */ provider?: string; /** * The user token, like email address. */ userToken?: string; } ``` The following functions are implemented: | Provider | Provider | | ---- | ---- | | loginWithFacebook | Facebook | | loginWithGoogle | Google | ## Example ```typescript SocialLogin.loginWithFacebook( (result) => { console.log("code: " + result.code); console.log("error: " + result.error); console.log("userToken: " + result.userToken); console.log("displayName: " + result.displayName); console.log("photo: " + result.photo); console.log("authToken: " + result.authToken); } ); ``` It is worth noting that for an Angular-based app, this callback should be wrapped within an `NgZone` to Angular handle updating the view properly when complete. ```typescript import { Component, NgZone } from "angular/core"; @Component({}) class SigninComponent { constructor(private ngZone: NgZone) {} login() { SocialLogin.loginWithFacebook((result) => { this.ngZone.run(() => { console.log("code: " + result.code); console.log("error: " + result.error); console.log("userToken: " + result.userToken); console.log("displayName: " + result.displayName); console.log("photo: " + result.photo); console.log("authToken: " + result.authToken); }); }); } } ``` There is also a [great example](https://github.com/dgomezs/facebook-login) by [dgomezs](https://github.com/dgomezs) that shows how to configure your app for Facebook. ## Logging If you want to get the logging output of the module, you can use `SocialLogin.addLogger()` function to add a callback that receives a message from the module: ```typescript SocialLogin.addLogger(function(msg: any, tag: string) { console.log('[nativescript-social-login]: (' + tag + '): ' + msg); }); ``` ## Contributors * [Fábio Araújo](https://github.com/fmsaraujo) * [Brad Martin](https://github.com/bradmartin) * [Jeremiah Ogbomo](https://github.com/jogboms) * [Shripal Soni](http://www.shripalsoni.com) * [Andrii Votiakov](https://github.com/votiakov) * [Felipe Waku](https://github.com/felipewaku)