Skip to content

Commit

Permalink
Merge pull request #8 from Keyri-Co/feature/login_and_register_methods
Browse files Browse the repository at this point in the history
Feature/login and register methods
  • Loading branch information
AndrewKuliahin96 authored Jan 10, 2024
2 parents b774a60 + 163c6e5 commit 6c354df
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 38 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ Keyri.getAssociationKey('kuliahin.andrew@gmail.com')
});
```

### Enable QR Auth
### Keyri QR Auth

QR Auth can be enabled with a single function call. This process handles scanning the code, generating the session info,
QR Auth can be processed by Keyri with a single function call. This process handles scanning the code, generating the session info,
displaying a confirmation screen to the user, and, if the user confirms, sending the encrypted payload you provide to
the Keyri widget in your browser.

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "0.1.4",
"version": "0.2.0",
"name": "@keyri/cordova-keyri",
"cordova_name": "Cordova Keyri Plugin",
"description": "Cordova Keyri SDK Plugin for QR login",
Expand Down Expand Up @@ -34,7 +34,7 @@
"license": "MIT",
"engines": {
"cordovaDependencies": {
"1.0.0": {
"0.2.0": {
"cordova": ">=11.0.0",
"cordova-android": ">=11.0.0"
}
Expand Down
12 changes: 7 additions & 5 deletions plugin.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
id="cordova-keyri"
version="0.1.4">
version="0.2.0">

<name>CordovaKeyri</name>
<description>Cordova Keyri SDK Plugin</description>
<keywords>authentication, qr-login, passwordless, multifactor-authentication, mobile-authentication, ecosystem:cordova, cordova-android, cordova, camera, cordova-ios</keywords>
<keywords>authentication, qr-login, passwordless, multifactor-authentication, mobile-authentication,
ecosystem:cordova, cordova-android, cordova, camera, cordova-ios
</keywords>
<license>MIT</license>

<engines>
Expand All @@ -20,8 +22,8 @@
<js-module src="dist/types.js" name="types"/>

<platform name="android">
<framework src="com.keyri:keyrisdk:4.0.2"/>
<framework src="com.keyri:scanner:4.0.2"/>
<framework src="com.keyri:keyrisdk:4.1.1"/>
<framework src="com.keyri:scanner:4.1.1"/>
<framework src="com.google.code.gson:gson:2.10.1"/>

<source-file src="src/android/com/keyri/cordova/plugin/CordovaKeyri.kt"
Expand Down Expand Up @@ -52,7 +54,7 @@
<source url="https://github.com/CocoaPods/Specs.git"/>
</config>
<pods use-frameworks="true">
<pod name="keyri-pod" spec="~> 4.2.5"/>
<pod name="keyri-pod" spec="~> 4.4.1"/>
</pods>
</podspec>
</platform>
Expand Down
81 changes: 57 additions & 24 deletions src/android/com/keyri/cordova/plugin/CordovaKeyri.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import android.content.Intent
import androidx.fragment.app.FragmentActivity
import com.keyrico.keyrisdk.Keyri
import com.keyrico.keyrisdk.entity.session.Session
import com.keyrico.keyrisdk.sec.fingerprint.enums.EventType
import com.keyrico.keyrisdk.sec.fraud.enums.EventType
import com.google.gson.Gson
import org.apache.cordova.CallbackContext
import org.apache.cordova.CordovaPlugin
Expand All @@ -17,6 +17,7 @@ import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import com.keyrico.scanner.easyKeyriAuth

class CordovaKeyri : CordovaPlugin() {

Expand Down Expand Up @@ -88,7 +89,7 @@ class CordovaKeyri : CordovaPlugin() {
"sendEvent" -> {
val publicUserId = arguments?.getString(0)
val eventType = arguments?.getString(1)
val success = arguments?.getBoolean(2)
val success = arguments?.getBoolean(2) ?: true

sendEvent(publicUserId, eventType, success, callbackContext)
}
Expand All @@ -100,6 +101,18 @@ class CordovaKeyri : CordovaPlugin() {
initiateQrSession(sessionId, publicUserId, callbackContext)
}

"login" -> {
val publicUserId = arguments?.getString(0)

login(publicUserId, callbackContext)
}

"register" -> {
val publicUserId = arguments?.getString(0)

register(publicUserId, callbackContext)
}

"initializeDefaultConfirmationScreen" -> {
val payload = arguments?.getString(1)

Expand All @@ -116,7 +129,7 @@ class CordovaKeyri : CordovaPlugin() {

"confirmSession" -> {
val payload = arguments?.getString(0)
val trustNewBrowser = arguments?.getString(1)
val trustNewBrowser = arguments?.getBoolean(1) ?: false

confirmSession(payload, trustNewBrowser, callbackContext)
}
Expand Down Expand Up @@ -194,7 +207,7 @@ class CordovaKeyri : CordovaPlugin() {
}

private fun generateAssociationKey(publicUserId: String?, callback: CallbackContext) {
keyriCoroutineScope(callback::error).launch {
keyriCoroutineScope(callback).launch {
val associationKey = publicUserId?.let {
keyri.generateAssociationKey(publicUserId).getOrThrow()
} ?: keyri.generateAssociationKey().getOrThrow()
Expand All @@ -204,7 +217,7 @@ class CordovaKeyri : CordovaPlugin() {
}

private fun generateUserSignature(publicUserId: String?, data: String?, callback: CallbackContext) {
keyriCoroutineScope(callback::error).launch {
keyriCoroutineScope(callback).launch {
if (data == null) {
callback.error("generateUserSignature, data must not be null")
} else {
Expand All @@ -218,7 +231,7 @@ class CordovaKeyri : CordovaPlugin() {
}

private fun listAssociationKeys(callback: CallbackContext) {
keyriCoroutineScope(callback::error).launch {
keyriCoroutineScope(callback).launch {
val keys = keyri.listAssociationKeys().getOrThrow()
val resultArray = JSONArray()

Expand All @@ -235,7 +248,7 @@ class CordovaKeyri : CordovaPlugin() {
}

private fun listUniqueAccounts(callback: CallbackContext) {
keyriCoroutineScope(callback::error).launch {
keyriCoroutineScope(callback).launch {
val keys = keyri.listUniqueAccounts().getOrThrow()
val resultArray = JSONArray()

Expand All @@ -252,7 +265,7 @@ class CordovaKeyri : CordovaPlugin() {
}

private fun getAssociationKey(publicUserId: String?, callback: CallbackContext) {
keyriCoroutineScope(callback::error).launch {
keyriCoroutineScope(callback).launch {
val associationKey = publicUserId?.let {
keyri.getAssociationKey(publicUserId).getOrThrow()
} ?: keyri.getAssociationKey().getOrThrow()
Expand All @@ -262,7 +275,7 @@ class CordovaKeyri : CordovaPlugin() {
}

private fun removeAssociationKey(publicUserId: String?, callback: CallbackContext) {
keyriCoroutineScope(callback::error).launch {
keyriCoroutineScope(callback).launch {
if (publicUserId == null) {
callback.error("removeAssociationKey, publicUserId must not be null")
} else {
Expand All @@ -273,7 +286,7 @@ class CordovaKeyri : CordovaPlugin() {
}

private fun sendEvent(publicUserId: String?, eventType: String?, success: Boolean, callback: CallbackContext) {
keyriCoroutineScope(callback::error).launch {
keyriCoroutineScope(callback).launch {
val type = EventType.values().firstOrNull { it.type == eventType }

if (type == null) {
Expand All @@ -291,7 +304,7 @@ class CordovaKeyri : CordovaPlugin() {
}

private fun initiateQrSession(sessionId: String?, publicUserId: String?, callback: CallbackContext) {
keyriCoroutineScope(callback::error).launch {
keyriCoroutineScope(callback).launch {
if (sessionId == null) {
callback.error("initiateQrSession, sessionId must not be null")
} else {
Expand All @@ -306,16 +319,36 @@ class CordovaKeyri : CordovaPlugin() {
}
}

private fun login(publicUserId: String?, callback: CallbackContext) {
keyriCoroutineScope(callback).launch {
keyri.login(publicUserId).onSuccess { loginObject ->
callback.success(JSONObject(Gson().toJson(loginObject)))
}.onFailure {
callback.error("login, ${it.message}")
}
}
}

private fun register(publicUserId: String?, callback: CallbackContext) {
keyriCoroutineScope(callback).launch {
keyri.register(publicUserId).onSuccess { registerObject ->
callback.success(JSONObject(Gson().toJson(registerObject)))
}.onFailure {
callback.error("register, ${it.message}")
}
}
}

private fun initializeDefaultConfirmationScreen(payload: String?, callback: CallbackContext) {
keyriCoroutineScope(callback::error).launch {
keyriCoroutineScope(callback).launch {
if (activeSession == null) {
callback.error("initializeDefaultConfirmationScreen, can't find session")
} else if (payload == null) {
callback.error("initializeDefaultConfirmationScreen, payload must not be null")
} else {
(cordova.getActivity() as? FragmentActivity)?.supportFragmentManager?.let { fm ->
keyri.initializeDefaultConfirmationScreen(fm, activeSession, payload).onSuccess { authResult ->
callback.success(authResult)
keyri.initializeDefaultConfirmationScreen(fm, requireNotNull(activeSession), payload).onSuccess { authResult ->
callback.success()
}.onFailure {
callback.error("initializeDefaultConfirmationScreen, ${it.message}")
}
Expand All @@ -325,15 +358,15 @@ class CordovaKeyri : CordovaPlugin() {
}

private fun processLink(link: String?, payload: String?, publicUserId: String?, callback: CallbackContext) {
keyriCoroutineScope(callback::error).launch {
keyriCoroutineScope(callback).launch {
if (link == null) {
callback.error("processLink, link must not be null")
} else if (payload == null) {
callback.error("processLink, payload must not be null")
} else {
(cordova.getActivity() as? FragmentActivity)?.supportFragmentManager?.let { fm ->
keyri.processLink(fm, Uri.parse(link), payload, publicUserId).onSuccess { authResult ->
callback.success(authResult)
callback.success()
}.onFailure {
callback.error("processLink, ${it.message}")
}
Expand All @@ -343,40 +376,40 @@ class CordovaKeyri : CordovaPlugin() {
}

private fun confirmSession(payload: String?, trustNewBrowser: Boolean, callback: CallbackContext) {
keyriCoroutineScope(callback::error).launch {
keyriCoroutineScope(callback).launch {
if (activeSession == null) {
callback.error("confirmSession, can't find session")
} else if (payload == null) {
callback.error("confirmSession, payload must not be null")
} else {
activeSession.confirm(payload, requireNotNull(cordova.getActivity()), trustNewBrowser).onSuccess {
activeSession?.confirm(payload, requireNotNull(cordova.getActivity()), trustNewBrowser)?.onSuccess {
callback.success()
}.onFailure {
}?.onFailure {
callback.error("confirmSession, ${it.message}")
}
}
}
}

private fun denySession(payload: String?, callback: CallbackContext) {
keyriCoroutineScope(callback::error).launch {
keyriCoroutineScope(callback).launch {
if (activeSession == null) {
callback.error("denySession, can't find session")
} else if (payload == null) {
callback.error("denySession, payload must not be null")
} else {
activeSession.deny(payload, requireNotNull(cordova.getActivity())).onSuccess {
activeSession?.deny(payload, requireNotNull(cordova.getActivity()))?.onSuccess {
callback.success()
}.onFailure {
}?.onFailure {
callback.error("denySession, ${it.message}")
}
}
}
}

private fun keyriCoroutineScope(errorCallback: (e: Throwable) -> Unit): CoroutineScope {
private fun keyriCoroutineScope(callback: CallbackContext): CoroutineScope {
val exceptionHandler = CoroutineExceptionHandler { _, e ->
errorCallback(e.message ?: "Error calling this method")
callback.error(e.message ?: "Error calling this method")
}

return CoroutineScope(Dispatchers.IO + exceptionHandler)
Expand Down
28 changes: 28 additions & 0 deletions src/iOS/com/keyri/cordova/plugin/CordovaKeyri.swift
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,34 @@ import Keyri
} ?? sendIsNotInitialized(methodName: "initiateQrSession", command: command)
}

@objc(login:)
func login(command: CDVInvokedUrlCommand) {
let publicUserId = command.arguments[1] as? String

keyri?.login(publicUserId: publicUserId) { result in
switch result {
case .success(let loginObject):
self.processResult(message: loginObject.asDictionary(), command: command)
case .failure(let error):
self.processError(error: error, command: command)
}
} ?? sendIsNotInitialized(methodName: "login", command: command)
}

@objc(register:)
func register(command: CDVInvokedUrlCommand) {
let publicUserId = command.arguments[1] as? String

keyri?.register(publicUserId: publicUserId) { result in
switch result {
case .success(let registerObject):
self.processResult(message: registerObject.asDictionary(), command: command)
case .failure(let error):
self.processError(error: error, command: command)
}
} ?? sendIsNotInitialized(methodName: "register", command: command)
}

@objc(initializeDefaultConfirmationScreen:)
func initializeDefaultConfirmationScreen(command: CDVInvokedUrlCommand) {
guard let session = activeSession else {
Expand Down
16 changes: 11 additions & 5 deletions www/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type {
ProcessLinkOptions,
InitializeKeyriOptions,
SendEventOptions,
SendEventOptions, LoginObject, RegisterObject,
} from './types';
import {KeyriFingerprintEventResponse, KeyriSession} from "./types";

Expand Down Expand Up @@ -31,11 +31,11 @@ export class CordovaKeyriPlugin {
return asPromise('generateUserSignature', [publicUserId, data]);
};

listAssociationKeys(): Promise<string[]> {
listAssociationKeys(): Promise<Map<string, string>> {
return asPromise('listAssociationKeys');
};

listUniqueAccounts(): Promise<string[]> {
listUniqueAccounts(): Promise<Map<string, string>> {
return asPromise('listUniqueAccounts');
};

Expand All @@ -55,6 +55,14 @@ export class CordovaKeyriPlugin {
return asPromise('initiateQrSession', [sessionId, publicUserId]);
};

login(publicUserId?: string): Promise<LoginObject> {
return asPromise('login', [publicUserId]);
};

register(publicUserId?: string): Promise<RegisterObject> {
return asPromise('register', [publicUserId]);
};

initializeDefaultConfirmationScreen(payload: string): Promise<boolean> {
return asPromise('initializeDefaultConfirmationScreen', [payload]);
};
Expand Down Expand Up @@ -85,5 +93,3 @@ if (!window.plugins) {
if (!window.plugins.CordovaKeyri) {
window.plugins.CordovaKeyri = CordovaKeyri;
}

export default CordovaKeyri;
12 changes: 12 additions & 0 deletions www/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ export interface KeyriSession {
mobileTemplateResponse?: KeyriMobileTemplateResponse;
}

export interface LoginObject {
timestampNonce: string,
signature: string,
publicKey: string,
userId: string,
}

export interface RegisterObject {
publicKey: string,
userId: string,
}

export interface KeyriFingerprintEventResponse {
apiCiphertextSignature: string;
publicEncryptionKey: string;
Expand Down

0 comments on commit 6c354df

Please sign in to comment.