Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.authsignal.passkey.AuthsignalPasskey
import com.authsignal.push.AuthsignalPush
import com.authsignal.sms.AuthsignalSMS
import com.authsignal.totp.AuthsignalTOTP
import com.authsignal.whatsapp.AuthsignalWhatsApp
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
Expand All @@ -28,6 +29,7 @@ class AuthsignalPlugin: FlutterPlugin, ActivityAware, MethodCallHandler {
private lateinit var email: AuthsignalEmail
private lateinit var sms: AuthsignalSMS
private lateinit var totp: AuthsignalTOTP
private lateinit var whatsapp: AuthsignalWhatsApp

private var activity: Activity? = null
private var context: Context? = null
Expand All @@ -54,6 +56,7 @@ class AuthsignalPlugin: FlutterPlugin, ActivityAware, MethodCallHandler {
email = AuthsignalEmail(tenantID, baseURL)
sms = AuthsignalSMS(tenantID, baseURL)
totp = AuthsignalTOTP(tenantID, baseURL)
whatsapp = AuthsignalWhatsApp(tenantID, baseURL)

result.success(null)
}
Expand Down Expand Up @@ -309,6 +312,38 @@ class AuthsignalPlugin: FlutterPlugin, ActivityAware, MethodCallHandler {
}
}

"whatsapp.challenge" -> {
coroutineScope.launch {
val response = whatsapp.challenge()

handleResponse(response, result)?.let {
val data = mapOf(
"challengeId" to it.challengeId,
)

result.success(data)
}
}
}

"whatsapp.verify" -> {
val code = call.argument<String>("code")!!

coroutineScope.launch {
val response = whatsapp.verify(code)

handleResponse(response, result)?.let {
val data = mapOf(
"isVerified" to it.isVerified,
"token" to it.token,
"failureReason" to it.failureReason,
)

result.success(data)
}
}
}

"setToken" -> {
val token = call.argument<String>("token")!!

Expand Down
39 changes: 39 additions & 0 deletions ios/Classes/AuthsignalPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public class AuthsignalPlugin: NSObject, FlutterPlugin {
var email: AuthsignalEmail?
var sms: AuthsignalSMS?
var totp: AuthsignalTOTP?
var whatsapp: AuthsignalWhatsApp?

public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "authsignal", binaryMessenger: registrar.messenger())
Expand All @@ -29,6 +30,7 @@ public class AuthsignalPlugin: NSObject, FlutterPlugin {
self.email = AuthsignalEmail(tenantID: tenantID, baseURL: baseURL)
self.sms = AuthsignalSMS(tenantID: tenantID, baseURL: baseURL)
self.totp = AuthsignalTOTP(tenantID: tenantID, baseURL: baseURL)
self.whatsapp = AuthsignalWhatsApp(tenantID: tenantID, baseURL: baseURL)

result(nil)

Expand Down Expand Up @@ -341,6 +343,43 @@ public class AuthsignalPlugin: NSObject, FlutterPlugin {
result(verifyResponse)
}
}

case "whatsapp.challenge":
Task.init {
let response = await self.whatsapp!.challenge()

if response.error != nil {
let error = FlutterError(code: response.errorCode ?? "unexpected_error", message: response.error, details: "");
result(error)
} else {
let challengeResponse: [String: Any?] = [
"challengeId": response.data!.challengeId,
]

result(challengeResponse)
}
}

case "whatsapp.verify":
let arguments = call.arguments as! [String: Any]
let code = arguments["code"] as! String

Task.init {
let response = await self.whatsapp!.verify(code: code)

if response.error != nil {
let error = FlutterError(code: response.errorCode ?? "unexpected_error", message: response.error, details: "");
result(error)
} else {
let verifyResponse: [String: Any?] = [
"isVerified": response.data!.isVerified,
"token": response.data!.token,
"failureReason": response.data!.failureReason,
]

result(verifyResponse)
}
}

case "setToken":
let arguments = call.arguments as! [String: Any]
Expand Down
3 changes: 3 additions & 0 deletions lib/authsignal_flutter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'src/authsignal_push.dart';
import 'src/authsignal_email.dart';
import 'src/authsignal_sms.dart';
import 'src/authsignal_totp.dart';
import 'src/authsignal_whatsapp.dart';

export 'src/types.dart' show AuthsignalResponse, TokenPayload, ErrorCode;

Expand All @@ -18,6 +19,7 @@ class Authsignal {
late AuthsignalEmail email;
late AuthsignalSms sms;
late AuthsignalTotp totp;
late AuthsignalWhatsapp whatsapp;

bool _initialized = false;

Expand All @@ -27,6 +29,7 @@ class Authsignal {
email = AuthsignalEmail(initCheck: initCheck);
sms = AuthsignalSms(initCheck: initCheck);
totp = AuthsignalTotp(initCheck: initCheck);
whatsapp = AuthsignalWhatsapp(initCheck: initCheck);
}

Future<void> initCheck() async {
Expand Down
47 changes: 47 additions & 0 deletions lib/src/authsignal_whatsapp.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

import 'types.dart';

class AuthsignalWhatsapp {
final AsyncCallback initCheck;

AuthsignalWhatsapp({required this.initCheck});

@visibleForTesting
final methodChannel = const MethodChannel('authsignal');

Future<AuthsignalResponse<ChallengeResponse>> challenge() async {
await initCheck();

try {
final data = await methodChannel.invokeMapMethod<String, dynamic>('whatsapp.challenge');

if (data != null) {
return AuthsignalResponse(data: ChallengeResponse.fromMap(data));
} else {
return AuthsignalResponse(data: null);
}
} on PlatformException catch (ex) {
return AuthsignalResponse.fromError(ex);
}
}

Future<AuthsignalResponse<VerifyResponse>> verify(String code) async {
await initCheck();

var arguments = <String, dynamic>{'code': code};

try {
final data = await methodChannel.invokeMapMethod<String, dynamic>('whatsapp.verify', arguments);

if (data != null) {
return AuthsignalResponse(data: VerifyResponse.fromMap(data));
} else {
return AuthsignalResponse(data: null);
}
} on PlatformException catch (ex) {
return AuthsignalResponse.fromError(ex);
}
}
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: authsignal_flutter
description: "The Authsignal Flutter SDK for Passkeys and Push Auth"
version: 1.1.3
version: 1.2.0
homepage: "https://github.com/authsignal/authsignal-flutter"

environment:
Expand Down