<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>NathanHJones.com &#187; mobile</title>
	<atom:link href="http://nathanhjones.com/category/mobile/feed/" rel="self" type="application/rss+xml" />
	<link>http://nathanhjones.com</link>
	<description>just thinking outloud</description>
	<lastBuildDate>Fri, 11 Nov 2011 06:55:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>A Single Sign-on Pattern for Enterprise iOS Applications</title>
		<link>http://nathanhjones.com/2011/11/11/a-single-sign-on-pattern-for-enterprise-ios-applications/</link>
		<comments>http://nathanhjones.com/2011/11/11/a-single-sign-on-pattern-for-enterprise-ios-applications/#comments</comments>
		<pubDate>Fri, 11 Nov 2011 06:30:32 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[business]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[enterprise]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[iphone sdk]]></category>
		<category><![CDATA[mSSO]]></category>
		<category><![CDATA[single sign-on]]></category>
		<category><![CDATA[SSO]]></category>

		<guid isPermaLink="false">http://nathanhjones.com/?p=341</guid>
		<description><![CDATA[In conversations with clients, we continue to hear how important single sign-on is to their enterprise mobile application strategy. According to a study earlier this year by Kelton Research 250 IT Managers, 21% of respondents indicated that they plan to deploy 20, or more, enterprise applications to their organization this year. In order for enterprises [...]]]></description>
			<content:encoded><![CDATA[<p>
In conversations with clients, we continue to hear how important single sign-on is to their enterprise mobile application strategy.  According to a <a href="http://www.echannelline.com/usa/story.cfm?item=26463">study earlier this year by Kelton Research 250 IT Managers</a>, 21% of respondents indicated that they plan to deploy 20, or more, enterprise applications to their organization this year.
</p>
<p>
In order for enterprises to realize the productivity gains factored into the investment decisions for those applications, IT Managers must explore options for enabling single sign-on for their users. In this post, we&#8217;ll outline a mobile single sign-on (mSSO) pattern for enterprise iOS applications.
</p>
<h2>Assumptions</h2>
<ol>
<li>Your company has a centralized single sign-on service exposed on the network &#8211; LDAP, Novell Access Manager, etc. This approach will work with a number of identity management architectures, but you will need to tailor credential management accordingly. For this demo, our service calls are simulated with hardcoded tokens.</li>
<li>Your company has a standardized credential timeout period or a way of dynamically distributing that value to applications. For this demo, we&#8217;ll use a static 30 minute timeout period.</li>
<li>You are able to sign and distribute builds to a device. This is important because keychain activities do not function in the simulator.</li>
</ol>
<h2>Implementation</h2>
<h4>Approach</h4>
<p>
Our approach will consist of creating three applications &#8211; two mock business applications and one logout application. Each application may contain its own logout functionality, but a single logout application makes the user&#8217;s activity of killing a session intuitive.  In practice, the mSSO pattern would be implemented as a stand-alone library which could be easily dropped into each of your various enterprise applications.
</p>
<p>
The business applications retrieve a unique authentication token which is included with each service request.  This token will be stored in the device&#8217;s <a href="http://developer.apple.com/library/ios/#documentation/Security/Reference/keychainservices/Reference/reference.html">keychain</a>, which will be shared across our suite of applications.  We will also maintain an &#8216;expiration date&#8217; within the keychain so that subsequent requests from our various apps can (if required) preemptively prompt the user to authenticate.
</p>
<p>
Authentication for this demo may be simplistic, but <a href="http://blogs.captechconsulting.com/blog/jack-cox/managing-complex-mobile-transactions">existing patterns</a> cover implementing authentication in a service-based mobile application.  For example, the &#8216;store credentials&#8217; logic presented in this example would live somewhere in that pattern&#8217;s &#8220;authenticateOperation&#8221;.
</p>
<p>
One possible extension of the mSSO pattern is to confirm that your credentials have not expired before issuing a call to the service.  You would use the mSSO pattern to sign your network requests, but rely on the service and response handlers to inform you that credentials have expired.  Checking credential expiration prior to making a service call limits unnecessary network traffic.
</p>
<h4>Configuration</h4>
<p>
There are two key steps that must be completed in order for your applications to share keychain access.</p>
<ol>
<li>Each application included in your mSSO effort must share a Bundle Seed ID, which allows shared keychain access between our suite of applications. This is configured within the <a href="http://developer.apple.com/ios/manage/overview/index.action">iOS management portal</a>. We&#8217;ll configure our applications using the default &#8216;Team ID&#8217; selection.</li>
<p><a href="http://nathanhjones.com/wp-content/uploads/2011/11/app1.png"><img src="http://nathanhjones.com/wp-content/uploads/2011/11/app1-300x136.png" alt="" title="app1" width="300" height="136" class="aligncenter size-medium wp-image-354" /></a><br />
<a href="http://nathanhjones.com/wp-content/uploads/2011/11/end-result.png"><img src="http://nathanhjones.com/wp-content/uploads/2011/11/end-result-300x61.png" alt="" title="end-result" width="300" height="61" class="aligncenter size-medium wp-image-355" /></a></p>
<li>We also need to enable and add an entitlements file that specifies that this application should be able to access the shared keychain. <span style="font-weight:bold;">This step is done after the Xcode project has been created.</span></li>
<ul>
<li>Select your app target in Xcode and choose the &#8216;Summary&#8217; tab.</li>
<li>Choose &#8216;Enable Entitlements&#8217; at the bottom.</li>
<li>Set the Entitlements File name to &#8220;mSSO&#8221; and hit return. Select &#8216;Create&#8217; when prompted.</li>
<li>Unless needed for your application, remove iCloud configuration settings.</li>
<li>Add a keychain value titled &#8220;mSSO&#8221;, our Bundle Seed ID is prepended to this value for us.</li>
<p><a href="http://nathanhjones.com/wp-content/uploads/2011/11/app-target-entitlements.png"><img src="http://nathanhjones.com/wp-content/uploads/2011/11/app-target-entitlements-300x137.png" alt="" title="app-target-entitlements" width="300" height="137" class="aligncenter size-medium wp-image-360" /></a><br />
<a href="http://nathanhjones.com/wp-content/uploads/2011/11/mSSO-entitlements-file.png"><img src="http://nathanhjones.com/wp-content/uploads/2011/11/mSSO-entitlements-file-300x35.png" alt="" title="mSSO-entitlements-file" width="300" height="35" class="aligncenter size-medium wp-image-361" /></a>
</ul>
</ol>
<h4>Development</h4>
<p>
We&#8217;ll walk through how to create App1 in detail, and then let you work through App2 and the Logout application. Let&#8217;s start by opening Xcode and creating a single view application.  Before we get started, add the Security.framework and create your entitlement files as outlined above.  <a href="http://useyourloaf.com/blog/2010/3/29/simple-iphone-keychain-access.html" target="_blank">Here</a> is a good primer for interacting with the keychain.
</p>
<ol>
<li>Add the custom <code>mSSOUtils</code> and <code>DateUtils</code> classes as outlined below.  Make sure that you import accordingly.  Due to changes in iOS related to <a href="http://developer.apple.com/library/ios/#releasenotes/General/WhatsNewIniPhoneOS/Articles/iOS5.html#//apple_ref/doc/uid/TP30915195-SW4">ARC</a> (developer account required), you will need to disable ARC for the <code>mSSOUtils</code> class.  You can do so by selecting your target in Xcode and viewing the <span style="font-weight:bold;">Build Phases</span> tab. Expand the <span style="font-weight:bold;">Compile Sources</span> section and double click the <code>mSSOUtils</code> class to add the <code>-fno-objc-arc</code> compiler flag.  You may need to clean and build.<br />
<span style="font-weight:bold;">mSSOUtils:</span></p>

<div class="wp_codebox"><table><tr id="p3418"><td class="code" id="p341code8"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#define kmSSOKeychainGroup @&quot;3Q4M6DQ9WM.mSSO&quot;</span>
<span style="color: #6e371a;">#define kAuthenticationServiceName @&quot;com.captechconsulting.msso&quot;</span>
<span style="color: #6e371a;">#define kCredentialToken @&quot;mSSOAuthenticationToken&quot;</span>
<span style="color: #6e371a;">#define kCredentialExpiration @&quot;mSSOCredentialsExpirationDate&quot;</span>
<span style="color: #6e371a;">#define kExpirationTimeout 60.0 * 30    // 30 minute timeout</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// *** PRIVATE METHODS DEF *** //</span>
<span style="color: #a61390;">@interface</span> mSSOUtils <span style="color: #002200;">&#40;</span>Private<span style="color: #002200;">&#41;</span>
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSMutableDictionary</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> keychainSearch<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>identifier;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> getValueForIdentifier<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>identifer;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span> setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>value forIdentifier<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>identifier;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> deleteValueForIdentifier<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>identifier;
<span style="color: #a61390;">@end</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> mSSOUtils<span style="color: #002200;">:</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span> authenticateWithUsername<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>username andPassword<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>password <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// for testing purposes, each call to this method authenticates successfully</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// set the token - app specific - change this in your App2 implementation</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self setValue<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;TokenSetFromApp1&quot;</span> forIdentifier<span style="color: #002200;">:</span>kCredentialToken<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// token set, now set the credential expiration</span>
        <span style="color: #002200;">&#91;</span>self extendCredentials<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Unable to set token.&quot;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> logout <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// destroy token AND expiration date</span>
    <span style="color: #002200;">&#91;</span>self deleteValueForIdentifier<span style="color: #002200;">:</span>kCredentialToken<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self deleteValueForIdentifier<span style="color: #002200;">:</span>kCredentialExpiration<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// credential management</span>
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> extendCredentials <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSDate</span> <span style="color: #002200;">*</span>newExpireDate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>DateUtils dateWithTimeout<span style="color: #002200;">:</span>kExpirationTimeout<span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>newExpireString <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>DateUtils stringFromDate<span style="color: #002200;">:</span>newExpireDate withFormat<span style="color: #002200;">:</span>kDateFormat<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">BOOL</span> success <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self setValue<span style="color: #002200;">:</span>newExpireString forIdentifier<span style="color: #002200;">:</span>kCredentialExpiration<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>success<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Unable to extend credentials.&quot;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span> credentialsExpired <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// if no token exists, call credentials expired</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self credentialToken<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #400080;">NSDate</span> <span style="color: #002200;">*</span>expirationDate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self credentialExpirationDate<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>expirationDate<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// check for expiration</span>
        <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>DateUtils dateInPast<span style="color: #002200;">:</span>expirationDate<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// if there is no expiration date, default to 'expired'</span>
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #11740a; font-style: italic;">// sign the request with current credentials - we'll add the token as an HTTP header field</span>
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSMutableURLRequest</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> signRequest<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSMutableURLRequest</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>request <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>token <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self credentialToken<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>token<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>request addValue<span style="color: #002200;">:</span>token forHTTPHeaderField<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;auth-token&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> request;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// methods to retrieve credential information</span>
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> credentialToken <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>token <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self getValueForIdentifier<span style="color: #002200;">:</span>kCredentialToken<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> token;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDate</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> credentialExpirationDate <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>expirationDateString <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self getValueForIdentifier<span style="color: #002200;">:</span>kCredentialExpiration<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>expirationDateString<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// convert to date</span>
        <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>DateUtils dateFromString<span style="color: #002200;">:</span>expirationDateString withFormat<span style="color: #002200;">:</span>kDateFormat<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">nil</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> displayAuthenticateView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIViewController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>vc <span style="color: #002200;">&#123;</span>
    authenticateViewController <span style="color: #002200;">*</span>authenticateView <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>authenticateViewController alloc<span style="color: #002200;">&#93;</span> initWithNibName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;authenticateViewController&quot;</span> bundle<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    UINavigationController <span style="color: #002200;">*</span>nc <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UINavigationController alloc<span style="color: #002200;">&#93;</span> initWithRootViewController<span style="color: #002200;">:</span>authenticateView<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>vc presentModalViewController<span style="color: #002200;">:</span>nc animated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #6e371a;">#pragma mark -</span>
<span style="color: #6e371a;">#pragma mark PRIVATE METHODS</span>
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSMutableDictionary</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> keychainSearch<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>identifier <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSMutableDictionary</span> <span style="color: #002200;">*</span>keychainSearch <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableDictionary</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>keychainSearch setObject<span style="color: #002200;">:</span>kmSSOKeychainGroup forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecAttrAccessGroup<span style="color: #002200;">&#93;</span>;   <span style="color: #11740a; font-style: italic;">// inform the search that we're using the shared keychain</span>
    <span style="color: #002200;">&#91;</span>keychainSearch setObject<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecClassGenericPassword forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecClass<span style="color: #002200;">&#93;</span>;   <span style="color: #11740a; font-style: italic;">// set the type to generic password - other options are certification, internet password, etc</span>
&nbsp;
    <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>encodedIdentifier <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>identifier dataUsingEncoding<span style="color: #002200;">:</span>NSUTF8StringEncoding<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>keychainSearch setObject<span style="color: #002200;">:</span>encodedIdentifier forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecAttrGeneric<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>keychainSearch setObject<span style="color: #002200;">:</span>encodedIdentifier forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecAttrAccount<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>keychainSearch setObject<span style="color: #002200;">:</span>kAuthenticationServiceName forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecAttrService<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> keychainSearch;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> getValueForIdentifier<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>identifier <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSMutableDictionary</span> <span style="color: #002200;">*</span>search <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self keychainSearch<span style="color: #002200;">:</span>identifier<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>search setObject<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecMatchLimitOne forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecMatchLimit<span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">// limit it to the first result</span>
    <span style="color: #002200;">&#91;</span>search setObject<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kCFBooleanTrue forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecReturnData<span style="color: #002200;">&#93;</span>;    <span style="color: #11740a; font-style: italic;">// return data vs a dictionary of attributes</span>
&nbsp;
    <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>value <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
    OSStatus status <span style="color: #002200;">=</span> SecItemCopyMatching<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CFDictionaryRef<span style="color: #002200;">&#41;</span>search,
                                          <span style="color: #002200;">&#40;</span>CFTypeRef <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&amp;</span>value<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>status <span style="color: #002200;">==</span> noErr<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithUTF8String<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>value bytes<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">nil</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span> setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>value forIdentifier<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>identifier <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// check if value exists</span>
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>existingValue <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self getValueForIdentifier<span style="color: #002200;">:</span>identifier<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>existingValue<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>existingValue isEqualToString<span style="color: #002200;">:</span>value<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #11740a; font-style: italic;">// update value</span>
            <span style="color: #400080;">NSMutableDictionary</span> <span style="color: #002200;">*</span>search <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self keychainSearch<span style="color: #002200;">:</span>identifier<span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>valueData <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>value dataUsingEncoding<span style="color: #002200;">:</span>NSUTF8StringEncoding<span style="color: #002200;">&#93;</span>;
            <span style="color: #400080;">NSMutableDictionary</span> <span style="color: #002200;">*</span>update <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableDictionary</span> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>valueData, <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecValueData, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
            OSStatus status <span style="color: #002200;">=</span> SecItemUpdate<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CFDictionaryRef<span style="color: #002200;">&#41;</span>search,
                                            <span style="color: #002200;">&#40;</span>CFDictionaryRef<span style="color: #002200;">&#41;</span>update<span style="color: #002200;">&#41;</span>;
&nbsp;
            <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>status <span style="color: #002200;">==</span> errSecSuccess<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
            <span style="color: #002200;">&#125;</span>
            <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
        <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #11740a; font-style: italic;">// create new entry</span>
        <span style="color: #400080;">NSMutableDictionary</span> <span style="color: #002200;">*</span>add <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self keychainSearch<span style="color: #002200;">:</span>identifier<span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>valueData <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>value dataUsingEncoding<span style="color: #002200;">:</span>NSUTF8StringEncoding<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>add setObject<span style="color: #002200;">:</span>valueData forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecValueData<span style="color: #002200;">&#93;</span>;
&nbsp;
        OSStatus status <span style="color: #002200;">=</span> SecItemAdd<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CFDictionaryRef<span style="color: #002200;">&#41;</span>add,<span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>status <span style="color: #002200;">==</span> errSecSuccess<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
        <span style="color: #002200;">&#125;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
&nbsp;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> deleteValueForIdentifier<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>identifier <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSMutableDictionary</span> <span style="color: #002200;">*</span>search <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self keychainSearch<span style="color: #002200;">:</span>identifier<span style="color: #002200;">&#93;</span>;
    SecItemDelete<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CFDictionaryRef<span style="color: #002200;">&#41;</span>search<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p><span style="font-weight:bold;">DateUtils:</span></p>

<div class="wp_codebox"><table><tr id="p3419"><td class="code" id="p341code9"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDate</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> dateFromString<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #a61390;">string</span> withFormat<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>format <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSDateFormatter</span> <span style="color: #002200;">*</span>dateFormatter <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDateFormatter</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>dateFormatter setDateFormat<span style="color: #002200;">:</span>format<span style="color: #002200;">&#93;</span>;
	<span style="color: #400080;">NSDate</span> <span style="color: #002200;">*</span>date <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>dateFormatter dateFromString<span style="color: #002200;">:</span><span style="color: #a61390;">string</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #a61390;">return</span> date;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> stringFromDate<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDate</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>date withFormat<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>format; <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSDateFormatter</span> <span style="color: #002200;">*</span>dateFormatter <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDateFormatter</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>dateFormatter setDateFormat<span style="color: #002200;">:</span>format<span style="color: #002200;">&#93;</span>;
	<span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>dateString <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>dateFormatter stringFromDate<span style="color: #002200;">:</span>date<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> dateString;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDate</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> dateWithTimeout<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSTimeInterval<span style="color: #002200;">&#41;</span>timeout <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSDate</span> <span style="color: #002200;">*</span>now <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDate</span> date<span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSDate</span> <span style="color: #002200;">*</span>timeoutDate <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>now dateByAddingTimeInterval<span style="color: #002200;">:</span>timeout<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> timeoutDate;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span> dateInPast<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDate</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>date <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>date compare<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDate</span> date<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> NSOrderedAscending<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

</li>
<li>Within the generated <code>ViewController</code>, add two <code>UILabel</code> outlets/properties &#8211; token and expiration date &#8211; and a &#8220;Logout&#8221; button.  You&#8217;ll need to add two custom methods: logout and a selector to handle the foreground notification we register to receive.

<div class="wp_codebox"><table><tr id="p34110"><td class="code" id="p341code10"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span> logout<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>mSSOUtils logout<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>mSSOUtils displayAuthenticateView<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> enterForeground<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// reset labels as we've entered the foreground</span>
    self.token.text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>mSSOUtils credentialToken<span style="color: #002200;">&#93;</span>;
    self.expiration.text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>DateUtils stringFromDate<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>mSSOUtils credentialExpirationDate<span style="color: #002200;">&#93;</span> withFormat<span style="color: #002200;">:</span>kDateFormat<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

</li>
<li>You should only need to update two view lifecycle methods within <code>ViewController</code> &#8211; <code>viewDidLoad</code> and <code>viewWillAppear</code>.  Within <code>viewDidLoad</code>, we register to receive a notification when the app is brought to the foreground that triggers our UI updates.  The additions to <code>viewWillAppear</code> simply update our labels if there is data in the keychain.

<div class="wp_codebox"><table><tr id="p34111"><td class="code" id="p341code11"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewDidLoad <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super viewDidLoad<span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">// register for enter foreground notification to update labels</span>
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNotificationCenter</span> defaultCenter<span style="color: #002200;">&#93;</span> addObserver<span style="color: #002200;">:</span>self 
                                             selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>enterForeground<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>
                                                 name<span style="color: #002200;">:</span>UIApplicationWillEnterForegroundNotification
                                               object<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewWillAppear<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>animated <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super viewWillAppear<span style="color: #002200;">:</span>animated<span style="color: #002200;">&#93;</span>;
&nbsp;
    self.token.text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>mSSOUtils credentialToken<span style="color: #002200;">&#93;</span>;
    self.expiration.text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>DateUtils stringFromDate<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>mSSOUtils credentialExpirationDate<span style="color: #002200;">&#93;</span> withFormat<span style="color: #002200;">:</span>kDateFormat<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

</li>
<li>Add an <code>authenticateViewController</code> to your project. This will be displayed modally when the users credentials need to be re-challenged. This example simply has a login button, but this is where you would include typical login fields.

<div class="wp_codebox"><table><tr id="p34112"><td class="code" id="p341code12"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span> authenticate<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// if authentication is successful, dismiss the view</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>mSSOUtils authenticateWithUsername<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;username&quot;</span> andPassword<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;hashedPassword&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>self dismissModalViewControllerAnimated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>   
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

</li>
<li>Last up, we&#8217;ll need to update our application delegate to confirm our credentials are valid when the app launches or is brought back from the background.  You&#8217;ll need to update the <code>didFinishLaunchingWithOptions</code> and <code>applicationWillEnterForeground</code> methods as noted below:

<div class="wp_codebox"><table><tr id="p34113"><td class="code" id="p341code13"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>application<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIApplication <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>application didFinishLaunchingWithOptions<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>launchOptions <span style="color: #002200;">&#123;</span>
    self.window <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIWindow alloc<span style="color: #002200;">&#93;</span> initWithFrame<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIScreen mainScreen<span style="color: #002200;">&#93;</span> bounds<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">// Override point for customization after application launch.</span>
    self.viewController <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>ViewController alloc<span style="color: #002200;">&#93;</span> initWithNibName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;ViewController&quot;</span> bundle<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    self.window.rootViewController <span style="color: #002200;">=</span> self.viewController;
    <span style="color: #002200;">&#91;</span>self.window makeKeyAndVisible<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// credentials don't exist or are expired - display the authenticate view</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>mSSOUtils credentialsExpired<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>mSSOUtils displayAuthenticateView<span style="color: #002200;">:</span>self.viewController<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>applicationWillEnterForeground<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIApplication <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>application <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// credentials don't exist or are expired - display the authenticate view</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>mSSOUtils credentialsExpired<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>mSSOUtils displayAuthenticateView<span style="color: #002200;">:</span>self.viewController<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

</li>
<li>Now, rinse and repeat for App2.  You can follow the same steps for the Logout application, but you really just need a single view that calls <code>[mSSOUtils logout]</code> on launch and informs the user their credentials have been terminated.

<div class="wp_codebox"><table><tr id="p34114"><td class="code" id="p341code14"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>application<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIApplication <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>application didFinishLaunchingWithOptions<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>launchOptions <span style="color: #002200;">&#123;</span>
    self.window <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIWindow alloc<span style="color: #002200;">&#93;</span> initWithFrame<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIScreen mainScreen<span style="color: #002200;">&#93;</span> bounds<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">// Override point for customization after application launch.</span>
    self.viewController <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>ViewController alloc<span style="color: #002200;">&#93;</span> initWithNibName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;ViewController&quot;</span> bundle<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    self.window.rootViewController <span style="color: #002200;">=</span> self.viewController;
    <span style="color: #002200;">&#91;</span>self.window makeKeyAndVisible<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// logout to kill credentials</span>
    <span style="color: #002200;">&#91;</span>mSSOUtils logout<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>applicationWillEnterForeground<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIApplication <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>application <span style="color: #002200;">&#123;</span>   
    <span style="color: #11740a; font-style: italic;">// logout to kill credentials</span>
    <span style="color: #002200;">&#91;</span>mSSOUtils logout<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

</li>
</ol>
<p>
Here are a couple helpful hints while developing your solution:</p>
<ul>
<li>We&#8217;ve disabled ARC for the <code>mSSOUtils</code> class, which means you need to handle memory management yourself.</li>
<li>When building your application, if you get a Mach-O Linker error, ensure that you&#8217;ve added the Security.framework.</li>
</ul>
<h4>Testing</h4>
<p>
Our testing won&#8217;t get too crazy, but at this point you should be all set to install our suite of apps on your device.
</p>
<p>
We&#8217;ll start by opening App1 and simulating an authentication call. Once the modal view is dismissed, our token and expiration date should be updated &#8211; expiration being now + 30 minutes.  From here, jump to App2 where you should see the App1 token/expiration. Logout and re-authenticate within App2, which will update our token and expiration date.  Now, we&#8217;ll wait 30 minutes and test whether our token expires. After 30 minutes, open App1, you should be prompted with an authentication view.  Authenticate and then open the Logout app.  Enter App2 from the multi-task tray, you should be prompted to authenticate once again.
</p>
<p>
The test sequence above has been captured in the screenshots below.  Note: for brevity, I&#8217;ve excluded screenshots of each authentication view except for the final step.<br />
<a href="http://nathanhjones.com/wp-content/uploads/2011/11/mSSO-Testing.jpg"><img src="http://nathanhjones.com/wp-content/uploads/2011/11/mSSO-Testing-300x143.jpg" alt="" title="mSSO Testing" width="300" height="143" class="aligncenter size-medium wp-image-374" /></a>
</p>
<h4>Closing</h4>
<p>
This post presents a pattern for implementing single sign-on for your enterprise iOS applications. It should give you the foundation needed to begin implementing single sign-on in your applications. I&#8217;ve attached the source for App1. If you&#8217;ve got questions or are interested in additional source files, I&#8217;m <a href="http://twitter.com/nathanhjones">@nathanhjones</a> on Twitter.
</p>
<div style="border: 1px solid #cdcdcd; background-color: #ffffff; padding: 10px 0 10px 10px;">
<span style="font-weight:bold;">Project files:</span> <a href="http://nathanhjones.com/wp-content/uploads/2011/11/mssoapp1.zip">mssoapp1.zip</a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://nathanhjones.com/2011/11/11/a-single-sign-on-pattern-for-enterprise-ios-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google AdWords gets partial HTML5 makeover</title>
		<link>http://nathanhjones.com/2010/09/15/google-adwords-gets-partial-html5-makeover/</link>
		<comments>http://nathanhjones.com/2010/09/15/google-adwords-gets-partial-html5-makeover/#comments</comments>
		<pubDate>Thu, 16 Sep 2010 03:48:55 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[adwords]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[local storage]]></category>

		<guid isPermaLink="false">http://nathanhjones.com/?p=279</guid>
		<description><![CDATA[It&#8217;s been a while since I&#8217;ve posted but I saw something this evening that I thought was worth posting.  I&#8217;ve been spending a lot of my free time lately developing and promoting an iPhone app.  I&#8217;ve got a second in process so this whole process has been a great learning experience.  Part of my mobile [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a while since I&#8217;ve posted but I saw something this evening that I thought was worth posting.  I&#8217;ve been spending a lot of my free time lately developing and promoting an <a href="http://apptory.com" target="_self">iPhone app</a>.  I&#8217;ve got a second in process so this whole process has been a great learning experience.  Part of my mobile obsession extends to browser based apps (i.e. not App Store downloads) that utilize some of the advancements in the <a href="http://dev.w3.org/html5/spec/Overview.html">HTML5 specification </a>(I use the word &#8216;specification&#8217; loosely as I&#8217;ll include local storage, geolocation, etc under the same umbrella on this site).</p>
<p>HTML5 has it&#8217;s pro&#8217;s and con&#8217;s that each developer needs to weigh (we won&#8217;t get into that here) but <a href="http://dev.w3.org/html5/webstorage/">web storage</a> and <a href="http://dev.w3.org/html5/webdatabase/">web database</a> are great advances.  The packaged modern mobile browsers (Safari, Android browser, etc) all support the specification which allows applications to store information from within their application that persists from session to session.  It can be very powerful&#8230;but it is definitely open for exploitation.  A common example is Gmail which utilizes the storage feature (along with App Cache) to allow you to work within the Gmail web-app while you are not connected to a network.  It also speeds up the entire user experience.</p>
<p>All that being said, I logged into AdWords this evening to begin preparing my campaign for this weekend and noticed they&#8217;ve begun utilizing local storage.  The great thing about it is that they request your approval rather than doing it behind the scenes.  Given that any website can create a &#8216;database&#8217; on your local machine for storing information, I think that all user-agents (think Safari, Firefox, Chrome, etc) should force the user to authorize each use of local storage &#8211; i.e. one approval for gmail.com).</p>
<p>In short, it&#8217;s really cool that more and more sites are beginning to implement these features as browsers roll-out support but I&#8217;m more impressed that AdWords asks for permission.  I think more web-apps should follow the AdWords lead!</p>
<p><a href="http://nathanhjones.com/wp-content/uploads/2010/09/Screen-shot-2010-09-15-at-11.28.09-PM.png"><img class="aligncenter size-full wp-image-280" title="AdWords Implements HTML5 database feature" src="http://nathanhjones.com/wp-content/uploads/2010/09/Screen-shot-2010-09-15-at-11.28.09-PM.png" alt="" width="521" height="212" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://nathanhjones.com/2010/09/15/google-adwords-gets-partial-html5-makeover/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gone Mobile with WPtouch</title>
		<link>http://nathanhjones.com/2010/01/14/gone-mobile-with-wptouch/</link>
		<comments>http://nathanhjones.com/2010/01/14/gone-mobile-with-wptouch/#comments</comments>
		<pubDate>Fri, 15 Jan 2010 04:06:45 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[nathanhjones.com]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[wptouch]]></category>

		<guid isPermaLink="false">http://nathanhjones.com/?p=259</guid>
		<description><![CDATA[The other day I read Justin Levy&#8217;s post on going mobile with WPtouch and just had to experiment.  I haven&#8217;t previously had a mobile specific version so it&#8217;s definitely an exciting move. Here&#8217;s a quick round up of my experience. Installation Installation was a breeze.  WPtouch is a WordPress plugin, all it took was downloading the files, [...]]]></description>
			<content:encoded><![CDATA[<p>The other day I read <a href="http://justinrlevy.com/2010/01/05/gone-mobile/">Justin Levy&#8217;s post on going mobile</a> with <a href="http://www.bravenewcode.com/wptouch/">WPtouch</a> and just had to experiment.  I haven&#8217;t previously had a mobile specific version so it&#8217;s definitely an exciting move. Here&#8217;s a quick round up of my experience.</p>
<h3>Installation</h3>
<p>Installation was a breeze.  WPtouch is a WordPress plugin, all it took was downloading the files, uploading it to my server and activating it from the dashboard.  Once activated we were up-and-running with the vanilla install.  Now on to customizing&#8230;</p>
<h3>Setup</h3>
<p>WPtouch offers a wide array of customizing (sorry, this is a word I&#8217;ve gotten way too used to in the SAP world) options from enabling AJAX comment posting to custom CSS/Javascript inclusion.  I kept my install fairly simple but there were a couple things I changed.</p>
<ol>
<li>I call myself a developer so I went with a snazzy App Store icon as my mobile banner image (see end of the post). WPtouch has a pretty good selection of images although they&#8217;re mostly centered around the iPhone.  If nothing meets your needs you&#8217;re more than welcome to upload a custom file.<a href="http://nathanhjones.com/wp-content/uploads/2010/01/WPtouch-banner-icons.png"><img title="WPtouch-banner-icons" src="http://nathanhjones.com/wp-content/uploads/2010/01/WPtouch-banner-icons.png" alt="" width="508" height="290" /></a></li>
<li>Linking of my AdSense and Analytics accounts.  Must haves&#8230;AdSense to collect those occasional pennys and Analytics to obviously to continue to understand how people flow through the site.  Adding both was EXTREMELY easy to do with a custom section for each.<a href="http://nathanhjones.com/wp-content/uploads/2010/01/WPtouch-adsense-and-analytics.png"><img title="WPtouch-adsense-and-analytics" src="http://nathanhjones.com/wp-content/uploads/2010/01/WPtouch-adsense-and-analytics.png" alt="" width="542" height="149" /></a></li>
</ol>
<p>WPtouch gives you the option to display a &#8216;desktop&#8217; (i.e. non-mobile) version of your website to users on their first visit and include the ability to toggle mobile vs. desktop in your theme footer.  I get the potential draw but if you&#8217;re going to go mobile, I&#8217;m not sure why you wouldn&#8217;t always default mobile and allow them to switch back if they want.</p>
<p>Anyways, you can also change what icon is used for each post and how much information about the post is shown (e.g. just the title, title and a teaser, tags, categories, etc).  I played with the settings a bit but I think that&#8217;s really more of a personal choice&#8230;at least until I get time to test and study analytic data.</p>
<h3>Additions and Suggestions</h3>
<p>For a donation supported plugin I can&#8217;t really complain.  It&#8217;s easy and relatively robust but there are still a couple things I would like to see enhanced:</p>
<ol>
<li>I understand it&#8217;s a mobile device and landscape is limited but a second &#8216;title&#8217; (under NathanHJones.com below) would be ideal.  Obviously, each blog owner would need to be smart about how it was used.</li>
<li>Better AdSense rendering.  This may be slightly out of the WPtouch developers hands but I noticed that AdSense ads show up very boxy compared to the smooth WPtouch design.  I don&#8217;t know if that&#8217;s anything they can fix or perhaps me just being new to AdSense mobile but it didn&#8217;t exactly flow together.</li>
</ol>
<p><a href="http://nathanhjones.com/wp-content/uploads/2010/01/WPtouch-adsense-rendering.jpg"><img title="WPtouch-adsense-rendering" src="http://nathanhjones.com/wp-content/uploads/2010/01/WPtouch-adsense-rendering.jpg" alt="" width="230" height="133" /></a></p>
<p>If you&#8217;re mobile version is powered by WPtouch leave a comment and let me know what you think!  Finally, here&#8217;s a fullscreen shot of NathanHJones.com&#8230;the mobile version&#8230;from my iPhone.</p>
<p><a href="http://nathanhjones.com/wp-content/uploads/2010/01/nathanhjones.com-mobile.jpg"><img title="nathanhjones.com-mobile" src="http://nathanhjones.com/wp-content/uploads/2010/01/nathanhjones.com-mobile.jpg" alt="" width="224" height="336" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://nathanhjones.com/2010/01/14/gone-mobile-with-wptouch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Garyvee&#8217;s New ObsessedTV.com</title>
		<link>http://nathanhjones.com/2009/02/28/garyvees-new-obsessedtvcom/</link>
		<comments>http://nathanhjones.com/2009/02/28/garyvees-new-obsessedtvcom/#comments</comments>
		<pubDate>Sun, 01 Mar 2009 00:56:05 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[business]]></category>
		<category><![CDATA[communication]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[gary vaynerchuk]]></category>
		<category><![CDATA[garyvee]]></category>
		<category><![CDATA[obsessedtv]]></category>

		<guid isPermaLink="false">http://nathanhjones.com/?p=208</guid>
		<description><![CDATA[So, I&#8217;ve seen mixed reviews of Gary Vaynerchuk&#8217;s newest venture, ObsessedTV.com.  Some love it and a couple hate it, but I&#8217;m not sure they&#8217;re really giving it a chance.  I must admit, when I first loaded it up I was a bit shocked at the direction he took but I think it&#8217;s a pretty solid [...]]]></description>
			<content:encoded><![CDATA[<p>So, I&#8217;ve seen mixed reviews of <a href="http://garyvaynerchuk.com/">Gary Vaynerchuk&#8217;s</a> newest venture, <a href="http://obsessedtv.com/">ObsessedTV.com</a>.  Some love it and a couple hate it, but I&#8217;m not sure they&#8217;re really giving it a chance.  I must admit, when I first loaded it up I was a bit shocked at the direction he took but I think it&#8217;s a pretty solid play.  I mean, it&#8217;s different than we&#8217;re used to from Gary (hell, it&#8217;s not even 100% Gary) but he&#8217;s expanding his empire&#8230;what did you want him to do another wine show?!?  Perhaps something dedicated solely to Cabernet Franc, Gewürztraminer or Burgundy?!?  What gives!  He&#8217;s been there and clearly conquered that and while it will take time for people to adjust, I think it&#8217;s a step in a great direction.</p>
<p>Now, onto the show &#8211; I watched the Mark Bittman interview.  I&#8217;m not really their target demographic which is why the &#8220;set&#8221; probably wasn&#8217;t what I expected.  I can&#8217;t really take it to them for that though, it&#8217;s what I would consider a pretty standard set for interview format shows.  Overall, the episode seemed pretty &#8220;early stage&#8221; to me in that Samantha didn&#8217;t feel totally at ease, maybe even a little nervous.  Maybe it was the new setting but some of that may have been Mark who, in my opinion, seemed a bit snarky.  I think he&#8217;s earned a little of that right and I still think he&#8217;s a very interesting man.  Anyways, I look forward to future episodes as they just off the jitters and I can&#8217;t wait to see what kind of guests they can swing.  Knowing the little I do about Gary I&#8217;m sure they won&#8217;t disappoint.</p>
<p>In closing, I think it&#8217;s great idea that has real potential and it&#8217;s a bold move into a new demographic for Gary.  I want to see how it plays out but like I said earlier, he&#8217;s conquered wine and is making a play to expand his media empire.  For that my friends, you have to respect him.  As Gary would put it, he&#8217;s hustlin&#8217; and you can&#8217;t get down on someone for that!  Keep up the great work Gary and I look forward to the other stuff you plan on bringing us.</p>
]]></content:encoded>
			<wfw:commentRss>http://nathanhjones.com/2009/02/28/garyvees-new-obsessedtvcom/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Review: AIM for Windows Mobile</title>
		<link>http://nathanhjones.com/2008/07/02/review-aim-for-windows-mobile/</link>
		<comments>http://nathanhjones.com/2008/07/02/review-aim-for-windows-mobile/#comments</comments>
		<pubDate>Wed, 02 Jul 2008 20:48:18 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[communication]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[aim]]></category>
		<category><![CDATA[aol]]></category>
		<category><![CDATA[instant messaging]]></category>
		<category><![CDATA[product reviews]]></category>

		<guid isPermaLink="false">http://nathanhjones.com/?p=75</guid>
		<description><![CDATA[AOL launched a mobile version of it&#8217;s once king AOL Instant Messanger (AIM) the other day and initial findings are promising but they&#8217;ve got a ways to go. ReadWriteWeb thinks it&#8217;s a must have app for Windows Mobile devices and I tend to agree if they make some changes. However, hands down it beats what [...]]]></description>
			<content:encoded><![CDATA[<p>AOL <a href="http://beta.aol.com/projects.php?project=aimwinmobile">launched a mobile version</a> of it&#8217;s once king AOL Instant Messanger (AIM) the other day and initial findings are promising but they&#8217;ve got a ways to go.   ReadWriteWeb thinks it&#8217;s a <a href="http://www.readwriteweb.com/archives/6_must_have_windows_mobile_app.php">must have app for Windows Mobile devices</a> and I tend to agree if they make some changes.  However, hands down it beats what Google is offering for my mobile phone without downloading a third party application&#8230;a big fat goose egg.  I understand they&#8217;re pushing their own mobile operating system but come on! Blackberry has one and Bill Gates isn&#8217;t even running the day to day operations at Microsoft anymore so let bygones be bygones. But I digress.  I know it&#8217;s still in Beta but here are some thoughts.</p>
<ol>
<li><strong>IT&#8217;S A HUGE BATTERY KILLER!!!</strong> I know the TREO 750 already has &#8216;poor&#8217; battery life according to critics but this drains it faster than Britney Spears bounces in and out of rehab.  I can normally get through a full day with moderate email/phone usage but when I&#8217;m running Mobile AIM my battery is ready for charging by 11AM &#8211; that&#8217;s roughly 3.5 hours of use for you bean counters.  This has got to be fixed before launching the final version.</li>
<li><strong>IT&#8217;S A MEMORY HOG!!!</strong> I&#8217;m not sure if it&#8217;s just intense processing or if it&#8217;s an actual memory leak but I gained 12MB of memory after shutting down AIM.  Gained means it allocated it back to usable memory when I shut it down&#8230;it was using 15% (give or take) of my processing power.  On a mobile device that&#8217;s a HUGE amount of processing power!</li>
<li>It doesn&#8217;t give external notifications (other than sound which is just obnoxious) when you have a new IM.  If you choose to turn on sound it will play the standard new IM sound.  However, if your phone is on vibrate it doesn&#8217;t do anything to alert you.</li>
<li>The interface is visually pleasing and mostly functional, here are a few comments:
<ul>
<li>Good:
<ul>
<li>Navigating between various conversations and your buddy list is extremely easy, especially if you have a touch screen.  I think without a touch screen many of the features I enjoy would be difficult</li>
<li>You can add/edit/delete groups and friends which is pretty slick for a mobile Beta release</li>
<li>You can easily toggle between available, busy and invisible (major plus considering Google Talk hasn&#8217;t even got that right in their desktop client yet)</li>
<li>Setting messages (away or status &#8211; however you use them) is a breeze</li>
</ul>
</li>
<li>Bad:
<ul>
<li>There are some issues with how it &#8216;pages&#8217; when you scroll through your buddy list &#8211; it&#8217;s a little clunky.  This may be attributed to the fact that it&#8217;s using so much processing power and the system chokes a little when you try and scroll</li>
<li>When you&#8217;re in the conversation mode the &#8216;send&#8217; button is on the wrong side &#8211; at least compared to the TREO 750.  Text messaging on the TREO is displayed a lot like IM conversations and the send/close buttons are on different sides than AIM Mobile has them.  This is big from a usability stand-point &#8211; I&#8217;ve already had several messages that didn&#8217;t get sent because I clicked the wrong button.  Just takes getting used to I suppose&#8230;</li>
<li>There is an &#8216;alert me when&#8217; option on the menu that I can&#8217;t seem to activate.  Not sure how it would work given the fact that I don&#8217;t get notified of IMs unless I&#8217;m physically in the application</li>
</ul>
</li>
</ul>
</li>
<li>There isn&#8217;t an automatic updater.  Not a huge deal but definitely an inconvenience.  Now I have to go to the <a href="http://beta.aol.com/projects.php?project=aimwinmobile">Beta site</a> and download the new version every time they release a fix.  They have said an update notification is on it&#8217;s way in a future version though.  In the mean time it would be nice if the site included dates/times of the most recent release so I could guesstimate whether I should install again.  Maybe I&#8217;m just missing it because that seems like common sense.</li>
</ol>
<p>Here are a couple things I&#8217;d like to see them add on top of general usability/performance:</p>
<ol>
<li>Add an option to my photo menu to set a particular image as my AIM icon</li>
<li>Add an option to my photo menu to send images to AIM buddies if I&#8217;m logged in</li>
<li>Allow me to add a link to my Windows Today screen that will take me to a new IM if there is one</li>
</ol>
<p>My current client has blocked AIM/Google Talk so if you&#8217;re in the same boat this is definitely worth the download.  Here&#8217;s a shot of the user interface from the AIM Mobile site.</p>
<p><a href="http://nathanhjones.com/wp-content/uploads/2008/07/aim_beta2screen.png"><img class="alignnone size-full wp-image-76" title="AIM Beta for Windows Mobile" src="http://nathanhjones.com/wp-content/uploads/2008/07/aim_beta2screen.png" alt="" width="240" height="320" /></a></p>
<p><span style="font-size: 10px;">(image courtesy of AIM Beta site)</span></p>
]]></content:encoded>
			<wfw:commentRss>http://nathanhjones.com/2008/07/02/review-aim-for-windows-mobile/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WM6 Type-ahead Delay</title>
		<link>http://nathanhjones.com/2008/04/12/wm6-type-ahead-delay/</link>
		<comments>http://nathanhjones.com/2008/04/12/wm6-type-ahead-delay/#comments</comments>
		<pubDate>Sat, 12 Apr 2008 16:33:17 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[keyboard lag]]></category>
		<category><![CDATA[windows mobile]]></category>
		<category><![CDATA[wm6]]></category>

		<guid isPermaLink="false">http://nathanhjones.com/?p=66</guid>
		<description><![CDATA[I recently upgraded to WM6 and am slowly getting things working the way I like. Throughout the upgrade and re-setup process I&#8217;ve found a couple pretty odd settings. One of those pesky settings has been the type-ahead feature. Similar to most type-ahead features you&#8217;ve probably seen around the web, after you type a couple characters [...]]]></description>
			<content:encoded><![CDATA[<p>I <a href="http://nathanhjones.com/2008/03/25/windows-mobile-6-only-google-search/">recently upgraded to WM6</a> and am slowly getting things working the way I like.   Throughout the upgrade and re-setup process I&#8217;ve found a couple pretty odd settings.  One of those pesky settings has been the type-ahead feature.  Similar to most type-ahead features you&#8217;ve probably seen around the web, after you type a couple characters it suggests words so you don&#8217;t have to type them out.</p>
<p>It&#8217;s a great feature but the default configuration has it suggesting words after the first character which taxes the system (very noticeable delays) and just doesn&#8217;t make sense.  If I&#8217;m typing the word &#8216;the&#8217;, I don&#8217;t need the computer to suggest the word for me.  I&#8217;m pretty sure I&#8217;m not that poor of a speller.  So, for those of you who have also become frustrated by the ridiculous type-ahead settings here&#8217;s a quick fix.  Nothing mind boggling&#8230;just felt it should be documented.</p>
<p><strong>Fixing:</strong></p>
<ol>
<li>Go to the &#8216;Start&#8217; menu and enter the Settings</li>
<li>Select the Input option (looks like a small keyboard)</li>
<li>Choose the &#8216;Word Completion&#8217; tab at the bottom of the screen</li>
<li>You can now turn it off completely or just set it up to only trigger when you really need it.  Mine is configured to suggest 4 words after I type 4 letters</li>
</ol>
<p>Hope this helps someone else out!!</p>
]]></content:encoded>
			<wfw:commentRss>http://nathanhjones.com/2008/04/12/wm6-type-ahead-delay/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows Mobile 6 &#8211; Only Google search?</title>
		<link>http://nathanhjones.com/2008/03/25/windows-mobile-6-only-google-search/</link>
		<comments>http://nathanhjones.com/2008/03/25/windows-mobile-6-only-google-search/#comments</comments>
		<pubDate>Wed, 26 Mar 2008 02:47:09 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[technology]]></category>

		<guid isPermaLink="false">http://nathanhjones.com/2008/03/25/windows-mobile-6-only-google-search/</guid>
		<description><![CDATA[So I upgraded from Windows Mobile 5 to Windows Mobile 6 last week and I&#8217;ve spent a decent amount of time tinkering with the enhancements and think WM6 is a nice improvement.  They&#8217;ve added some great new features such as enhanced calendaring and HTML formatted emails.  For those of you who use a WM5 device, [...]]]></description>
			<content:encoded><![CDATA[<p>So I upgraded from Windows Mobile 5 to Windows Mobile 6 last week and I&#8217;ve spent a decent amount of time tinkering with the enhancements and think WM6 is a nice improvement.  They&#8217;ve added some great new features such as enhanced calendaring and HTML formatted emails.  For those of you who use a WM5 device, you know what I&#8217;m talking about.  While I didn&#8217;t mind the strictly text email, the new features are greatly appreciated.</p>
<p>After poking around some of the settings I found that WM6 doesn&#8217;t have MSN as the default search engine for the web search feature on the &#8216;today&#8217; screen.  I know Microsoft has paid penalties out the wazoo for monopolistic practices in it&#8217;s PC operating systems so I figured they just didn&#8217;t want to get nailed for this and set a different default.  But why Google of all people?!?  At least they tried to purchase of Yahoo&#8230;why not set them as the default?!?  After some more searching I was surprised to find that not only is Google the default search engine, it&#8217;s the only search engine that you can set.  One of Microsoft&#8217;s biggest competitors holds the sole search rights on Windows Mobile devices&#8230;weird!</p>
<p>After thinking about it a bit I figured it had to be something that Palm or AT&amp;T configured and it wasn&#8217;t Microsoft&#8217;s choice.  The thing that bugs me is I don&#8217;t even have the option to add a new search engine.  I wonder if AT&amp;T or Palm is getting kickbacks for this nonsense?!?</p>
<p>Then, after reading my blog news a few days ago I heard that <a href="http://googlemobile.blogspot.com/2008/03/fast-is-better-than-slow.html">Google launched a downloadable plugin for Windows</a> (and <a href="http://mashable.com/2008/03/20/google-search-windows-mobile/">here</a>) that allows for &#8216;fast&#8217; search from the &#8216;today&#8217; screen of your WM device.  That&#8217;s cool, except it already exists and doesn&#8217;t require a download.  Not like it takes up much space, but there is just no need.</p>
<p>Now, as many of you are aware I show a lot of love to Google.  I normally approve emphatically of what they do but I just don&#8217;t see the point here.</p>
<p>Overall Google, I think it was a waste of time and money to build.  But that&#8217;s just me.  Better luck next time.</p>
]]></content:encoded>
			<wfw:commentRss>http://nathanhjones.com/2008/03/25/windows-mobile-6-only-google-search/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

