@ist-group/react-native-skolid

A library for managing a user's session with SkolID in a react native application.

Stats

StarsIssuesVersionUpdatedCreatedSize
@ist-group/react-native-skolid
13.2.23 months ago4 years agoMinified + gzip package size for @ist-group/react-native-skolid in KB

Readme

SKOLID-REACT-NATIVE-SDK

A library for managing a user's session with SkolID in a react native application.

Installation

react-native link react-native-skolid

Android

In MainApplication.java change the instantiation of RNSkolid to include the variable BuildConfig.DEBUG into the constructor parameter useTestAccountType. This makes sure that the correct account type is used depending on the build configuration (Account type: com.ist.home.skolid for release build and com.ist.home.skolid.test for debug build).

Add an intent filter in AndroidManifest.xml with the schema that the application will listen to:

<intent-filter android:label="MyAppName">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="MyScheme" />
</intent-filter>

Add the following string to strings.xml:

<string name="account_name">SkolID</string>

Add an authenticator config for release in src/main/res/xml/authenticator.xml:

<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="com.ist.home.skolid"
    android:icon="@mipmap/ic_launcher"
    android:smallIcon="@mipmap/ic_launcher"
    android:label="@string/account_name"
    />

Add an authenticator config for debug in src/main/res/xml/authenticator_debug.xml:

<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="com.ist.home.skolid.test"
    android:icon="@mipmap/ic_launcher"
    android:smallIcon="@mipmap/ic_launcher"
    android:label="@string/account_name"
    />

Add an service in AndroidManifest.xml that is required for the skolid accounts:

<service
    android:name=".SkolidAccountService"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="android.accounts.AccountAuthenticator" />
    </intent-filter>

    <meta-data android:name="android.accounts.AccountAuthenticator"
        android:resource="@xml/${authenticatorXmlFile}" />
</service>

Insert/merge the following into the build.gradle in the iteration of application variants:

def mergedFlavor = variant.getMergedFlavor()
if (variant.buildType.name.equals("release")) {
    mergedFlavor.manifestPlaceholders = [sharedUserId:"com.ist.home", authenticatorXmlFile: "authenticator"]
} else {
    mergedFlavor.manifestPlaceholders = [sharedUserId:"com.ist.home.test", authenticatorXmlFile: "authenticator_debug"]
}

Set the launchMode to SingleTask in AndroidManifest.xml (android:launchMode="singleTask").

IOS

More info needed.

Usage

Configs

Example configs:

import {LogLevel, AccountConfig, SessionConfig} from "@ist-group/react-native-skolid";

const sessionConfig: SessionConfig = {
  environment: "demo",

  clientId: "cliendId",
  clientSecret: "clientSecret",

  redirectUri: "com.example.app://authcode",
  logLevel: LogLevel.Debug,
  scope: "openid offline_access notification profile skolid.full-access",
};

const accountConfig: AccountConfig = {
  session: sessionConfig,
  logLevel: LogLevel.Debug,

  googleIosClientId: "googleIosClientId",
  googleServerClientId: "googleServerClientId",

  appName: "RideShare",
  appUri: "com.ist.home.rideshare://",
};

Authentication

See dist/core/authentication.d.ts for more information.

Example usage with username and password:

import {authentication} from "@ist-group/react-native-skolid";

const sessionConfig = {} // See above clause for config details.

const someLoginFlow = async () => {
  const session = await authentication.loginUsernamePassword(
    sessionConfig,
    "username", 
    "password"
  );
}

Session storage

Example browser login:

import {sessionStorage} from "@ist-group/react-native-skolid";
const sessionConfig = {} // See above clause for config details.

const someLoginFlow = async () => {
  const session = await sessionStorage.loginBrowser(sessionConfig);
}

To store above session in a persistent manner you can use rememberSession

await sessionStorage.rememberSession(session);

const session = await sessionStorage.recallSession();
if (!session) {
  // None stored
}

And to remove it

await sessionStorage.forgetSession();

Account management

To bind a session to your device ID (iCloud-token on iOS, device user on Android) After associating a session, that session may be restored within this app and other apps that bind with SkolID and are signed by the same keystores.

