nativescript-social-login-v2
Version:
NativeScript plugin for social (token based) log-ins.
461 lines (356 loc) • 14.2 kB
Markdown
[](https://www.npmjs.com/package/nativescript-social-login)
[](https://www.npmjs.com/package/nativescript-social-login)
[](https://www.nativescript.org/) module for social (token based) log-ins.
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WBLVWQKHLH3JG)
| Provider | Android | iOS |
| ---- | ---- | ---- |
| Google | Yes | Yes |
| Facebook | Yes | Yes |
| Twitter | No | No |
[](https://raw.githubusercontent.com/mkloubert/nativescript-social-login/master/LICENSE)
The full documentation can be found on [readme.io](https://nativescript-sociallogin.readme.io/).
* Implemented login on iOS
* Implemented login on iOS
* The default value for `ILoginConfiguration.google.isRequestAuthCode` is `(false)` now. This behavior will not be changed in the future again!
Run
```bash
tns plugin add nativescript-social-login
```
inside your app project to install the module.
```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>
```
```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>
```
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.
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
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
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
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
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;
}
```
Include the module in your code-behind:
```typescript
import SocialLogin = require("nativescript-social-login");
```
```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.
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 |
```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.
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);
});
```
* [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)