Skip to content

Commit

Permalink
feat(app): Implement issuance preview screen ios
Browse files Browse the repository at this point in the history
Signed-off-by: Talwinder kaur <[email protected]>
  • Loading branch information
Talwinder kaur committed Aug 3, 2023
1 parent fe4a68a commit e6942a8
Show file tree
Hide file tree
Showing 9 changed files with 565 additions and 137 deletions.
2 changes: 1 addition & 1 deletion demo/app/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ SPEC CHECKSUMS:
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
integration_test: 13825b8a9334a850581300559b8839134b124670
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
safe_device: 4539eb6bdbeb4b61a763a51c4e73e6b37dea4e3d
Expand Down
7 changes: 7 additions & 0 deletions demo/app/ios/Runner/OpenID4CI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,11 @@ public class OpenID4CI {
func getAuthorizationCodeGrantParams() throws -> Openid4ciAuthorizationCodeGrantParams {
return try initiatedInteraction.authorizationCodeGrantParams()
}

// Not doing locale handling or text color handling etc.
func getIssuerMetadata() throws -> Openid4ciIssuerMetadata {
return try initiatedInteraction.issuerMetadata()
}


}
101 changes: 87 additions & 14 deletions demo/app/ios/Runner/flutterPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin {
case "getIssuerID":
getIssuerID(arguments: arguments!, result:result)

case "getIssuerMetaData":
getIssuerMetaData(result:result)

case "activityLogger":
storeActivityLogger(result:result)

Expand Down Expand Up @@ -404,6 +407,88 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin {
}
}

public func getIssuerMetaData(result: @escaping FlutterResult) {
guard let openID4CI = self.openID4CI else{
return result(FlutterError.init(code: "NATIVE_ERR",
message: "error while getting issuer meta data",
details: "openID4CI not initiated. Call authorize before this."))
}

do {

var issuerMetaData = try openID4CI.getIssuerMetadata()
// creddential issuer
var credIssuer = issuerMetaData.credentialIssuer()

// supported Credentials list
var supportedCredentials = issuerMetaData.supportedCredentials()!
var supportedCredentialsList = getSupportedCredentialsList(supportedCredentials: supportedCredentials)

// localized issuer displays data
var localizedIssuerDisplays = issuerMetaData.localizedIssuerDisplays()!
var localizedIssuerDisplayList :[Any] = []
for index in 0..<localizedIssuerDisplays.length() {
let localizedIssuerDisplay :[String:Any] = [
"name": localizedIssuerDisplays.atIndex(index)!.name(),
"locale": localizedIssuerDisplays.atIndex(index)!.locale(),
]

localizedIssuerDisplayList.append(localizedIssuerDisplay)
}


var issuerMetaDataRespList: [Any] = []
let issuerMetaDataResp:[String:Any] = [
"credentialIssuer": credIssuer,
"supportedCredentials" : supportedCredentialsList,
"localizedIssuerDisplays":localizedIssuerDisplayList
]

issuerMetaDataRespList.append(issuerMetaDataResp)

result(issuerMetaDataRespList)

} catch {
result(FlutterError.init(code: "NATIVE_ERR",
message: "error while getting issuer meta data",
details: error))
}

}

public func getSupportedCredentialsList(supportedCredentials: Openid4ciSupportedCredentials) -> [Any] {
var supportedCredentialsList: [Any] = []
for index in 0..<supportedCredentials.length() {
var typeStrArray = [String]()
for i in 0..<(supportedCredentials.atIndex(index)!.types()?.length())!{
let type1 = supportedCredentials.atIndex(index)!.types()?.atIndex(i)
typeStrArray.append(type1!)
}

var localizedCredentialsDisplayRespList: [Any] = []
for i in 0..<(supportedCredentials.atIndex(index)!.localizedDisplays()?.length())!{
let localizedCredentialsDisplayResp :[String:Any] = [
"name": supportedCredentials.atIndex(index)!.localizedDisplays()!.atIndex(i)!.name(),
"locale": supportedCredentials.atIndex(index)!.localizedDisplays()!.atIndex(i)!.locale(),
"logo": supportedCredentials.atIndex(index)!.localizedDisplays()!.atIndex(i)!.logo()!.url(),
"textColor": supportedCredentials.atIndex(index)!.localizedDisplays()!.atIndex(i)!.textColor(),
"backgroundColor": supportedCredentials.atIndex(index)!.localizedDisplays()!.atIndex(i)!.backgroundColor()
]
localizedCredentialsDisplayRespList.append(localizedCredentialsDisplayResp)
}

let supportedCredentialResp:[String:Any] = [
"format": supportedCredentials.atIndex(index)!.format(),
"types": typeStrArray,
"display": localizedCredentialsDisplayRespList
]

supportedCredentialsList.append(supportedCredentialResp)
}

return supportedCredentialsList
}

