Tuesday, 6 November 2012

Microsoft Surface Windows 8 RT: How to deploy/debug application

Windows 8 RT has restriction on launch 3rd party application, which were downloaded/delivered to device not from Microsoft store. Microsoft selected the same strategy as Apple. I already described in previous article what will happen if you launch application, copied to the Surface device manually, even if it is compiled for the ARM processor. Operation system will show alert message:

Windows 8 RT: message "This app can't run on your PC"


The question is obvious: How to develop/deploy and test applications on your personal device?
The answer is "You have to switch you device into developer mode." I am going to describe how to do it in this article.

Development Environment:

Simple scenario (work at an office) - one PC (dev box) and Surface device on the same network segment


Technically, you need one computer with installed Visual Studio 2012 and your tablet, which is connected to the same network segment. You will use 1st one to develop application and debug application and tablet for the user interface interactions.


PC Configuration
Memory: 4Gb
CPU: i5
Operation System: Windows 8 Enterprise
Development Tool: Microsoft Visual Studio 2012
Location: Office

Microsoft Surface Device
Memory: 2Gb
CPU: ARM type
HDD: 64 Gb
Location: Office


Advanced Scenario - work remotely 

There is common scenario when your main development box (powerful one) is located at an office but you are at public place (Starbucks for example) and you need to test something and check-in code to source control system, such as TFS.  In this scenario you have to use VPN access, but it is better if you have additional laptop (any OS, which will support VPN connection and remote desktop). I am using Apple MAC Air in my case.

Here is simple diagram, which shows how it will work:



you will you use VPN connection from your laptop and Microsoft Surface to your office. You laptop will be connected to dev box by RDP (remote desktop). The result will be pretty same.

Additional laptop makes you really mobile developer and you can work from anywhere!!!!
When I am working from home, I prefer to use the same scenario but I also use Apple TV to stream my MAC Air screen to Huge TV. This is a beauty of the Apple technologies!

So....
I am using my MAc to develop applications for the Microsoft Windows 8 RT :-)

Using Apple MAC Air to RDP to MS Windows 8 Enterprise with installed Visual Studio 2012 and debug Windows 8 Rt application on my Microsoft Surface device. Screen from MAC is streamed to TV via Apple TV.



Setup Microsoft Surface device for the development

Microsoft uses the same approach as Apple - make device compatible with development mode. 
The best approach to do it is to install "Remote Tools", which come with Visual Studio 2012.


Simply copy rtools_setup_arm.exe executable file from that folder to your Surface device (ARM determines CPU. in Pro version it will be Intel) and install it. you will be prompted for couple dialog boxes and it is done.

After installation of the remote tools you will see 2 new applications at Metro-style screen: "Remote debugger" and "Microsoft Test Tools Adapter".

Windows 8 Rt with installed "Remote debugger" and "Microsoft Test Tools Adapter"

To allow Visual studio deploy/run application at Microsoft Surface device, you have to configure remote debugger. After run "Remote debugger", you have to setup security (I turned it of in this sample) and management port. If you work from multiple places, I recommend to use port 8080 - it is standard second http port for the web browsing and open in most providers, so you will not have any issues with development. 

Microsoft Remote Debugger configured at Windows 8 RT
when you will start configure remote debugging tool, you will be prompted to switch this device to development mode.



Setup Development computer

I have heterogeneous environment at my office, so i used Hyper-V to setup new instance of Microsoft Windows 8 operation system and installed Microsoft Visual Studio 2012 on it. If you interesting how it will work from learning perspective, you can download trial version of OS and dev tool, which will be valid for 90 days.

You can create any type of Metro-style project  - I used Metro-style Grid template in this sample. Next step is to configure Visual studio for the remote debugging: select project debug properties with option target device "Remote machine". You have to enter your Surface device ip address and port, which you configured in previous step.

VS 2012: setting up remote debug settings

you can also find you computer in network:

VS 2012: search Microsoft Surface with remote debugging tools

Deploy application

Next step is to prepare package and deploy it to Microsoft Surface device. you have 2 options here: manual deployment and automatic deployment during debug mode.

Setup Package Application Manifest

before create package, you have to setup some package parameters, such as application name, release version, certificate etc....
Simply find package.appmanifest file in project, double click on it and it will oped UI with configuration:




Manual deployment

If you have visual studio and don't have connected device, you can prepare package, copy it to usb key and deploy it offline. in this case, you have to do right click on properties and select "Store\Create App package" in popup menu.

VS 2012: Create application package


VS 2012: package creation - local mode



Next screen is very important for the package creation. You should setup release version, select checkbox if you want to increase release version automatically or not and you have to select compilation option for the platforms (select ARM for the Windows 8 RT).

VS 2012: package creation - release version/ compilation option  
VS 2012: package complete


After you copy package from "AppPackages" (folder can contain different releases. select which you want) to device, you have to run deployment script by right mouse click on file "Add-AppDevPackage" and select "Run with PowerShell".

Windows 8 RT: deploy package via PowerShell

Next step is magic step, which close Windows 8 RT eyes on all deployment policies and allows install application on device:

Windows 8 RT: changing the execution policy via PowerShell
After package is deployed, you should be able to see application at metro-Style style.


Automatic deployment

Automatic deployment is a beauty - you just need start Visual Studio in debug mode( press "F5" key) and application will be automatically deployed to remote device. If you did previous step, you will be alerted that such application was already deployed but you still have an option to re-deploy and run it.

Next step is to setup break points in solution and use your fingers on device touch screen.

Summary

As always, Microsoft shows that Visual Studio is very powerful tool, which allows developers to use the same tool to create/debug new types/styles of applications. I would wish if it would be the same for the rest :-)

Happy debugging!!!




Saturday, 3 November 2012

Microsoft Surface Windows RT 8 - 64GB as is - My review

If you visit Microsoft store (today is 2 Nov 2012), home page says
"Experience Surface at a Microsoft Store near you". What I did, I went to "Eaton Centre" - Toronto downtown, where Microsoft opened retails store and bought it !!!

Microsoft Surface: Windows 8 RT


In this article I am going to review it from my point of view. I heard and read many news about windows 8. I even downloaded it and developed couple apps with "Metro style" but never used it on real device. My decision to purchase was to test it in my hands.

