Skip to content

Commit

Permalink
feat(app): Fetch supported credential based on type (#658)
Browse files Browse the repository at this point in the history
Signed-off-by: Talwinder kaur <[email protected]>
  • Loading branch information
talwinder kaur authored Nov 6, 2023
1 parent a6718fb commit 04ec4e9
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 90 deletions.
145 changes: 83 additions & 62 deletions demo/app/ios/Runner/flutterPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin {
getIssuerID(arguments: arguments!, result:result)

case "getIssuerMetaData":
getIssuerMetaData(result:result)
getIssuerMetaData(arguments: arguments!, result:result)

case "activityLogger":
storeActivityLogger(result:result)
Expand Down Expand Up @@ -424,13 +424,19 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin {
}
}

public func getIssuerMetaData(result: @escaping FlutterResult) {
public func getIssuerMetaData(arguments: Dictionary<String, Any>, 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."))
}

guard let credentialTypes = arguments["credentialTypes"] as? Array<String> else{
return result(FlutterError.init(code: "NATIVE_ERR",
message: "error while reading credentialTypes",
details: "parameter credential types is missed"))
}

do {

var issuerMetaData = try openID4CI.getIssuerMetadata()
Expand All @@ -439,7 +445,7 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin {

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

// localized issuer displays data
var localizedIssuerDisplays = issuerMetaData.localizedIssuerDisplays()!
Expand All @@ -466,7 +472,7 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin {
]

issuerMetaDataRespList.append(issuerMetaDataResp)

print(issuerMetaDataRespList)
result(issuerMetaDataRespList)

} catch let error as NSError {
Expand All @@ -477,34 +483,39 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin {

}

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

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)
for credType in credentialTypes {
if (credType == type){
typeStrArray.append(type!)
typeStrArray.append("VerifiableCredential")

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)
}
}
}

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

supportedCredentialsList.append(supportedCredentialResp)
}

return supportedCredentialsList
Expand All @@ -516,6 +527,12 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin {
message: "error while reading initializeWalletInitiatedFlow issuer URI",
details: "Pass issuerURI as the arguments"))
}

guard let credentialTypes = arguments["credentialTypes"] as? Array<String> else{
return result(FlutterError.init(code: "NATIVE_ERR",
message: "error while reading credentialTypes",
details: "parameter credential types is missed"))
}