public func initializeWalletInitiatedFlow(arguments: Dictionary<String, Any>, result: @escaping FlutterResult){
guard let issuerURI = arguments["issuerURI"] as? String else {
return result(FlutterError.init(code: "NATIVE_ERR",
Expand All @@ -422,20 +507,8 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin {
let walletInitiatedOpenID4CI = try walletSDK.createOpenID4CIWalletIntiatedInteraction(issuerURI: issuerURI)
let supportedCredentials = try walletInitiatedOpenID4CI.getSupportedCredentials()

var supportedCredentialsList: [Any] = []
for index in 0..<supportedCredentials.length() {
var typeStrArray = [String]()
for i in 0..<(supportedCredentials.atIndex(index)!.types()?.length())!{
let type1 = supportedCredentials.atIndex(index)!.types()?.atIndex(i)
typeStrArray.append(type1!)
}

let supportedCredentialResp:[String:Any] = [
"format": supportedCredentials.atIndex(index)!.format(),
"types": typeStrArray
]
supportedCredentialsList.append(supportedCredentialResp)
}
var supportedCredentialsList = getSupportedCredentialsList(supportedCredentials: supportedCredentials)

self.walletInitiatedOpenID4CI = walletInitiatedOpenID4CI
result(supportedCredentialsList)

Expand Down
84 changes: 17 additions & 67 deletions demo/app/lib/scenarios/handle_openid_issuance_flow.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ SPDX-License-Identifier: Apache-2.0

import 'dart:convert';
import 'dart:developer';
import 'dart:ffi';
import 'package:app/views/issuance_preview.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:app/wallet_sdk/wallet_sdk.dart';
Expand All @@ -25,22 +27,19 @@ void handleOpenIDIssuanceFlow(BuildContext context, String qrCodeURL) async {
final StorageService storageService = StorageService();
final Future<SharedPreferences> prefs = SharedPreferences.getInstance();
var authCodeArgs;
if (qrCodeURL.contains("credential_offer_uri")){
if (qrCodeURL.contains("credential_offer_uri")) {
authCodeArgs = await parseCredentialOfferUri(qrCodeURL);
log("credential offer uri auth code ${authCodeArgs}");
} else {
if (qrCodeURL.contains("authorization_code")){
if (qrCodeURL.contains("authorization_code")) {
authCodeArgs = await readIssuerAuthFlowConfig(qrCodeURL);
log("auth code arguments fetched from config file $authCodeArgs");
// While fetching auth code args based on issuer key from file, if no key-value pair is found then set the
// arguments to default scope and redirect url.
authCodeArgs ??= {
"scopes": [
"openid",
"profile"
],
"redirectURI": "trustbloc-wallet://openid4vci/authcodeflow/callback"
};
"scopes": ["openid", "profile"],
"redirectURI": "trustbloc-wallet://openid4vci/authcodeflow/callback"
};
}
}

Expand All @@ -50,21 +49,21 @@ void handleOpenIDIssuanceFlow(BuildContext context, String qrCodeURL) async {
var authorizeResultPinRequired = responseJson["pinRequired"];
log("pin required flow - $authorizeResultPinRequired");
if (authorizeResultPinRequired == true) {
navigateToOTPScreen(context);
navigateToIssuancePreviewScreen(context, authorizeResultPinRequired);
return;
} else if (responseJson["authorizationURLLink"] != '') {
// initiate authCode Flow
log("initiating authCode Flow- ${responseJson["authorizationURLLink"]}");
Uri uri = Uri.parse(responseJson["authorizationURLLink"]);
navigateToAuthFlow(context, uri);
navigateToIssuancePreviewScreenAuthFlow(context, uri);
return;
} else {
navigateToWithoutPinFlow(context);
navigateToIssuancePreviewScreen(context, authorizeResultPinRequired);
return;
}
}

readIssuerAuthFlowConfig(String qrCodeURL) async {
readIssuerAuthFlowConfig(String qrCodeURL) async {
var decodedUri = Uri.decodeComponent(qrCodeURL);
final uri = Uri.parse(decodedUri);
var credentialIssuerKey = json.decode(uri.queryParameters["credential_offer"]!);
Expand All @@ -76,8 +75,7 @@ void handleOpenIDIssuanceFlow(BuildContext context, String qrCodeURL) async {
parseCredentialOfferUri(String qrCodeURL) async {
var decodedUri = Uri.decodeComponent(qrCodeURL);
final uri = Uri.parse(decodedUri);
final response = await http
.get(Uri.parse(uri.queryParameters['credential_offer_uri']!));
final response = await http.get(Uri.parse(uri.queryParameters['credential_offer_uri']!));
if (response.statusCode == 200) {
final String configResp = await rootBundle.loadString('lib/assets/issuerAuthFlowConfig.json');
final configData = await json.decode(configResp);
Expand All @@ -88,59 +86,11 @@ parseCredentialOfferUri(String qrCodeURL) async {
}
}

void navigateToWithoutPinFlow(BuildContext context) async{
final Future<SharedPreferences> prefs = SharedPreferences.getInstance();
var WalletSDKPlugin = WalletSDK();
final StorageService storageService = StorageService();
final SharedPreferences pref = await prefs;

var didType = pref.getString('didType');
var keyType = pref.getString('keyType');
// choosing default if no selection is made
didType = didType ?? "ion";
keyType = keyType ?? "ED25519";

var didResolution = await WalletSDKPlugin.createDID(didType, keyType);
var didDocEncoded = json.encode(didResolution);
Map<String, dynamic> responseJson = json.decode(didDocEncoded);

var didID = responseJson["did"];
var didDoc = responseJson["didDoc"];
log("created didID :$didID");
pref.setString('userDID',didID);
pref.setString('userDIDDoc',didDoc);

String? credentials = await WalletSDKPlugin.requestCredential('');
String? issuerURL = await WalletSDKPlugin.issuerURI();
String? resolvedCredentialDisplay = await WalletSDKPlugin.serializeDisplayData([credentials],issuerURL!);

var activities = await WalletSDKPlugin.storeActivityLogger();

var credID = await WalletSDKPlugin.getCredID([credentials]);

log("activities and credID handle open id -$activities and $credID");
storageService.addActivities(ActivityDataObj(credID!, activities));

navigateToCredPreviewScreen(context, credentials, issuerURL, resolvedCredentialDisplay!, didID, credID);
void navigateToIssuancePreviewScreen(BuildContext context, bool? authorizeResultPinRequired) async {
Navigator.push(context,
MaterialPageRoute(builder: (context) => IssuancePreview(authorizeResultPinRequired: authorizeResultPinRequired)));
}

void navigateToOTPScreen(BuildContext context) async {
Navigator.push(context, MaterialPageRoute(builder: (context) => const OTP()));
void navigateToIssuancePreviewScreenAuthFlow(BuildContext context, Uri uri) async {
Navigator.push(context, MaterialPageRoute(builder: (context) => IssuancePreview(uri: uri)));
}

navigateToCredPreviewScreen(
BuildContext context, String credentialResp, String issuerURL, String resolvedCredentialDisplay, String didID, String credID) async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CredentialPreview(credentialData: CredentialData(rawCredential: credentialResp, issuerURL: issuerURL, credentialDisplayData: resolvedCredentialDisplay, credentialDID: didID, credID: credID)),));
}


void navigateToAuthFlow(BuildContext context, Uri uri) async {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => HandleRedirectUri(uri, "issuer-initiated-flow", "")
));
}
Loading

0 comments on commit e6942a8

Please sign in to comment.