I am technical person and have computers at home and at work. The reason only to buy mobile devices such as tablets is to use it for work or for entertainment, so I will compare my purchase with some Apple products. I am not covering everything, but only what I found during a day (I will describe UI features in next article).

Price

Retail store didn't have 32Gb version, so I bought 64Gb version of Microsoft Surface Win-RT. Retail price on it was 719CAD + taxes = 812.47 (hate taxes). As you can see it is not so cheap - It is price of the pretty good laptop nowadays. Let's see what is inside.

(as I said, I bought 64GB version, which is 100 CAD more expensive then 32GB). Technically speaking I bought 32GB for the 100CAD + taxes!!! Awesome profit for manufacturer.

Device

Device weight


It is pretty heavy for mobile device. If you hold device by one hand and type text you will be tired very soon. It is one of the reasons why Apple is releasing mini iPad (sweet thing is that it will have 4G, so I can use cellular data plan), which I am going to buy.

Device hardware



Microsoft Surface: hardware information


CPU: ARM (not intel) - it means that all apps, should be compilable with ARM option
Memory: 2GB - well, Windows and 2GB sounds dangerous, but take into consideration that it is RT version it could be good :-)
Ports: microSD, USB 2.0 (pro version should have USB 3.0), Micro HD Video (Pro version should have display port). If you want connect device to your monitor, you have 3 options - use micro HD Video and use adapters: USB->HDMI or USB->VGA, which you can buy right as MS Store for "only" :-) ~44CAD

HDD: 64Gb but in reality
OS shows 54GB only, where 10GB eaten by OS. In a fact I have 46Gb free only. I only updated existing apps (described below) - It is definitely catch for end users.

Microsoft Surface: Windows 8 RT -  hdd catch

Device keyboard


Device has attachable keyboard. I liked idea to have keyboard to be attachable to device by magnet, but is has its own issue - it doesn't highlight symbols when it is dark, like it Apple does with laptops. I am a person who work day and night and it is very critical to see symbols on a keyboard :-)

Do you see it on next picture?

Microsoft Surface: Windows 8 RT - keyboard is not visible in dark


Screen Zoom


What disappointed me is that screen zoom doesn't work everywhere. It works inside of running applications if they support it, but not in desktop mode. When I brought my device to work, we tried to use it right away to customize desktop and use RDP (remote desktop access) to manage other computers but it is not possible with touch screen - you can easily press wrong menu item and delete files instead of copying them.

Surface: Windows 8 RT - zoom is not working.
It is not possible to select small menu items and objects.


It works good only when you RDP to another Windows 8, which has metro style :-) I made picture of that to show:

Windows 8 RT: using Remote Desktop Connection to another Windows 8,
where I run metro style application :-)



Another option is to use mouse pad, located at keyboard but I found it working not very good (my personal feeling - I use many laptops with no issues but this keyboard has an issue from user experience perspective - in general).

Applications


Every technical person would be happy to have fully functioning windows on mobile device, even if device is not so powerful, but Windows 8 RT restrict use 3rd party applications. You can only download new apps from Microsoft Store (which is very weak at this point of time). Another thing - you cannot even use this device to debug applications. I copied application to this device, which was developed by VS and compiled for the ARM CPU, but here is a message:


"This app can't run on your PC. To find apps for this PC, open the Windows Store. "
Microsoft is fully controlling applications, which will be coming to this operation system. Developers in the same situation as on Apple's platform. I have read couple of articles that MS already rejected some popular applications to be on MS store. I am pretty sure that very soon new hack will be releases, which will allow to to run ARM compiled application not via MS Store.


Windows 8 RT is coming with Office 2013, but it is Home/Student edition. The fact is that it has missing Visio stops me from creating technical documents with diagrams by using this device.

Applications' updates

Staring from this point, all applications which you downloaded by using "Store" will be auto-updated by Store (the same idea as Apple store).

Windows 8 RT: app updates via Microsoft Store


At the same time, you shouldn't forget about "Windows Update". Here is what was Updated right after I bought it:

Windows 8 RT: Windows updates after I bought new device

Internet Browsing - Flash


I expected to see working flash in internet explorer, but flash is working only on approved by Microsoft sites - sucks.


XBox 360 control - SmartGlass


Yes, you can use this device to manage XBox 360. I downloaded XBox SmartGlass application and tried it. It sounds sweet in promo but in reality it sucks.

SmartGlass requirements:

You have to login with the same account on SmartGlass as you currently logged in on XBox. if you have multiple profiles on XBox and switch them, you have to switch them on SmartGlass - it is becoming nightmare.

Use tablet as additional information screen:
SmartGlass application can display details about what is going on on XBox while you are watching movie/playing music or playing game:

XBox SmartGlass on Windows 8 RT.
Picture shows game info/stats while my son is playing it.

First of all, I experienced latency between my actions on device and response from XBox screen.
When I used "Remote Control/Controller" feature and tried to navigate between XBox tabs and select particular item on screen, screen could easily jumped from one tab to another, like from "games" to "Tv and movies".




Another part, which I hated is that you have to swipe left to move right tab on a screen (really confusing).

Internet Explorer on XBox

I also tried Internet Explorer on XBox - awesome!!! But is is not related with Surface/Win 8 RT success at all - it is cool thing/application, which Microsoft enabled on XBox (after all these years!!!!!! MS would have bigger success if they would enable it long time ago, but it is another discussion). The biggest risk is that hackers can start develop new js scripts/worms for the XBox. It is start to develop Antivirus for the XBox :-)

In any way, here is picture of typing urls via SmartGlass on Xbox




Generally, it is great idea to control XBox via mobile devices, but it should be much simpler from end-user perspective and cheaper. I have simple question: "Why should I connect to XBox via additional  (not cheap) device to use keyboard, which has internet explorer itself????????????"

Here is what I am talking about: XBox has its own keyboard, which you can attach to a game controller. I bought this one for 6.99CAD (6.99CAD vs 800CAD - what do you think about it?):

XBox 360 game controller with attached keyboard: browsing internet

Video/Music

Windows 8 RT doesn't have windows media player, but it still has Metro style apps, which allow to play video and music. I really was happy when found that I don't need to convert my .avi files to new format like in case with other mobile devices :-) It is definitely great advantage for the end-user.