import {accountManager, sessionStorage} from "@ist-group/react-native-skolid";
const accountConfig = {} // See above clause for config details.


const someLoginFlow = async () => {
  const session = await sessionStorage.loginBrowser(
    accountConfig.session
  );

  await accountManager.associateSessionAndDevice(
    accountConfig,
    session
  );
}

Restoring a session

const accounts = await accountManager.loadAccounts(accountConfig);
if (accounts.length <= 0) {
  // No accounts, login please.
  return null;
}

// This will emit a new session event as well.
const session = await accountManager.loginAccount(accountconfig, accounts[0]);
return session;

Logging out and deassociating a session

// This will emit a logout event.
await accountManager.logout(accountConfig, session);

Events

See dist/events.d.ts for a list of all events and their arguments.

Example usage:

import {events, Event} from "@ist-group/react-native-skolid";

/**
 * This event is emitted from browser logins.
 * It is also used by a sister module (@ist-group/react-native-skolid-ui)
 */
const newSessionCB = events.on(Event.NEW_SESSION, (evt, [session]) => {
  // Do something nice with your new session.
});

/**
 * Any non recoverable error will be transmitted here.
 */
const errorCB = events.on(Event.ERROR, (evt, [err]) => {
  // Oh no, something horrible happened, report it!
});

events.emit(Event.ERROR, [new Error("We sending a message aight."]);
events.remove(Event.NEW_SESSION, newSessionCB)

Using SkolID API

import {
  skolid,
  sessionStorage,
  environments
} from "@ist-group/react-native-skolid";

const sessionConfig = {} // See above clause for config details.
const skolidConfig = environments.getEnvironment(sessionConfig);

const someFlow = async () => {
  const session = await sessionStorage.recallSession();
  const res = await skolid.query(skolidConfig, session, `query {me {id}}`, {})
  console.log("Nice id I've got:", res.data.me.id);
}

Using Famla API

import {
  skolid,
  Famla,
  FamlaConfig,
  sessionStorage,
  environments,
  authentication
} from "@ist-group/react-native-skolid";

const sessionConfig = {} // See above clause for config details.
const skolidConfig = environments.getEnvironment(sessionConfig);

const famlaConfig: FamlaConfig = {
  appName: "application",
  famlaAPIUrl: skolidConfig.notificationApiUrl
}

const secret = genSecret();

// This will send an email with login information
Famla.setupLogin(famlaConfig, {
  email: "user@example.com",
  secret,
  application: famlaConfig.appName,
})

const validateCode = async (code: string) => {
  const loginTicket = await Famla.loginUser(famlaConfig, {
    key: code,
    secret
  });

  const session = await authentication.loginSignInTicket(
    sessionConfig,
    loginTicket
  );
}

Initializing Google SignIn

import {accountManager} from "@ist-group/react-native-skolid";

const accountConfig = {} // See above clause for config details.

// Initialize Google SignIn
accountManager.setGoogleSignIn(accountConfig).then(async () => {
  console.log("Google activated:", accountManager.isGoogleAvailable());

  // This emits a new session.
  const session = await accountManager.loginGoogle(accountConfig);
}).catch(console.error);

Development

Since the react-native packer doesn't work well with symbolic links the yarn link command cannot be used with this library. Instead use the node cpx cli to watch and copy files to the target project when developing:

cpx-linker

To store paths and make copying easier, you can use cpx-linker.

cd project/to/use/react-native-skolid/in
yarn add @ist-group/cpx-linker
yarn cpx-linker --link path/to/react-native-skolid
yarn cpx-linker --copy --watch

Next time you only have to run yarn cpx-linker --copy --watch.

cpx

npm install cpx --global
yarn start
cpx "./{android,dist}/**/_._" ../my-app/node_modules/@ist-group/react-native-skolid --watch --verbose

Or to just copy the js files (if the app already has the latest native module)

cpx "./dist/**/_._" ../my-app/node_modules/@ist-group/react-native-skolid/dist --watch --verbose

Deployment

NPM

Run the following command to deploy a new version to NPM:

yarn publish

If you find any bugs or have a feature request, please open an issue on github!

The npm package download data comes from npm's download counts api and package details come from npms.io.