Skip to content
This repository was archived by the owner on Sep 4, 2024. It is now read-only.

Prevents "Device requesting login is not supported" for Flutter SDKs #32

Merged
merged 5 commits into from
Aug 15, 2023
Merged
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
2 changes: 1 addition & 1 deletion magic_demo/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "link.magic.DemoApp"
minSdkVersion 20
minSdkVersion 23
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
Expand Down
12 changes: 12 additions & 0 deletions magic_demo/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,32 +1,44 @@
PODS:
- agent_dart (1.0.0):
- Flutter
- Flutter (1.0.0)
- flutter_web_auth (0.5.0):
- Flutter
- package_info_plus (0.4.5):
- Flutter
- secp256r1 (0.1.0):
- Flutter
- webview_flutter_wkwebview (0.0.1):
- Flutter

DEPENDENCIES:
- agent_dart (from `.symlinks/plugins/agent_dart/ios`)
- Flutter (from `Flutter`)
- flutter_web_auth (from `.symlinks/plugins/flutter_web_auth/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- secp256r1 (from `.symlinks/plugins/secp256r1/ios`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)

EXTERNAL SOURCES:
agent_dart:
:path: ".symlinks/plugins/agent_dart/ios"
Flutter:
:path: Flutter
flutter_web_auth:
:path: ".symlinks/plugins/flutter_web_auth/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
secp256r1:
:path: ".symlinks/plugins/secp256r1/ios"
webview_flutter_wkwebview:
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"

SPEC CHECKSUMS:
agent_dart: 60b2c0137d382ac8e72defc2a6d8907d94d92bd7
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_web_auth: c25208760459cec375a3c39f6a8759165ca0fa4d
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
secp256r1: c4054eb1aa9e47c266a9c2914e9c8c5dd17b8ffd
webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a

PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
Expand Down
2 changes: 1 addition & 1 deletion magic_demo/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ dependencies:


# Live imports
magic_sdk: ^4.0.0
magic_sdk: ^4.1.0
magic_ext_oauth: ^0.3.4
magic_ext_tezos: ^0.2.2
magic_ext_solana: ^0.3.1
Expand Down
36 changes: 23 additions & 13 deletions packages/magic_sdk/lib/provider/rpc_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import '../../provider/types/relayer_response.dart';
import '../../provider/types/rpc_request.dart';
import '../../relayer/url_builder.dart';
import '../../relayer/webview.dart';
import '../../relayer/types/DPop.dart';

import 'package:web3dart/json_rpc.dart';
import 'package:webview_flutter/webview_flutter.dart';
Expand All @@ -19,22 +20,31 @@ class RpcProvider implements RpcService {

RpcProvider(this._overlay, {this.rpcUrl = ""});

/// Sends message to relayer
Future<JavaScriptMessage> send(
{required MagicRPCRequest request,
required Completer<JavaScriptMessage> completer}) async {
var msgType = OutboundMessageType.MAGIC_HANDLE_REQUEST;
var encodedParams = await URLBuilder.instance.encodedParams;
Future<JavaScriptMessage> send({
required MagicRPCRequest request,
required Completer<JavaScriptMessage> completer,
}) async {
var msgType = OutboundMessageType.MAGIC_HANDLE_REQUEST;
var encodedParams = await URLBuilder.instance.encodedParams;

var relayerRequest = RelayerRequest(
msgType: '${msgType.toString().split('.').last}-$encodedParams',
payload: request);
// Get the JWT value from the createJwt() method
String? jwt = await createJwt();

_overlay.enqueue(
relayerRequest: relayerRequest, id: request.id, completer: completer);
var relayerRequest = RelayerRequest(
msgType: '${msgType.toString().split('.').last}-$encodedParams',
payload: request,
rt: null,
jwt: jwt,
);

return completer.future;
}
_overlay.enqueue(
relayerRequest: relayerRequest,
id: request.id,
completer: completer,
);

return completer.future;
}

/* web3dart wrapper */
@override
Expand Down
4 changes: 3 additions & 1 deletion packages/magic_sdk/lib/provider/types/relayer_request.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ part 'relayer_request.g.dart';
class RelayerRequest<T> {
String msgType;
MagicRPCRequest<T> payload;
String? rt;
String? jwt;

RelayerRequest({required this.msgType, required this.payload});
RelayerRequest({required this.msgType, required this.payload, this.rt, this.jwt});

/// A necessary factory constructor for creating a new User instance
/// from a map. Pass the map to the generated `_$UserFromJson()` constructor.
Expand Down
4 changes: 4 additions & 0 deletions packages/magic_sdk/lib/provider/types/relayer_request.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion packages/magic_sdk/lib/provider/types/relayer_response.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ part 'relayer_response.g.dart';
class RelayerResponse<T> {
String msgType;
MagicRPCResponse<T> response;
String? rt;

RelayerResponse({required this.msgType, required this.response});
RelayerResponse({required this.msgType, required this.response, this.rt});

/// A necessary factory constructor for creating a new User instance
/// from a map. Pass the map to the generated `_$UserFromJson()` constructor.
Expand Down
2 changes: 2 additions & 0 deletions packages/magic_sdk/lib/provider/types/relayer_response.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

76 changes: 76 additions & 0 deletions packages/magic_sdk/lib/relayer/types/DPop.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import 'dart:convert';
import 'dart:typed_data';

import 'package:crypto/crypto.dart';
import 'package:uuid/uuid.dart';
import 'package:secp256r1/secp256r1.dart';

final _alias = "link.magic.auth.dpop";

String base64UrlEncoded(List<int> data) {
var b64 = base64.encode(data);
b64 = b64.replaceAll('+', '-');
b64 = b64.replaceAll('/', '_');
b64 = b64.replaceAll('=', '');
return b64;
}

Future<String?> createJwt() async {
try {
// Get the public key.
final publicKey = await SecureP256.getPublicKey(_alias);

// Get the public key, raw representation.
final rawPublicKey = publicKey.rawKey;

// Extract the x and y coordinates.
final xCoordinateData = rawPublicKey.sublist(1, 33);
final yCoordinateData = rawPublicKey.sublist(33, 65);

// If you need base64-encoded strings for JWK:
final xCoordinateBase64 = base64UrlEncoded(xCoordinateData);
final yCoordinateBase64 = base64UrlEncoded(yCoordinateData);

// Convert the public key to JWK format.
var headers = {
"typ": "dpop+jwt",
"alg": "ES256",
"jwk": {
"kty": "EC",
"crv": "P-256",
"x": xCoordinateBase64,
"y": yCoordinateBase64
}
};

final headersData = utf8.encode(json.encode(headers));
final headersB64 = base64UrlEncoded(headersData);

// construct claims
final iat = DateTime.now().millisecondsSinceEpoch ~/ 1000;
var uuid = Uuid();
final jti = uuid.v4().toLowerCase();

final claims = {
"iat": iat,
"jti": jti
};
final claimsData = utf8.encode(json.encode(claims));
final claimsB64 = base64UrlEncoded(claimsData);

// sign
final signingInput = headersB64 + "." + claimsB64;
final signature = await SecureP256.sign(_alias, Uint8List.fromList(utf8.encode(signingInput)));

final signatureB64 = base64UrlEncoded(signature);

final jwt = signingInput + "." + signatureB64;

return jwt;

} catch (error) {
// handle error
print(error);
return null;
}
}
2 changes: 1 addition & 1 deletion packages/magic_sdk/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: magic_sdk
description: This is your entry-point to secure, passwordless authentication for your iOS or Android-based Flutter app.
version: 4.0.0
version: 4.1.0
homepage: https://magic.link
repository: https://github.com/magiclabs/magic-flutter

Expand Down