Microsoft already had services to sell Video/Music via XBox and they brought it to mobile device, like Apple did it with iTunes.

I really laughed when I tried to play music sample from XBox store via "Music" application and got this message:



Summary


The fact is that device is heavy and doesn't have 3G/4G makes this device not mobile device but stationary. List of applications is pretty small at this point of time, which makes purchase of this device is very expensive. As I said, you can buy pretty good laptop for the same price, which can host fully functioning OS. I would wait fully functioning operation system "Windows 8 Pro" with device, which has large memory and intel CPU. It will make life easier (mine at least).

P.S.
I used Apple Mac Air to work on this article and used iPhone to make pictures :-) I am going return Surface (if it is possible).












Friday, 25 May 2012

Microsoft .NET Authentication Service Framework 4.0 as Single Sign On point - different clients

Introduction


I will describe windows authentication service, which is became as part of the Microsoft Framework 4.0 and how to use it in differnt applications such as
ASP.NET, MVC, Console, Silverlight application project types and create them in Visual Studio. I will also show how to use Authentication service from IOS (iPhone/ iPad) but
lets start from the beginning. You can find many articles about it but I will try to cover as much as possible in one place. I will aslo cover what is going on during authentication (extended version of the http://support.microsoft.com/kb/910443 with printscreens :-) ).

You can find determination of the authentication at wiki page, such as "Authentication is the act of confirming the truth of an attribute of a datum or entity".
http://en.wikipedia.org/wiki/Authentication

Microsoft developed perfect framework and ASP.NET server controls, which allowed easily develop application with different authentication mechanisms
by using built-in authentication providers and create new. The most used/popular authentication mechanism in web sites is Forms authentication - when user has to enter user name/password/custom data. Of course, there is no perfect system to protect, but at least framework allowes to create your own authentication provider based on common interfaces. You can find how to create custom authentication provider at MSDN site.


Nowadays we use differnt platforms and clients to access to the same data by using different applications.
It brought point to have Single Sign On services. SOA architecture fits those requirements.

SSO sample


Microsoft extended existing framework with Application Services, such as Authentication/Membership and Profile service, which is covered in this article:
http://msdn.microsoft.com/en-us/library/bb386582.aspx
I will describe all of 3 services and their impact on existing applications/network infrastructure, but as I said above, this article describe authentication service only.

Application infrastructure/configuration:


Multi-layered application:
front-end->service grid/application layer->data layer (3 layered application infrastructure). No limit in layers nowadays.
So, what Microsoft actually made and how to use it in application?
Talking about previous diagram we can say that application, using authentication service will be looking like this
<front-end 1/2...>-<authentication service>->Credential database/<Administrative portal>

SSO: multi-layered diagram



Lets start describe application architecture from data level to front-end.

1.Database configuration


You can use MS SQL/Oracle/MySql ... databases. I will be focused on MS SQL database. Here are steps to create and configure database:

1) Create database


Im am not going to cover using Microsoft SQL Management Studio and providing T-SQL script to create one (path to data file and log file can be diffenet on your environment):

CREATE DATABASE [SSO_DB] ON  PRIMARY
( NAME = N'SSO_DB', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\SSO_DB.mdf' , SIZE = 10240KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
 LOG ON
( NAME = N'SSO_DB_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\SSO_DB_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)

2) Create account, which will have access to database


I created user sso_user with db_owner permissions to database SSO_DB and password <sso_password>. I will use it to update database schema and use it in connection string.
It is better to use windows authentication, but I did it for sample.

3) create database schema


I will use tool, which comes with Microsoft .NET framework:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regsql.exe
when you run it, you have to select "Configure SQL Server for application services",

aspnet_regsql.exe: Configure database


enter database instance, database "SSO_DB" and enter user name/password of sql user, which we created in step 2.

aspnet_regsql.exe: Enter credentials


after you finish all steps, you can check database schema:

aspnet_regsql.exe: database schema



aspnet_Users table will contain list of users. It also contain important field: ApplicationId, which is refernced to aspnet_Applications.
It means that database stores users from many applications, and you have to provide correct application name to make sure that your user will be authenticated.
Database configuration is done.

2. Administrative web site


Main task for the admin portal is to manage users/roles. You have 2 options how to fo it:
a) use Visual Studio ASP.NET configuration. You just need create empty web site, configure authentication in web.config and start do it.
b) create custom administrative portal with it's own pages and flows. You can find many samples in internet how to do it by using Membership namespace.
By my opinion, I think that Microsoft would create web site template long time ago for those purpose but it didn't do it yet.
I will be focused on first approach.

a) create web site application in Visual StudioI created solution solution with name POC.Authentication (POC - prove of concept) and created empty ASP.NET Empty Web application with name POC.Authentication.Web.Admin.

MS Visual Studio: create ASP.NET empty application


b) update web.config to enable forms authentication
there are following parts to enable forms authentication
connection string - I used account, which was described in database topic
set authentication to forms
configure AspNetSqlMembershipProvider provider
web.config should looks like this

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <clear/>
    <add name="LocalSqlServer"
         connectionString="Data Source=.;Initial Catalog=SSO_DB;User ID=sso_user;Password=sso_password"
         providerName="System.Data.SqlClient" />
  </connectionStrings>
  <system.web>
        <compilation debug="true" targetFramework="4.0" />
    <authentication mode="Forms" />
    <membership>
      <providers>
        <clear/>
        <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="LocalSqlServer"
             enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
             maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
             applicationName="/" />
      </providers>
    </membership>
  </system.web>
</configuration>

All parameters for AspNetSqlMembershipProvider are very important, but at this point of time the most important parameter is applicationName.
Technically speaking one database created earlier can serve many applications. You can check database schema and will find that "aspnet_Users" table has foreign key to "aspnet_Applications" on ApplicationId column.

Authentication database: sql select statements


c) create usersTo start cerate users, you have to select web application project in Visual Studio solution explorer and click on "ASP.NET configuration"

ASP.NET Configuration



ASP.NET configuration uses connection string with name "LocalSqlServer" by default. but nobody stops you to change name later.
New web site will be started. Click on "Security" link.



click on "Create user" link and on next page create couple of users. Based on configuration of the "AspNetSqlMembershipProvider" you can see different field.

ASP.NET Configuration: create user