guard let walletSDK = self.walletSDK else{
return result(FlutterError.init(code: "NATIVE_ERR",
Expand All @@ -527,7 +544,7 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin {
let walletInitiatedOpenID4CI = try walletSDK.createOpenID4CIWalletInitiatedInteraction(issuerURI: issuerURI)
let supportedCredentials = try walletInitiatedOpenID4CI.getSupportedCredentials()

var supportedCredentialsList = getSupportedCredentialsList(supportedCredentials: supportedCredentials)
var supportedCredentialsList = getSupportedCredentialsList(supportedCredentials: supportedCredentials, credentialTypes: credentialTypes)

self.walletInitiatedOpenID4CI = walletInitiatedOpenID4CI
result(supportedCredentialsList)
Expand Down Expand Up @@ -767,7 +784,7 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin {


public func resolveCredentialDisplay(arguments: Dictionary<String, Any>, result: @escaping FlutterResult){


guard let resolvedCredentialDisplayData = arguments["resolvedCredentialDisplayData"] as? String else{
return result(FlutterError.init(code: "NATIVE_ERR",
Expand All @@ -780,43 +797,47 @@ public class SwiftWalletSDKPlugin: NSObject, FlutterPlugin {
var resolvedCredDisplayList : [Any] = []
var claimList:[Any] = []


for i in 0...((displayData!.credentialDisplaysLength())-1){
let credentialDisplay = displayData!.credentialDisplay(at: i)!
for i in 0...(credentialDisplay.claimsLength())-1{
let claim = credentialDisplay.claim(at: i)!
var claims : [String: Any] = [:]
if claim.isMasked(){
claims["value"] = claim.value()
claims["rawValue"] = claim.rawValue()
}
var order: Int = -1
if claim.hasOrder() {
do {
try claim.order(&order)
claims["order"] = order
} catch let err as NSError {
print("Error: \(err)")
if(displayData!.credentialDisplaysLength() != 0){
for i in 0...((displayData!.credentialDisplaysLength())-1){
let credentialDisplay = displayData!.credentialDisplay(at: i)!
if(credentialDisplay.claimsLength() != 0){
for i in 0...(credentialDisplay.claimsLength())-1{
let claim = credentialDisplay.claim(at: i)!
var claims : [String: Any] = [:]
if claim.isMasked(){
claims["value"] = claim.value()
claims["rawValue"] = claim.rawValue()
}
var order: Int = -1
if claim.hasOrder() {
do {
try claim.order(&order)
claims["order"] = order
} catch let err as NSError {
print("Error: \(err)")
}
}
claims["rawValue"] = claim.rawValue()
claims["valueType"] = claim.valueType()
claims["label"] = claim.label()
claimList.append(claims)
}
}
claims["rawValue"] = claim.rawValue()
claims["valueType"] = claim.valueType()
claims["label"] = claim.label()
claimList.append(claims)

let overview = credentialDisplay.overview()
let logo = overview?.logo()

var resolveDisplayResp : [String: Any] = [:]
resolveDisplayResp["claims"] = claimList
resolveDisplayResp["overviewName"] = overview?.name()
resolveDisplayResp["logo"] = logo?.url()
resolveDisplayResp["textColor"] = overview?.textColor()
resolveDisplayResp["backgroundColor"] = overview?.backgroundColor()
resolveDisplayResp["issuerName"] = issuerDisplayData?.name()


resolvedCredDisplayList.append(resolveDisplayResp)
}

let overview = credentialDisplay.overview()
let logo = overview?.logo()

var resolveDisplayResp : [String: Any] = [:]
resolveDisplayResp["claims"] = claimList
resolveDisplayResp["overviewName"] = overview?.name()
resolveDisplayResp["logo"] = logo?.url()
resolveDisplayResp["textColor"] = overview?.textColor()
resolveDisplayResp["backgroundColor"] = overview?.backgroundColor()
resolveDisplayResp["issuerName"] = issuerDisplayData!.name()

resolvedCredDisplayList.append(resolveDisplayResp)
}


Expand Down
47 changes: 34 additions & 13 deletions demo/app/lib/scenarios/handle_openid_issuance_flow.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,32 @@ import 'package:app/wallet_sdk/wallet_sdk.dart';
import 'package:flutter/services.dart';
import 'package:app/models/credential_offer.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';

import '../views/custom_error.dart';
import 'package:app/views/custom_error.dart';

void handleOpenIDIssuanceFlow(BuildContext context, String qrCodeURL) async {
var WalletSDKPlugin = WalletSDK();
var authCodeArgs;
if (qrCodeURL.contains('credential_offer_uri')) {
authCodeArgs = await parseCredentialOfferUri(qrCodeURL);
log('credential offer uri auth code $authCodeArgs');
} else 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'
};
} else {
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'
};
}
// Fetching and persisting credential type from credential offer query
await getCredentialType(qrCodeURL);
}

log('qr code url - $qrCodeURL');

Map<Object?, Object?>? flowTypeData;
try {
flowTypeData = await WalletSDKPlugin.initialize(qrCodeURL, authCodeArgs);
Expand Down Expand Up @@ -70,10 +74,27 @@ void handleOpenIDIssuanceFlow(BuildContext context, 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']!);
var credentialsQuery = json.decode(uri.queryParameters['credential_offer']!);
await persistCredentialType(credentialsQuery);
final String response = await rootBundle.loadString('lib/assets/issuerAuthFlowConfig.json');
final configData = await json.decode(response);
return configData[credentialIssuerKey['credential_issuer']];
return configData[credentialsQuery['credential_issuer']];
}

getCredentialType(String qrCodeURL) async {
var decodedUri = Uri.decodeComponent(qrCodeURL);
final uri = Uri.parse(decodedUri);
var credentialsQuery = json.decode(uri.queryParameters['credential_offer']!);
await persistCredentialType(credentialsQuery);
}

persistCredentialType(credentialsQuery) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final value = credentialsQuery['credentials'];
for (var val in value) {
var types = val['types'];
prefs.setStringList('credentialTypes', List<String>.from(types));
}
}

parseCredentialOfferUri(String qrCodeURL) async {
Expand Down
4 changes: 3 additions & 1 deletion demo/app/lib/views/credential_preview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ class CredentialPreviewState extends State<CredentialPreview> {
super.initState();
WalletSDKPlugin.parseCredentialDisplayData(widget.credentialData.credentialDisplayData).then((response) {
setState(() {
issuerDisplayData = response.first.issuerName;
if (response.first.issuerName.isNotEmpty){
issuerDisplayData = response.first.issuerName;
}
});
});

Expand Down
11 changes: 9 additions & 2 deletions demo/app/lib/views/issuance_preview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,15 @@ class IssuancePreviewState extends State<IssuancePreview> {
String textColor = '';
String logoURL = '';
String issuerLogoURL = '';
final Future<SharedPreferences> prefs = SharedPreferences.getInstance();
List<String>? credentialTypes;

@override
void initState() {
super.initState();
WalletSDKPlugin.getIssuerMetaData().then((response) {
prefs.then((value) {
credentialTypes = value.getStringList('credentialTypes');
}).whenComplete(() => WalletSDKPlugin.getIssuerMetaData(credentialTypes!).then((response) {
setState(() {
credentialIssuer = response.first.credentialIssuer;
issuerDisplayName = response.first.localizedIssuerDisplays.first.name;
Expand All @@ -64,7 +68,8 @@ class IssuancePreviewState extends State<IssuancePreview> {
textColor =
'0xff${response.first.supportedCredentials.first.display.first.textColor.toString().replaceAll('#', '')}';
});
});
}),
);
}

@override
Expand Down Expand Up @@ -246,6 +251,8 @@ class IssuancePreviewState extends State<IssuancePreview> {
String? credentials = await WalletSDKPlugin.requestCredential('');
String? issuerURL = await WalletSDKPlugin.issuerURI();
String? resolvedCredentialDisplay = await WalletSDKPlugin.serializeDisplayData([credentials], issuerURL!);
log('resolvedCredentialDisplay $resolvedCredentialDisplay');
resolvedCredentialDisplay = '{"credential_displays":[{"overview":{"name":"Permanent Resident Card","logo":{"url":"https://static.mattr.global/credential-assets/government-of-kakapo/web/logo.svg"},"background_color":"#3a2d2d"}}]}';

var activities = await WalletSDKPlugin.storeActivityLogger();

Expand Down
2 changes: 1 addition & 1 deletion demo/app/lib/views/otp.dart
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ class _OTPPage extends State<OTP> {
String? issuerURI = await WalletSDKPlugin.issuerURI();
serializeDisplayData =
await WalletSDKPlugin.serializeDisplayData([credentials], issuerURI!);
log('serializeDisplayData -> $serializeDisplayData');
log('serializeDisplayData otp-> $serializeDisplayData');
var activities = await WalletSDKPlugin.storeActivityLogger();
var credID = await WalletSDKPlugin.getCredID([credentials]);
log('activities and credID -$activities and $credID');
Expand Down
7 changes: 6 additions & 1 deletion demo/app/lib/views/wallet_initiated_connect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'package:flutter/material.dart';
import 'package:app/widgets/common_title_appbar.dart';
import 'package:app/wallet_sdk/wallet_sdk_mobile.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';

class ConnectIssuerList extends StatefulWidget {
const ConnectIssuerList({Key? key}) : super(key: key);
Expand All @@ -24,12 +25,16 @@ class ConnectIssuerList extends StatefulWidget {

class ConnectIssuerListState extends State<ConnectIssuerList> {
List<ConnectIssuerConfig> connectIssuerConfigList = List.empty(growable: true);
final Future<SharedPreferences> prefs = SharedPreferences.getInstance();

var walletSDKPlugin = WalletSDK();
final ConfigService _configService = ConfigService();
List<String>? credentialTypes;

Future<List<SupportedCredentials>> connect(String issuerURI) async {
return await walletSDKPlugin.initializeWalletInitiatedFlow(issuerURI);
final SharedPreferences pref = await prefs;
credentialTypes = pref.getStringList('credentialTypes');
return await walletSDKPlugin.initializeWalletInitiatedFlow(issuerURI, credentialTypes!);
}

readConnectIssuerConfig() async {
Expand Down
Loading

0 comments on commit 04ec4e9

Please sign in to comment.