"SecurityException" when trying to log in to a Windows Phone application

"SecurityException" when trying to log in to a Windows Phone application

Old forum URL: forums.lhotka.net/forums/t/11157.aspx


itogroup posted on Tuesday, February 14, 2012

I think this is stemming from a WCF config error, as I vaugely recall having similar issues when setting up my Windows Forms project. As I recall, WCF won't let you send a password across the wire unless the wire is secured. I'm hoping someone out there has experience with WCF/WP7 and can spot/point out an error.

The exception is raised when I call DataPortal.BeginFetch on my custom Identity type. The stack trace is below:

   at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type)
   at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type)
   at System.Runtime.Serialization.DataContract.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type)
   at System.Runtime.Serialization.DataContract.GetDataContract(RuntimeTypeHandle typeHandle, Type type, SerializationMode mode)
   at System.Runtime.Serialization.XmlObjectSerializerContext.GetDataContract(RuntimeTypeHandle typeHandle, Type type)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerializeReference(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
   at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
   at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at System.Runtime.Serialization.XmlFormatWriter.InternalSerialize(MethodInfo methodInfo, Object memberValue, Type memberType, Boolean writeXsiType, XmlObjectSerializerWriteContext context, XmlWriterDelegator xmlWriter)
   at System.Runtime.Serialization.XmlFormatWriter.WriteValue(Type memberType, Object memberValue, Boolean writeXsiType, XmlObjectSerializerWriteContext context, XmlWriterDelegator xmlWriter)
   at System.Runtime.Serialization.XmlFormatWriter.WriteMember(SerializingObject serObj, Int32 memberIndex, ClassDataContract derivedMostClassContract)
   at System.Runtime.Serialization.XmlFormatWriter.WriteClass(CallStackElement`1 callStackElement)
   at System.Runtime.Serialization.XmlFormatWriter.Serialize(XmlObjectSerializerWriteContext context)
   at System.Runtime.Serialization.XmlFormatWriter.InitializeCallStack(XmlWriterDelegator xmlWriterDel, Object obj, XmlObjectSerializerWriteContext writeContext, DataContract contract)
   at System.Runtime.Serialization.CollectionDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph)
   at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph)
   at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph)
   at System.Runtime.Serialization.DataContractSerializer.WriteObject(XmlWriter writer, Object graph)
   at Csla.Serialization.Mobile.MobileFormatter.Serialize(XmlWriter writer, Object graph)
   at Csla.Serialization.Mobile.MobileFormatter.Serialize(Stream serializationStream, Object graph)
   at Csla.Serialization.Mobile.MobileFormatter.Serialize(Object obj)
   at Csla.DataPortalClient.WcfProxy`1.BeginFetch(Object criteria, Object userState)
   at Csla.DataPortal`1.BeginFetch(Object criteria, Object userState)
   at Csla.DataPortal.BeginFetch[T](Object criteria, EventHandler`1 callback, Object userState)
   at Csla.DataPortal.BeginFetch[T](Object criteria, EventHandler`1 callback)
   at Harld.Data.HarldIdentity.BeginGetStaff(String username, String password, EventHandler`1 callback)
   at Harld.Data.HarldPrincipal.BeginLogin(String username, String password, Action`1 completed)
   at Harld.Client.Mobile.v4.ViewModels.Login.LoginUser()
   at Harld.Client.Mobile.v4.Views.Login.LoginButton_Click(Object sender, EventArgs e)
   at Microsoft.Phone.Shell.ApplicationBarItemContainer.FireEventHandler(EventHandler handler, Object sender, EventArgs args)
   at Microsoft.Phone.Shell.ApplicationBarIconButton.ClickEvent()
   at Microsoft.Phone.Shell.ApplicationBarIconButtonContainer.ClickEvent()
   at Microsoft.Phone.Shell.ApplicationBar.OnCommand(UInt32 idCommand)
   at Microsoft.Phone.Shell.Interop.NativeCallbackInteropWrapper.OnCommand(UInt32 idCommand)

 

Here's the service model chunk of the app.config from my Windows Forms project (this configuration works with our server config):

    <system.serviceModel>
        <client>
            <endpoint name="HarldWcfDataPortal" address="https://saservices.case.edu:4443/WcfPortal.svc" binding="basicHttpBinding" contract="Csla.Server.Hosts.IWcfPortal" bindingConfiguration="BasicSslBinding">
            </endpoint>
        </client>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicSslBinding" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647" receiveTimeout="00:01:00" sendTimeout="00:01:00">
                    <security mode="Transport">
                        <message clientCredentialType="UserName" algorithmSuite="Default"/>
                    </security>
                    <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
                </binding>
            </basicHttpBinding>
        </bindings>
    </system.serviceModel>

And here's the code I've created in the ctor of App.xaml for my Windows Phone application:

            Csla.DataPortal.ProxyTypeName = typeof(Csla.DataPortalClient.WcfProxy<>).AssemblyQualifiedName;
            Csla.DataPortalClient.WcfProxy.DefaultUrl = "https://server:5443/SlPortal.svc";
            BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
            binding.Name = "BasicSslBinding";
            binding.MaxReceivedMessageSize = 2147483647;
            binding.MaxBufferSize = 2147483647;
            binding.ReceiveTimeout = new TimeSpan(0, 1, 0);
            binding.SendTimeout = new TimeSpan(0, 1, 0);
            Csla.DataPortalClient.WcfProxy.DefaultBinding = binding;

NOTE: My windows form project includes a custom subclass of WcfProxy. If I try to link the proxy class into the Silverlight business objects library, I can't subclass WcfProxy (it's static)

RockfordLhotka replied on Tuesday, February 14, 2012

In Silverlight you subclass WcfProxy<T> to get the same result as in .NET.

itogroup replied on Wednesday, February 15, 2012

If I do

public class HarldWcfProxy : WcfProxy<HarldWcfProxy>

I get "The type 'Harld.Data.HarldWcfProxy' cannot be used as type parameter 'T' in the generic type or method 'Csla.DataPortalClient.WcfProxy<T>'. There is no implicit reference conversion from 'Harld.Data.HarldWcfProxy' to 'Csla.Serialization.Mobile.IMobileObject'."

If I try to have HarldWcfProxy implement IMobileObject, I have no idea what to do in GetChildren, GetState, SetChildren, and SetState.

RockfordLhotka replied on Wednesday, February 15, 2012

The Using CSLA 4: Data Portal Configuration book covers this scenario, including examples.

Your subclass also needs to be generic - HarldWcfProxy<T>

 

itogroup replied on Thursday, February 23, 2012

I was able to get my proxy working and am making some progress. I believe the SecurityException was due to the fact that I was trying to serialize a nested class. I unnested the class and am able to get past that exception. Now I'm getting:

 

Could not load type 'Csla.Serialization.SerializableAttribute' from assembly 'Csla, Version=4.2.2.0, Culture=neutral, PublicKeyToken=93be5fdc093e4c30'.

   at Harld.Data.Mobile.HarldIdentity.<>c__DisplayClassf.<BeginGetStaff>b__e(Object o, DataPortalResult`1 e)
   at Csla.DataPortal`1.OnFetchCompleted(DataPortalResult`1 e)
   at Csla.DataPortal`1.proxy_FetchCompleted(Object sender, DataPortalResult`1 e)
   at Csla.DataPortalClient.WcfProxy`1.OnFetchCompleted(DataPortalResult`1 e)
   at Csla.DataPortalClient.WcfProxy`1.proxy_FetchCompleted(Object sender, FetchCompletedEventArgs e)
   at Csla.WcfPortal.WcfPortalClient.OnFetchCompleted(Object state)
   at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
   at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at System.Delegate.DynamicInvokeOne(Object[] args)
   at System.MulticastDelegate.DynamicInvokeImpl(Object[] args)
   at System.Delegate.DynamicInvoke(Object[] args)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.Dispatch(DispatcherPriority priority)
   at System.Windows.Threading.Dispatcher.OnInvoke(Object context)
   at System.Windows.Hosting.CallbackCookie.Invoke(Object[] args)
   at System.Windows.Hosting.DelegateWrapper.InternalInvoke(Object[] args)
   at System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(IntPtr pHandle, Int32 nParamCount, ScriptParam[] pParams, ScriptParam& pResult)

RockfordLhotka replied on Thursday, February 23, 2012

It is really important to understand how we do serialization in Silverlight, on the phone, and soon in WinRT.

Because those platforms don't allow full use of reflection, Microsoft was unable to create BinaryFormatter or NetDataContractSerializer for those platforms.

So we ended up creating a rough equivalent that doesn't require reflection. To do this, we impose certain constraints on the types that can be serialized. Specifically, all types must be primitive .NET types, or must implement IMobileObject (or inherit from one of our base classes).

This is true for all objects in the object graph. All of them. No exceptions.

If you define a class that doesn't inherit from a CSLA base class, one of the MobileXYZ types in Csla.Core, or directly implement IMobileObject, then you can't serialize that type through the data portal.

I discuss this in the Using CSLA 4: Data Portal Configuration book, because it is quite important.

Copyright (c) Marimer LLC