you can check database content now and you will see something like that:

Authentication database: database content


User creation is done.

3. Service grid - Authentication service


Next step is configure WCF service, which will be responsible for the user authentication.
Create new project with type "WCF Service Application" and name is "POC.Authentication.Services"

MS Visual Studio: Create WCF Application


delete IService1.cs and Service1.svc - we are not going to use it. Instead, we will create new service with name "AuthenticationService.svc" (service name can be any), inherited from "System.Web.ApplicationServices.AuthenticationService"
Just delete IAuthenticationService.cs, AuthenticationService.svc.cs and modify AuthenticationService.svc to have this code:

<%@ ServiceHost Language="C#" Service="System.Web.ApplicationServices.AuthenticationService" Debug="true" %>


The solution should look like

MS Visual Studio: Solution Explorer


one more thing: make web.config changes to enable service

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <clear/>
    <add name="LocalSqlServer"
         connectionString="Data Source=.;Initial Catalog=SSO_DB;User ID=sso_user;Password=sso_password"
         providerName="System.Data.SqlClient" />
  </connectionStrings>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <authentication mode="Forms" />
    <membership>
      <providers>
        <clear/>
        <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="LocalSqlServer"
             enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
             maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
             applicationName="/" />
      </providers>
    </membership>
  </system.web>
  <system.web.extensions>
    <scripting>
      <webServices>
        <authenticationService enabled="true" requireSSL="false"  />
      </webServices>
    </scripting>
  </system.web.extensions>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding>
          <!-- this is for demo only. Https/Transport security is recommended -->
          <security mode="None"/>
        </binding>
      </basicHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <services>
      <!-- this enables the WCF AuthenticationService endpoint -->
      <service name="System.Web.ApplicationServices.AuthenticationService">
        <endpoint binding="basicHttpBinding"
            bindingNamespace="http://asp.net/ApplicationServices/v200"
            contract="System.Web.ApplicationServices.AuthenticationService"/>
      </service>
    </services>
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

what was changed from the original configuration file:
a) Connections and membership were taken from previous project.
b) <system.web> has been extended with <authentication mode="Forms" />
c) Section <system.web.extensions> has been added. authenticationService has attribute requireSSL, which should be enabled in production
d) <system.serviceModel> has been extended with <Bindings> - it is optional, but I enabled anonymous access to service for testing purposes
e) <system.serviceModel> has been extended with <services>, which describe service (I didn't create behaviourName, so it uses default one)
f) <system.serviceModel> has <serviceHostingEnvironment> node, which was extended with attribute aspNetCompatibilityEnabled="true". It is very iportant parameter for this service, because it is relying on ASP.NET session.
To test service, you can set "POC.Authentication.Services" as strartup project, set "AuthenticationService.svc" as startup page and press F5.
It will run my lovely "WCF Test client". If you see following app, everything is set up properly.

WCF Test Client: Authentication Service



If you don't like port, which Visual Studio assigned for service, you can change it in project properties.
There is one more thing, which should be done if you want use clients, like silverlight and your wcf domain/port is different then silverlight app:
You have to enable cross-domain access to your wcf service. There eis goos article about it:
http://msdn.microsoft.com/en-us/library/cc197955(v=vs.95).aspx
in our case just add 2 files as shown below:

clientaccesspolicy.xml

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="SOAPAction">
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

crossdomain.xml

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <allow-http-request-headers-from domain="*" headers="SOAPAction,Content-Type"/>
</cross-domain-policy>


4. Client application


Client application can be any application, which will consume Authentication WCF service. I will be focus on some of them.

DAL - Data access layer


I will create multiple applications, so I will create one DAL class library, which will contain service reference to authentication service and helpers to work with cookies.
One of the conditions of current sample:
1) Authentication cookie name at service should match client form authentication cookie name
2) Encryption should be the same at service and client side
If conditions above are not accomplished, you have to create custom method to extract service authentication ticket and set it to client cookies and use that ticket every time you call services.

In Visual Studio create new class library project "POC.Authentication.DAL". Delete "Class1.cs" file. Add refernce to "System.ServiceModel".
Add service reference to existing authentication service with name "serviceAuthentication".

MS Visual Studio: Add WCF Service Reference



Add new class "ServiceHelper.cs"

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.ServiceModel.Channels;
using System.ServiceModel;
 
namespace POC.Authentication.DAL
{
    public static class ServiceHelper
    {
        public static string uriString = @"http://mypoc.com";
        public static CookieContainer GetCookies(OperationContext oc)
        {
            HttpResponseMessageProperty httpResponseProperty =
                (HttpResponseMessageProperty)oc.IncomingMessageProperties[HttpResponseMessageProperty.Name];
            if (httpResponseProperty != null)
            {
                CookieContainer cookieContainer = new CookieContainer();
                string header = httpResponseProperty.Headers[HttpResponseHeader.SetCookie];
                if (header != null)
                    cookieContainer.SetCookies(new Uri(uriString), header);
                return cookieContainer;
            }
            return null;
        }
 
        public static void SetCookies(OperationContext oc, CookieContainer cookieContainer)
        {
            HttpRequestMessageProperty httpRequestProperty = null;
            if (oc.OutgoingMessageProperties.ContainsKey(HttpRequestMessageProperty.Name))
                httpRequestProperty = oc.OutgoingMessageProperties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
            if (httpRequestProperty == null)
            {
                httpRequestProperty = new HttpRequestMessageProperty();
                oc.OutgoingMessageProperties.Add(HttpRequestMessageProperty.Name,
                    httpRequestProperty);
            }
            httpRequestProperty.Headers.Add(HttpRequestHeader.Cookie, cookieContainer.GetCookieHeader(new Uri(uriString)));
        }
 
        public static string GetCookieHeader(CookieContainer cookieContainer)
        {
            return cookieContainer.GetCookieHeader(new Uri(uriString));
        }
    }
}


The project will look like:

MS Visual Studio: Authentication DAL project


4.a) ASP.NET web site

