How can I implement a custom challenge handler in Xamarin for iOS using IBM MobileFirst? - ios

I'm trying to implement an adapter-based authentication using IBM MobileFirst Platform Foundation 6.3 and Xamarin in iOS.
I have followed the IBM documentation on how to setup a customSecurityTest, adding realms and equivalent loginModules within authenticationConfig.xml. I have then setup 2 adapter procedures:
authenticateUser with securityTest="wl_unprotected", and another
HelloFromServer with a securityTest="SingleStepAuthAdapter" that actually does a user authentication, and executing WL.Server.setActiveUser("SingleStepAuthRealm", userIdentity) to create the user identity.
I have then created an iOS app using Xamarin Studio. Tried to invoke HelloFromServer, which as expected runs my ChallengeHandler module BUT within the HandleChallenge method while trying to invoke the authenticateUser procedure on the server, it respond back with another authRequired=TRUE.
Anybody having the same problem?

You did not provide any useful implementation code that can be inspected for errors - add both the adapter authentication implementation as well as the client-side code of the challenge handler.
While I have no experience with Xamarin, it should be noted that in order to get started you could:
Use the same exact implementation as done in the Adapter-based authentication tutorial. That is, the implementation in the adapter files, project configuration and so on.
Follow through the native iOS implementation, also based on the tutorial
The MFP Studio project and the native iOS project can be downloaded from here.

If you are repeatedly getting back authRequired=true, it looks like you are not notifying the server of the success from your HandleChallenge function. You can refer to the CustomChallengeHandler.cs provided with the sample that is shipped with the component. This is coded to handle a form-based challenge. You can modify it to handle an realm for adapter-based authentication.
So, here are the changes you need to do
1) You should implement the GetAdapterAuthenticationParameters method in your ChallengeHandler class.
For example,
public AdapterAuthenticationInfo AdapterAuthenticationParameters = new AdapterAuthenticationInfo();
....
public override AdapterAuthenticationInfo GetAdapterAuthenticationParameters ()
{
return AdapterAuthenticationParameters;
}
2) In the HandleChallenge function of your ChallengeHandler class, set the isAuthRequired = true. For example,
if (challenge.ResponseJSON["authRequired"] == true)
{
WorklightProcedureInvocationData invocationData = new WorklightProcedureInvocationData("DemoAdapter",
"submitAuthentication" , new object[1]); // Add the parameters you want to pass to the adapter
AdapterAuthenticationParameters.InvocationData = invocationData;
AdapterAuthenticationParameters.RequestOptions = null;
isAdapterAuth = true;
}
else
{
isAdapterAuth = false;
authSuccess = true;
}

Related

Enabling Single Sign On in TEdgeBrowser