In case of web site, client should support cookies, otherwise it will not work.
I am going to create simple web site with 2 pages only: default.aspx and login.aspx.
In Visual studio solution create ASP.NET empty application with name "POC.Authentication.Client.Web" and add 2 mentioned pages.
Add reference to "POC.Authentication.DAL" project and refernce to "System.ServiceModel".
Update web.config following way:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <authentication mode="Forms">
      <forms loginUrl="~/Login.aspx" path="/"/>
    </authentication>
    <authorization>
      <deny users="?" />
    </authorization>
  </system.web>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_1" closeTimeout="00:01:00"
          openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
          allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
          maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
          messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
          useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None"
              realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost.com:56511/AuthenticationService.svc"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_1"
        contract="serviceAuthentication.AuthenticationService" name="BasicHttpBinding_AuthenticationService" />
    </client>
  </system.serviceModel>
</configuration>

here are some comments about configuration:
a) <system.web> extended with <authentication> node, which sets forms authentication
b) <system.web> extended with <authorization>, which allow access to web site to authenticated users only
c) <system.serviceModel> defines WCF binding and <client> configuration to connect to authentication service. In endpoint address you shoudl set port, which was defined in authentication service project.
Update Default.aspx by adding
Welcome: <asp:LoginName ID="LoginName1" runat="server" />
Update Login.aspx by adding
<asp:Login ID="Login1" runat="server" onauthenticate="Login1_Authenticate"/>
Update Login.aspx.cs by adding

        protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
        {
            System.Net.CookieContainer cookieContainer = null;
            bool bLogin = false;
            POC.Authentication.DAL.serviceAuthentication.AuthenticationServiceClient authService = new DAL.serviceAuthentication.AuthenticationServiceClient();
            string customCredential = "Not used by the default membership provider.";
            using (new System.ServiceModel.OperationContextScope(authService.InnerChannel))
            {
                    bLogin = authService.Login(Login1.UserName, Login1.Password, customCredential, Login1.RememberMeSet);
                    cookieContainer = POC.Authentication.DAL.ServiceHelper.GetCookies(System.ServiceModel.OperationContext.Current);
            }
            if (bLogin == true)
            {
                //set authentication cookies
                Response.AddHeader("Set-Cookie", POC.Authentication.DAL.ServiceHelper.GetCookieHeader(cookieContainer));
                string strRedirect;
                strRedirect = Request["ReturnUrl"];
                if (strRedirect == null)
                    strRedirect = "default.aspx";
                Response.Redirect(strRedirect, true);
            }
        }


Now you can test it by seting "POC.Authentication.Client.Web" as startup project, "Default.aspx" as startup page and pressing F5.
Enter user name/password on login page.

ASP,NET Application: test authentication


If everything is ok, you will be redirected on default.aspx with welcome message.
Done.
What actually happening on web site? To understand it, I will use my favorite tool Fiddler.
I will do following changes to catch all http requests/responses coming to and from authentication service.
a) I will update web.config with putting this under <Configuration>

  <!--capture all requests from front-end to WCF services-->
  <system.net>
    <defaultProxy>
      <proxy proxyaddress="http://127.0.0.1:8888" usesystemdefault="False"/>
    </defaultProxy>
  </system.net>

It will allow send all outgoing requests via Fiddler proxy (By default, Fiddler captures all requests, coming from current user, but if your application uses different credentials it will not work. Method, described above allows catch everything coming from current web application).

b) I will update hosts file, located at <Windows folder>\System32\drivers\etc\hosts with this entry
127.0.0.1 localhost.com
it will make service accessible by localhost and localhost.com
and will update wcf service url from http://localhost:56511/AuthenticationService.svc to
http://localhost.com:56511/AuthenticationService.svc
(update port number with yours)
Now: start Fiddler and repeat the same testing steps, which you did before.
you should see following requests in Fiddler.

Fiddler: Authentication requests

If you double click on "Authentication.svc" request you will see request/response from service:

Fiddler: Authentication request/resposne


if you check cookies of service the response, you will see that service sends cookie, which contain authentication ticket:
Fiddler: Authentication service response - cookie


That is why we created helper class in DAL to extract cookies from service operational context.
if you double click on "default.aspx" request after redirection, you will see the same cookie, which were sent by authentication service.

Fiddler: Authentication Service Request - cookies


The achievement is: user is authenticated on web site + we can extract authentication ticket from cookies to authorize user for other service calls (I will describe that process in next article on the sample of Role Service).

4.b) MVC web site


MVC application is based on Model->View->Controller pattern. The application configuration is pretty same but implementation is slightly different.
Add new ASP.NET MVC 3 project "POC.Authentication.Client.WebMVC" to the existing solution.

MS Visual Studio: Create MVC3 Application


on the next step you will be prompted to select MVC project type. The easiest way for our scenario is to select MVC project with forms authentication:

MS Visual Studio: MVC3 Application creation properties


You can review existing project and you will find that it uses basic authentication and web.config has settings for the membership provider to connect to database.
Instead of direct database connection we will use authentication WCF service.
Project contains functionality, related with registration, but I will nor cover it in this artice and focusting on authentication process only.
We will add reference to existing DAL project, which was used in previous project:

MS Visual Studio: Add project reference to DAL


update web.config by removing <connectionstrings>, <membership>, <profile>, <rolemanager> and adding <system.serviceModel>, which we used in previous sample.
web.config should looks like:

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="webpages:Version" value="1.0.0.0"/>
    <add key="ClientValidationEnabled" value="true"/>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </assemblies>
    </compilation>
 
    <authentication mode="Forms">
      <forms loginUrl="~/Account/LogOn" timeout="2880" />
    </authentication>
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages"/>
      </namespaces>
    </pages>
  </system.web>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_1" closeTimeout="00:01:00"
          openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
          allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
          maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
          messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
          useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None"
              realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost.com:56511/AuthenticationService.svc"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_1"
        contract="serviceAuthentication.AuthenticationService" name="BasicHttpBinding_AuthenticationService" />
    </client>
  </system.serviceModel>
 
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
 
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