I have some C# code that shows how to enable Single Sign On in WebView2.
The TEdgeBrowser doesn't expose any of the properties that the C# code uses. In particular the interface defined in the Winapi.WebView2 unit for ICoreWebView2EnvironmentOptions doesn't have the functions for getting or setting AllowSingleSignOnUsingOSPrimaryAccount defined in it. I believe that this is because it was created from WebView2.tlb on 07/05/2020 whereas the property was added in the version released September 10, 2020.
What options do I have? Do I need to create my own version of WebView2 from the latest tlb and then duplicate the code in the Vcl.Edge unit to get a component with the SSO option enabled?
I don't need a visual component - I'd be happy to create the browser in code.
The C# code is:
private async void Form1_Load(object sender, EventArgs e)
{
var browser = new WebView2();
var options = new CoreWebView2EnvironmentOptions();
options.AllowSingleSignOnUsingOSPrimaryAccount = true;
var environment = await CoreWebView2Environment.CreateAsync(options: options).ConfigureAwait(false);
await browser.EnsureCoreWebView2Async(environment).ConfigureAwait(false);
Invoke((MethodInvoker)(() =>
{
browser.Dock = DockStyle.Fill;
this.Controls.Add(browser);
browser.Source = new Uri(https://example.com);
}));
}
Try WebView4Delphi instead. WebView4Delphi is fully updated to the latest WebView2 version and it supports all the WebView2 interfaces.
You only have to add this line before the GlobalWebView2Loader.StartWebView2 call :
GlobalWebView2Loader.AllowSingleSignOnUsingOSPrimaryAccount := True;
The demos use the initialization section of the main unit to create GlobalWebView2Loader and set the properties. If you use the SimpleBrowser demo as a template for your application then you would have to add the previous line here.
That property in GlobalWebView2Loader is used for all the browsers that share the same ICoreWebView2Environment which is the default behavior.
In case you need to create a browser with an independent ICoreWebView2Environment then you have to set this property before the TWVBrowserBase.CreateBrowser call :
MyWVBrowser.AllowSingleSignOnUsingOSPrimaryAccount := True;
MyWVBrowser would be an instance of TWVBrowser.

#iOSFindBy is displayed as deprecated, what can I use instead (using pagefactory for Hybrid usage of Android and iOS device))

I have no experience with iOS, but I am trying to redesign my Android Project for the iOS Guys to use it as well for iOS.
After search in internet I find out that this can happens by using the page factory and locating elements by #iOSFindBy,
After trying to use #iOSFindby for locating element using the page factory method, the compiler indicate that it is deprecated.
#iOSFindBy (Accessibility = "button_login")
#AndroidFindBy(id = "net.myApp.int:id/loginBtn")
private MobileElement login_Button2;
what Can I use instead of this?
I saw also in Appium java client (https://static.javadoc.io/io.appium/java-client/7.0.0/index.html?deprecated-list.html) :
*io.appium.java_client.pagefactory
Annotation Type iOSFindBy
Deprecated.
UIAutomation is going to get deprecated. Use iOSXCUITFindBy instead It is recommended to use XCUITest
#Retention(value=RUNTIME) #Target(value={FIELD,TYPE})
#Repeatable(value=iOSFindBySet.class) public #interface iOSFindBy
Used to mark a field on a Page Object to indicate an alternative mechanism for locating the element or a list of elements. Used in conjunction with PageFactory this allows users to quickly and easily create PageObjects. using iOS UI selectors, accessibility, id, name, class name, tag and xpath*
but I dont know if this is the solution and how to use
If I use it in my Code also get Error:
#iOSXCUITFindBy Accessibility = "button_login"
#AndroidFindBy(id = "net.myApp.int:id/loginBtn")
private MobileElement login_Button1;
Annotation are not allowed here.
Thanks for any Tip in advance
The best way to know how things work is to check related tests in appium-java-client repository on github:
#iOSXCUITFindBy(accessibility = "IntegerB")
private MobileElement textField2;
So in your case, it should be:
#iOSXCUITFindBy(accessibility = "button_login")
#AndroidFindBy(id = "net.myApp.int:id/loginBtn")
private MobileElement login_Button1;

Testing Flutter code that uses a plugin and platform channel

I have a flutter plugin which uses the platform channel to do some native work.
How do I properly write tests for my application that requires this plugin?
Unit tests only are good for pure dart functions. I don't believe Widget testing will be able to test things that use the platform channel to native. So that leaves integration testing.
From what I understand is that integration testing will start your main application and you can control it around your app and test things.
For my case, I want to test just the code that uses the plugin (that uses the platform channel for native stuff).
Also what is important is the values that come back from the platform channel, so it is important to call the native side using a real platform channel and not a mock one.
Is that possible? Can I tell the integration tester to open a dummy version of my application, kind of like an integrated widget tester?
It seems the short answer to your question is no. Flutter driver (integration testing) can only interact with the UI, AFAIK. It cannot intercept calls to plugins. It is used to test the entire app from the UI.
However it is possible to intercept calls to plugins in unit and widget tests. This allows monitoring the calls to the plugin and mocking the response. That way you can test your plugin's dart code and/or a widget that uses the plugin. Testing native code would involve writing native tests.
The following is an example of intercepting calls to a plugin for testing:
MethodChannel('audio_recorder')
.setMockMethodCallHandler((MethodCall methodCall) async {
log.add(methodCall);
switch (methodCall.method) {
case 'start':
isRecording = true;
return null;
case 'stop':
isRecording = false;
return {
'duration': duration,
'path': path,
'audioOutputFormat': extension,
};
case 'isRecording':
return isRecording;
case 'hasPermissions':
return true;
default:
return null;
}
});
For a complete example see here
Flutter team do mentions that they want to do more things in widgets test instead of driver(integration) test.
We're moving away from flutter_driver in favour of extending flutter_test to work on devices.
From Flutter 2.8 breaking changes doc, you should use binding in tester instead of setMockMethodCallHandler from channel.
// old code
myMethodChannel.setMockMethodCallHandler(...);
myMethodChannel.checkMockMethodCallHandler(...);
// new code
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(myMethodChannel, ...);
tester.binding.defaultBinaryMessenger.checkMockMessageHandler(myMethodChannel, ...);
Take ImagePicker as example:
widgetTest('', (tester) async {
const channel = MethodChannel('plugins.flutter.io/image_picker');
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
channel,
(MethodCall methodCall) => Future.value('some-image'),
);
});
One additional thing to #呂學洲 answer.. is if you're writing a unit test and don't have reference to widget tester instance you can access the binder like below
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger
Also make sure to wait for binder to initialize in the begging of the test like below
TestWidgetsFlutterBinding.ensureInitialized();
And to grab method call you can do:
final binaryBinding = TestDefaultBinaryMessengerBinding.instance;
pluginChannel = MethodChannel('channelName');
binaryBinding!.defaultBinaryMessenger.setMockMethodCallHandler(pluginChannel,
(MethodCall methodCall) async {
switch (methodCall.method) {
case 'call 1':
return mockValue;
default:
return null;
}
},
);
Hope that helps.

How to Communiccate between JD Edwards Enterprise one 9.0 and .Net

I have problem that how to communicate Jd Edwards Enterprise one 9.0 with .Net,and my project manager told me to look at the "fatclient" as it acts as a middle ware between these two,but there is no luck in my search,
Thanks in advance
Responding to this old post. Hopefully, this will help someone who has a similar need:
Take a look at our product LynX Business Integrator. It is Oracle Validated and it allows you to create integration processes natively in C# and publish it as a web service. So, you can write code like this:
private bool CallAddressBookBsfn(BusinessDocument businessDocument, Transaction transaction)
{
AddressBookMaster abm = businessDocument.document.input.AddressBook;
// create an instance of the Address Book Master Business function
// note the use of JDE Transactions
AddressBookMasterMBF bsfn = new AddressBookMasterMBF(transaction);
// set parameters - most of this code is auto-generated
bsfn.DpmnAddressBookNumber.InValue = (long)abm.AddressNumber;
bsfn.DpszSearchType.InValue = abm.AddressType;
bsfn.DpszAlphaName.InValue = abm.Name;
bsfn.DpszAddressLine1.InValue = abm.AddressLine1;
bsfn.DpszAddressLine2.InValue = abm.AddressLine2;
bsfn.DpszAddressLine3.InValue = abm.AddressLine3;
bsfn.DpszAddressLine4.InValue = abm.AddressLine4;
bsfn.DpszPostalCode.InValue = abm.ZipCodePostal;
bsfn.DpszCity.InValue = abm.City;
bsfn.DpszState.InValue = abm.State;
bsfn.DpszCountry.InValue = abm.Country;
bsfn.DpcActionCode.InValue = 'A';
bsfn.DpcUpdateMasterFile.InValue = '1';
// execute the business function
if (bsfn.Execute() != BusinessFunctionResult.Success)
{
// get errors
return false;
}
// assign output
businessDocument.document.output.AddressNumber = bsfn.DpmnAddressBookNumber.OutValue;
businessDocument.document.output.AddressNumberSpecified = true;
return true;
}
Take a look at our YouTube Channel at http://www.youtube.com/user/aelliuslynx and our product page at http://www.aellius.com/products/lynx-business-integrator
I am using old version 8.0 and if by "communication" you mean to be able from a .NET application to run JDE BSFN directly, then i am gonna dissapoint you but there isn't any way i know of.
Maybe things have changed in 9.0 but i doubt it.
Personally whenever i want to communicate with our JDE (AS400 based) i am using:
Frontend
-.NET Web Api services
-C# winforms apps
-ASP.NET
Backend
-Custom Dlls for Business logic and Data Access Layers.

StructureMap 202 - Why?

OK, I'm trying to set a property on a type I'm registering with SM.
Here's the code from the registry in one of my components. This
registry is being added during the configuration from a console app.
When I try to access the EndorsementSpecs property of the instance
AutoMandatoryEndorsementAggregator object, I get the 202. What's
interesting is that I can call
GetAllInstances>() from my
console app and it resolves just fine. Is there something about
accessing this code from within OnCreation that is causing the 202? I
can see everything I expect in WhatDoIHave(). I've also tried a TypeInterceptor with the same results.
//register all open generics
cfg.ConnectImplementationsToTypesClosing(typeof
(MandatoryEndorsementSpecBase<>));
ForSingletonOf<IMandatoryEndorsementAggregator<AutoPolicy>>()
.Use<AutoMandatoryEndorsementAggregator>()
.OnCreation((context, x) =>
{
var specs =
context.GetAllInstances<MandatoryEndorsementSpecBase<AutoPolicy>>();
x.EndorsementSpecs = specs;
})
;
Sorry to deflect your real questions, but are you just trying to inject all instances of MandatoryEndorsementSpecBase into AutoMandatoryEndorsementAggregatory?
If so, you can probably get away with just making it a constructor parameter so that they are all automatically injected.
public AutoMandatoryEndorsementAggregatory(MandatoryEndorsementSpecBase<AutoPolicy>[] endorsementSpecs){
EndorsementSpecs = endorsementSpecs;
}

Resources