Update "AccountController.cs" action "public ActionResult LogOn(LogOnModel model, string returnUrl)" by following way:

        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                System.Net.CookieContainer cookieContainer = null;
                bool bLogin = false;
                POC.Authentication.DAL.serviceAuthentication.AuthenticationServiceClient authService = new DAL.serviceAuthentication.AuthenticationServiceClient();
                string customCredential = "Not used by the default membership provider.";
                using (new System.ServiceModel.OperationContextScope(authService.InnerChannel))
                {
                    bLogin = authService.Login(model.UserName, model.Password, customCredential, model.RememberMe);
                    cookieContainer = POC.Authentication.DAL.ServiceHelper.GetCookies(System.ServiceModel.OperationContext.Current);
                }
                if (bLogin == true)
                {
                    //set authentication cookies
                    //Response.AddHeader("Set-Cookie", POC.Authentication.DAL.ServiceHelper.GetCookieHeader(cookieContainer));
                    HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName);
                    cookie.Value = cookieContainer.GetCookies(new Uri(POC.Authentication.DAL.ServiceHelper.uriString))[FormsAuthentication.FormsCookieName].Value;
                    Response.SetCookie(cookie);
 
                    if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                        return Redirect(returnUrl);
                    else
                        return RedirectToAction("Index""Home");
                }
                else
                    ModelState.AddModelError("""The user name or password provided is incorrect.");
            }
 
            // If we got this far, something failed, redisplay form
            return View(model);
        }

as you can see, we deleted FormAuthentication methods with calling wcf service. There is one more change: instead of using Response.AddHeader we use
Response.SetCookie(cookie); because previous method doesn't work when you use MVC RedirectToAction.

//TODO: create helper

Run application, click on "Logon" link at the upper right corner of the web page and on appeared page enter user name/password.
MVC Application: Test authentication


Click "Log on" button and you will be redirected to home page, where you can see signed in user name. Uer name is rendered by _LogOnPartial.cshtml partial view by accessing User.Identity.Name.
Done.

4.c) Silverlight application


Current sample is not perfect solution but minimum configuration and minimum UI. In Silverlight there is new technology: RIA services, which is preferrebale for the Silverlight, but I want show that WCF is also good solution in Silverlight.

In Visual studio create new Silverlight application with name "POC.Authentication.Client.Silverlight".

MS Visual Studio: create Silverlight application

On the second step of the project creation, visual studio will prompt to select hosting for the silverlight. You hav an option to select existing web project or create new one.
I selected to create new one with name "POC.Authentication.Client.Silverlight.Web" - it will be used for silverlight testing:

MS Visual Studio: New Silverlight Application parameters


Next step is make referece to existing WCF authentication service. I would use DAL project, but I cannot make refernce to it from silverlight project - sucks.
Ok, back to the reality - when you add service reference with name "serviceAuthentication" you will see solution like this:




ServiceReferences.ClientConfig configuration file will contain wcf binding.

<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_AuthenticationService" maxBufferSize="2147483647"
                    maxReceivedMessageSize="2147483647">
                    <security mode="None" />
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:56511/AuthenticationService.svc"
                binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_AuthenticationService"
                contract="serviceAuthentication.AuthenticationService" name="BasicHttpBinding_AuthenticationService" />
        </client>
    </system.serviceModel>
</configuration>

Next step is update MainPage.xaml

<UserControl x:Class="POC.Authentication.Client.Silverlight.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
 
    <Grid x:Name="LayoutRoot" Background="White">
        <Button Content="Login" Height="23" HorizontalAlignment="Left" Margin="325,0,0,0" Name="btnLogin" VerticalAlignment="Top" Width="75" Click="loginControl_LoginClick" />
        <sdk:Label Height="17" HorizontalAlignment="Left" Margin="12,25,0,0" Name="lblUserName" VerticalAlignment="Top" Width="102" Content="User Name:" />
        <sdk:Label Height="17" HorizontalAlignment="Left" Margin="12,67,0,0" Name="lblPassword" VerticalAlignment="Top" Width="102" Content="Password:" />
        <PasswordBox Height="23" HorizontalAlignment="Left" Margin="149,67,0,0" Name="txtPassword" VerticalAlignment="Top" Width="131" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="149,25,0,0" Name="txtUserName" VerticalAlignment="Top" Width="130" />
        <sdk:Label Height="28" Margin="149,0,52,0" Name="statusText" VerticalAlignment="Top" Content="Not Signed in" />
        <sdk:Label Height="28" HorizontalAlignment="Left" Margin="12,0,0,0" Name="label3" VerticalAlignment="Top" Width="120" Content="Status:" />
    </Grid>
</UserControl>

and code behind "MainPage.xaml.cs":

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using POC.Authentication.Client.Silverlight.serviceAuthentication;
 
namespace POC.Authentication.Client.Silverlight
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            checkIfUserLoggedIn();
        }
 
        private void loginControl_LoginClick(object sender, RoutedEventArgs e)
        {
            serviceAuthentication.AuthenticationServiceClient client = new serviceAuthentication.AuthenticationServiceClient();
            if (btnLogin.Content.Equals("Login"))
            {
                client.LoginCompleted += new EventHandler<serviceAuthentication.LoginCompletedEventArgs>(client_LoginCompleted);
                client.LoginAsync(txtUserName.Text, txtPassword.Password, ""true, txtUserName.Text);
            }
            else
            {
                client.LogoutAsync();
                client.LogoutCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(client_LogoutCompleted);
            }
        }
 
        void client_LogoutCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            checkIfUserLoggedIn();
        }
 
        void checkIfUserLoggedIn()
        {
            serviceAuthentication.AuthenticationServiceClient client = new serviceAuthentication.AuthenticationServiceClient();
            client.IsLoggedInAsync("user1");
            client.IsLoggedInCompleted += new EventHandler<IsLoggedInCompletedEventArgs>(client_IsLoggedInCompleted);
        }
 
        void client_LoginCompleted(object sender, LoginCompletedEventArgs e)
        {
            ShowHideLogin(e.UserState,e.Result);
            bool loggedIn = e.Error == null;
            if (e.Error != null) statusText.Content = e.Error.ToString();
        }
 
        private void ShowHideLogin(object userState, bool loggedIn)
        {
            Visibility b = System.Windows.Visibility.Visible;
            if (loggedIn)
            {
                b = System.Windows.Visibility.Collapsed;
                statusText.Content = userState + " logged In result:" + loggedIn.ToString();
                btnLogin.Content = "Loged out";
            }
            else
            {
                statusText.Content = "Not logged In";
                btnLogin.Content = "Login";
            }
            txtUserName.Visibility = b;
            txtPassword.Visibility = b;
            lblUserName.Visibility = b;
            lblPassword.Visibility = b;
       
        }
 
        void client_IsLoggedInCompleted(object sender, IsLoggedInCompletedEventArgs e)
        {
            ShowHideLogin("", e.Result);
            if (e.Error != null) statusText.Content = e.Error.ToString();
        }
    }
}

The coding is done.

Test Silverlight solution

To set silverlight solution, set "POC.Authentication.Client.Silverlight.Web" as startup project and "POC.Authentication.Client.SilverlightTestPage.aspx" as start page.
When you run application, you will see following UI:



Just eneter user name/password and press login button. You will see logged in result as true nd you will see user name.
Every time application loaded i call additional method to check if user is logged in.

Silverlight Application  - Authentication process analysis in a fiddler:

To understand what is happening with application, I will review fiddler in silverlight application, which was created in previous sample.
1) on Application startup you can see following requests:

Fiddler: Silverlight Application - isLoggedIn request


as you can see, we have following requests to server:
http://localhost:8595/POC.Authentication.Client.SilverlightTestPage.aspx
http://localhost:56511/clientaccesspolicy.xml - client access policy for wcf service
http://localhost:56511/AuthenticationService.svc - calls isLoggedIn method. (fisrt time user is not logged in)

2) Signin process:
you will see just one call:
http://localhost:56511/AuthenticationService.svc - to call Login method.
You will be able to see user name and password. That is why is so important to use https protocol, so nobody can catch user name/password in plan format.

Fiddler: Silverlight Application - authentication process (requests)


If you will check response headers, you will see that response sets client cookies:

Fiddler: Authentication service response - set cookies

3) Authentication magic

For every next call, client will pass client cookies and you can use it as user authentication on wcf side. If you refresh browser page by Ctrl+F5 (Internet Explorer) you will see that next call will contain authentication cookies in request:
http://localhost:56511/AuthenticationService.svc - calls isLoggedIn method. (User is logged in)

Fiddler: Silverlight Application - passing authentication cookies in request


5.d) Apple IOS (iPhone/iPad)


For this type of application you should use MAC OS with installed XCode development tool. Your iPad/iPhone should have wired/wireless connection to the same network or internet where your service is located.


I published service to my company public domain and use internet connection for testing - real life scenario. You have many options to call WCF services from objective C. You should remember one thing: If you want create reusable code between MAC OS and IOS you should select framework carefully. MAC OS has one tool, called WSMakeStubs but it works very bad with complex services and it doesn't work with IOS.

You have following options here:
1) use old fashion way to send http request and parse response from server by converting response body to Xml and parse it to extract values
2) you can use 3rd party tool to generate proxy classes. The sad part of this - Xcode doesn't have built-in tool to do it, like Microsoft Visual Studio does. I checked some of libraries and will use WSDL2ObjC tool (version 0.7). It based on 1st method and generates proxy classes (at least it works with Authentication service without any problem).

ok. Here are steps to create iPhone application, which will consume WCF service:

Run Xcode and created iPhone Application:

XCode: Create iPhone App

Please, uncheck "Use Automatic reference Counting". The version of WSDL2ObjC is generating classes with no "ACR" - hope that next version will do it.

XCode: Project Sumary

Generate Proxy classes:

Run WSDL2ObjC application. You have to insert url to your WCF service wsdl in the first input text box and select path where generated classes will be located.

WSDL2ObjC

I created "Services" subfolder to keep generated classes out of application functionality. I added all generated files to the project, so you can see, what was generated in the result:

WSDL2ObjC: generated classes


Prepare iPhone application to use generated proxy classes:

As I mentioned before, WSDL2OBJC is based on work with generating http requests and parsing Response as an XML to classes. To make it work you have to make couple settings in project, which described here:
http://code.google.com/p/wsdl2objc/wiki/UsageInstructions



following print screens show what should be done:

XCode: Linked Frameworks and Libraries

XCode: Build Settings - Header Search Paths

XCode: Build Settings - Other Linker Flags

Your project is compilable now.

Pepare iPhone Application UI:

I am using Xcode version 4.3.2 and my Ui will be based on StoryBoard. I will update home view as shown below

XCode: home view

Default View contains user name label and Sign-in button if user is not signed in. When user will click on "Sign-in" button he will see login screen. I created another view this way.

XCode: login view

For the Login View I created another controller with name "LoginViewController", which will contain login functionality.



XCode: add view controller



Next step is to create Seques between Views (views flow).
First seque will be from "Sign-in" button to "LoginView". I simply clicked on "Sign-in" button once and dragged arrow to Login View. I also set name "PerformLoginSeque" to created seque.

XCode: create seque

Another seque will be back from login view back to home view. In this case links will be from view to view directly (no controls involved). I set name "PerformBackToMainSeque" for that one.

Update ViewControllers with code:

ViewController


a) ViewController.h source code


#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UIActionSheetDelegate, UIAlertViewDelegate>
@property (retain) NSString  *userName;
@property (retain) NSHTTPCookie  *authToken;

@property (retain, nonatomic) IBOutlet UILabel *lblUserName;
@property (retain, nonatomic) IBOutlet UIButton *btnSignIn;

@end



b) ViewController.m source code


#import "ViewController.h"
#import "LoginViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize lblUserName;
@synthesize btnSignIn;

@synthesize userName;
@synthesize authToken;

- (void)viewDidLoad
{
    [super viewDidLoad];

    //Check if user is Authenticated
    //TODO: add logic to call service by applying authToken
    NSString* usertext=@"";
    if (self.userName==NULL)
    {
        usertext = @"You are not signed in.";
    }
    else {
        btnSignIn.hidden = true;
        usertext =[NSString stringWithFormat:@"%@ %@ \nToken: %@", @"You successfully signed in as user:", self.userName, self.authToken];
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Info" message:usertext delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil , nil];
        [alertView show];
    }
    [lblUserName setText: usertext ];
}

- (void)viewDidUnload
{
    [self setLblUserName:nil];
    [self setBtnSignIn:nil];
    
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}


- (void)dealloc {
    [lblUserName release];
    [btnSignIn release];
    [super dealloc];
}
@end

LoginViewController


To have access to controls at view level from controller you have to inherit view from  LoginViewController.

XCode: associate view with controller


Make sure "Assistance Editor" is visible.

XCode: display Assistant Editor

Next step is to create IBOutlets for every control, which you will have access to.

Xcode: Make textbox as public property of the controller

Xcode: Specify connection type

To handle events from "Login" and "Cancel" button you have to create IBActions. Do the same as was described in previous step, but use IBAction in connection type.

As for LoginViewController:
In my sample i will make asynchronous call, so it is very important to make delegation from "BasicHttpBinding_AuthenticationServiceBindingResponseDelegate" class. I will also pass user name and authentication cookie (token) to home form. That is why I implemented prepareForSegue method.
Don't forget to add

#import "AuthenticationServiceSvc.h"



Full source code for "LoginViewController.h" and "LoginViewController.m"is shown below.


c) LoginViewController.h source code 

#import <UIKit/UIKit.h>
#import "AuthenticationServiceSvc.h"

@interface LoginViewController : UIViewController <BasicHttpBinding_AuthenticationServiceBindingResponseDelegate, UIAlertViewDelegate>
@property (retain, nonatomic) IBOutlet UITextField *txtUserName;
@property (retain, nonatomic) IBOutlet UITextField *txtPassword;
@property BOOL isAuthenticated;
@property (assign) NSHTTPCookie *authToken;
- (IBAction)btnCancel_Click:(UIButton *)sender;
- (IBAction)btnLogin_Click:(UIButton *)sender;

@end

c) LoginViewController.m source code 

#import "LoginViewController.h"
#import "ViewController.h"

#import "AuthenticationServiceSvc.h"
@interface LoginViewController ()

@end

@implementation LoginViewController
@synthesize txtUserName;
@synthesize txtPassword;
@synthesize isAuthenticated;
@synthesize authToken;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view.
}

- (void)viewDidUnload
{
    [txtUserName release];
    [txtPassword release];
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (IBAction)btnLogin_Click:(UIButton *)sender {
    BasicHttpBinding_AuthenticationServiceBinding *b = nil;
    @try {
    
    b = [[AuthenticationServiceSvc BasicHttpBinding_AuthenticationServiceBinding] retain];
    b.logXMLInOut = YES;
    b.authUsername = @"";
    b.authPassword = @"";
    b.cookies = nil;
    
    
    AuthenticationServiceSvc_Login *cRequest = [[AuthenticationServiceSvc_Login alloc] autorelease];
    cRequest.username = txtUserName.text;; //@"user1";
    cRequest.password =txtPassword.text; //@"Pwd2";
    cRequest.isPersistent = NO;
    
    //do asynchronious call
    [b LoginAsyncUsingParameters:cRequest delegate:self]; 
    }
    @catch (NSException * e) {
        NSLog(@"Exception: %@", e); 
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Alert" message:e.description delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil , nil];
        [alertView show];
    }
@finally {
    [b release];
    }
}

//receive async call to Authenticate service
- (void) operation:(BasicHttpBinding_AuthenticationServiceBindingOperation *)operation completedWithResponse:(BasicHttpBinding_AuthenticationServiceBindingResponse *)response
{
        @try {

    
    //check reponse error
    if (response!=nil)
    {
        if (response.error!=nil)
        {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Alert" message:response.error.description delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil , nil];
            [alertView show];
            
            return;
        }
        NSArray *responseHeaders = response.headers;
        NSArray *responseBodyParts = response.bodyParts;
    
    for(id bodyPart in responseBodyParts) {
        /****
         * SOAP Fault Error
         ****/
        if ([bodyPart isKindOfClass:[SOAPFault class]]) {
            //Display message that error happened 
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Alert" message:((SOAPFault *)bodyPart).simpleFaultString delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil , nil];
            [alertView show];
            break;
        }
        
        //get response
        AuthenticationServiceSvc_LoginResponse *loginRespponse = (AuthenticationServiceSvc_LoginResponse *)bodyPart;
        if (loginRespponse.LoginResult.boolValue)
        {
            self.isAuthenticated = YES; //mark that user is authenticated
            
            //extract authentiction token from header  
            for (NSHTTPCookie *cookie in operation.binding.cookies) {
               //NSLog(@"Cookie:\n%@-%@",cookie.name, cookie.value); //NSHTTPCookie
                NSLog(@"Cookie:\n%@",cookie.description);
                self.authToken = cookie;
            }
            for(id header in responseHeaders) {
                // here do what you want with the headers, if there's anything of value in them
            }
            
            //check if response is ok and redirect user back to main page
            [self performSegueWithIdentifier:@"PerformBackToMainSeque" sender:self];
        }
        else {
            //Display message that error happened 
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Check user name/password and try again." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil , nil];
            [alertView show];
            
        }
    }
    }
    
    }
    @catch (NSException * e) {
        NSLog(@"Exception: %@", e); 
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Alert" message:e.description delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil , nil];
        [alertView show];
    }
    
}

-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"PerformBackToMainSeque"])
    {   
        if (self.isAuthenticated) //check if user is authenticated
        {
            ViewController *vc = [segue destinationViewController];
            vc.userName =txtUserName.text; //pass user name to main view
            vc.authToken = self.authToken; //token should be taken from service call
        }
    }
}

- (IBAction)btnCancel_Click:(UIButton *)sender {
   [self performSegueWithIdentifier:@"PerformBackToMainSeque" sender:self]; 
}


@end


iPhone application coding is Done.

Run iPhone Application to test Authentication service:

To test application make sure you set "iPhone 5.1 simulator" (where 5.1 is my current IOS version on iPhone and iPad. Yours can be different).

XCode: select simulator

Run application by pressing "Command+R". You will see home screen with message that user is not authenticated. Click on "Sign-in" button and you will see login screen.

XCode: Test application - Home view

On login screen enter user name and password, which you used in previous samples. You have 2 cases here: successful authentication and failure (failure can happen by different reasons, like user name/password is not valid or technical problems, like service/network connection unavailable)

XCode: Test application - Login View

In case of technical problems, like network issue you can see something like this:

XCode: Test application - No Internet Connection


If everything is ok, you will be redirected to home view. Home view will display message, which contains "Authentication Cookie", generated by service and extracted by application from response cookies. You can use that cookie to pass as authentication token in futures calls.

XCode: Test application - successful login


Current sample shows basics how to use Authentication service, but you can extend this idea for your own purposes.