an ios authentication architecture for all
DESCRIPTION
TRANSCRIPT
Get Ready1
An iOS Authentication Architecture for All
How to stop reinventing the auth wheel
2
PatternThere’s a
for That
4
WHAT’S THE BIG DEAL?
5
SpendTime
Building Features
that ROCK
6
EngineerAmazingFirst Impressions
7
BuildReliable
andSecure
Apps
8
Meet John
9
10
image by adamjackson1984
11
13
What to Build? 14
15
Business Cards
16
Ready, Set...17
18
19
but then...
20
21
O...AUTH22
Really!?23
What exactly is OAuth?
24
I have to use a UIWebView?!
WAIT!
25
Is there a library for this??
26
YESGTMOAuth, whew.
27
Just Download
It!
28
But then...
29
Things start going wrong...
30
GTMOAuth1 or 2?
31
Is Linked in OAuth 1 or 2?
32
BOTH?
33
One Hour Later
34
35
Jen!
36
37
Jen went to CocoaConf and...
38
Well...There’s a Pattern
39
CocoaAuth
40
AND there’s a reference implementation
41
Auth Kit
42
Three PatternsThree Steps
43
Accounts
1 2 3Auth
ControllersAuth UI
Three PattersThree Steps
44
But first...
45
John chose OAuth 2for Linked in
46
Why?47
John chose Google’sGTMOAuth
48
Why?49
Back to:Three patterns
Three steps
50
Accounts
1 2 3Auth
ControllersAuth UI
Three PattersThree Steps
51
So we want to implement Accounts...
52
First An Intro
53
OAuth 2
Meet OAuth 2.0
54
1st thing...
55
The Access Token
image by tv
56
It’s...
57
Opaque58
It has...
59
Scopes60
and it...
61
Expires62
That’s OAuth 2 Access Token
On to Step 1, Accounts
63
Accounts
1
64
If you need Auth you have user’s...
65
And if you have users, you need
account management
66
Accounts makes up the model layer
67
3 Entities in Accounts
68
1
2
3
Credentials
Accounts
Store
69
1
2
3
Credentials
Accounts
Store
70
@property(nonatomic, copy) NSString *accessToken;@property(nonatomic, strong) NSDate *expirationDate;
AKOAuth2AccountCredential : NSObject
71
That’s all for credentials, super easy.
Accounts is next.
72
1
2
3
Credentials
Accounts
Store
73
@property(nonatomic, copy, readonly) NSString *identifier;@property(nonatomic, copy, readonly) NSString *username;@property(nonatomic, copy, readonly) NSString *accountType;
- (void)clearCredential;
AKAccount : NSObject
74
Account Type
Subclassing
1
2
75
Account Type“com.linkedin”
76
Subclassing AKAccount
77
Base
Auth Protocol
Library
Class Structure
78
@interface AKAccount ()@property(nonatomic, copy, readwrite) NSString *identifier;
@end
@implementation AKAccount
+ (instancetype)accountWithIdentifier:(NSString *)identifier { return [[self alloc] initWithIdentifier:identifier];}
- (id)initWithIdentifier:(NSString *)identifier { self = [super init]; if (self) { _identifier = identifier; } return self;}
- (void)clearCredential { // Abstract method.}
@end
AKAccount Base
79
@class AKOAuth2AccountCredential;
@interface AKOAuth2Account : AKAccount
@property(nonatomic, strong, readonly) AKOAuth2AccountCredential *OAuth2Credential;
@end
@implementation AKOAuth2Account
- (AKOAuth2AccountCredential *)OAuth2Credential { // Subclasses should implement this. They should always access // credentials from a secure store. return nil;}
@end
AKOAuth2Account
80
@implementation AKGTMOAuth2Account
- (AKOAuth2AccountCredential *)OAuth2Credential { // Get credential from Google's GTMOAuth2 library.}
- (void)clearCredential { // Remove credential from storage.}
@end
AKGTMOAuth2Account
81
@property(nonatomic, copy, readonly) NSString *identifier;@property(nonatomic, copy, readonly) NSString *username;@property(nonatomic, copy, readonly) NSString *accountType;
- (void)clearCredential;
AKAccount : NSObject
82
1
2
3
Credentials
Accounts
Store
83
+ (void)registerAccountTypeClass:(Class)accountTypeClass;
+ (instancetype)sharedStore;
- (AKAccount *)newAccount;
- (void)saveAccount:(AKAccount *)account;
- (AKAccount *)authenticatedAccount;
AKAccountStore : NSObject
84
1
2
Account Ref Store
Credential Store
Implementing
85
1
2
Account Ref Store
Credential Store
Implementing
86
1
2
Account Ref Store
Credential Store
Implementing
87
Credential Store
2
1 Keychain
Library Provided
88
Keychain
1
89
Library Provided Store
2
90
- (AKOAuth2AccountCredential *)OAuth2Credential { AKGTMOAuth2AuthController *authController = [AKGTMOAuth2AuthController sharedController]; GTMOAuth2Authentication *auth = [authController newGTMOAuth2Authentication]; if (!auth) { return nil; } BOOL isAuthenticated = [GTMOAuth2ViewControllerTouch authorizeFromKeychainForName:authController.keychainItemName authentication:auth]; if (!isAuthenticated) { return nil; }
AKOAuth2AccountCredential *credential = [[AKOAuth2AccountCredential alloc] init]; credential.accessToken = auth.accessToken; return credential;}
GTMOAuth 2
91
+ (void)registerAccountTypeClass:(Class)accountTypeClass;
+ (instancetype)sharedStore;
- (AKAccount *)newAccount;
- (void)saveAccount:(AKAccount *)account;
- (AKAccount *)authenticatedAccount;
AKAccountStore : NSObject
92
Accounts, done.
Next pattern, #2
93
Auth Controller
2
94
Before looking at Auth Controller...
95
More OAuth2
Fun
96
The Actors
Client
Authorization Server
Resource Server
97
The Client
APP
98
Authorization Server99
Resource Server100
Before you can authenticate against an API’s OAuth you
have to ...
101
Register the Client102
Linked in103
And that gives you:
104
Client ID105
Client Secret106
That’s it. The Basics.
107
image by Damien Erambert
2Auth Controller
108
If you have auth...
109
You have a login...
110
If you have login,UIKit has to launch
a login flow.
111
Something has to be in control, no?
112
2 Protocols
113
- (void)beginAuthenticationAttempt;
- (void)unauthenticateAccount:(AKAccount *)account;
<AKAuthControl>
- (void)presentAKLoginViewController:(UIViewController *)viewController;
- (void)authControllerAccount:(AKAccount *)account didAuthenticate:(id<AKAuthControl>)authController;
- (void)authControllerAccount:(AKAccount *)account didUnauthenticate:(id<AKAuthControl>)authController;
<AKAuthHandler>
114
Now the star of the show,
AKAuthController
115
@property(nonatomic, weak) id<AKAuthHandler> authHandler;
+ (instancetype)sharedController;
AKAuthController : NSObject<AKAuthControl>
it’s abstract116
Simple
117
How does it work?
118
1
2
3
The Flows
Linkedin Auth Controller
Calling Linkedin API
119
The Flows120
id <AKAuthHandler> AKAuthController Login UIViewController
beginAuthenticationAttempt
initialize
presentAKLoginViewController:
user authenticated
authControllerAccount:didAuthenticate:
Login View Flow
121
Authenticated Flowid <AKAuthHandler> AKAuthController
beginAuthenticationAttempt
authControllerAccount:didAuthenticate:
122
Bounce Back Flowid <AKAuthHandler> AKAuthController Safari
beginAuthenticationAttempt
open URL
user authenticated
authControllerAccount:didAuthenticate:
App Delegate
open URL
123
So, the Linked in Auth Controller
124
But first...
125
Last OAuth 2 Lesson
126
The Grant
The Access Token (Part 2)
Two Steps
1
2
127
The Grant128
Yes, there IS another token.
129
Auth Code
Browser
The Request
The Redirect
130
Browser
131
The Request
132
Client Browser Auth Server
Auth Code Request URL
Auth Code GET Request
Redirect URL with Auth Code
Redirect URL with Auth Code
HTML Flow
133
Query String Params
https://www.linkedin.com/uas/oauth2/authorization
?response_type=code &client_id=YOUR_API_KEY &scope=SCOPE &state=STATE &redirect_uri=YOUR_REDIRECT_URI
134
The Redirect
135
Client Browser Auth Server
Auth Code Request URL
Auth Code GET Request
Redirect URL with Auth Code
Redirect URL with Auth Code
HTML Flow
136
And now, get the Auth Code...
137
It’s in the redirect URL query string.
YOUR_REDIRECT_URI/?code=AUTHORIZATION_CODE
138
So that’s the Auth Code Grant
139
Now, it’s time for some more Access
Token fun.
140
The Access Token141
Now that I have an Auth Code...
142
How do I get an Access Token?
143
Request
Response
144
Request
145
Client Auth Server
Access Token POST Request with Auth Code
JSON with Access Token
146
Query String Params
https://www.linkedin.com/uas/oauth2/accessToken
?grant_type=authorization_code &code=AUTHORIZATION_CODE &redirect_uri=YOUR_REDIRECT_URI &client_id=YOUR_API_KEY &client_secret=YOUR_SECRET_KEY
147
Response
148
Client Auth Server
Access Token POST Request with Auth Code
JSON with Access Token
149
Payload
{ "expires_in":5184000, "access_token":"AQXdSP_W41_UPs5ioT_t8HESyODB4FqbkJ8LrV_5mf f4gPODzOYR"}
150
So that’s how you get an Access Token
151
Back to... Linked in Auth Controller
152
Base
Auth Protocol
Library
AKAuthController
AKGTMOAuth2AuthController
MALinkedInAuthController
Subclass Structure
153
Using GTMOAuth2
154
Code Demo
155
We now have an Access token in the
Keychain
156
Time to make some API Calls
157
Calling the Linked in API
158
Getting Access Token from Account Store
Using the Access Token
Handling Bad Token Responses
1
23
159
Getting Access Token
1
160
Using Access Token
2
161
Client Resource Server
API Request with Access Token
Protected Resource
162
Code Demo
163
FINALLY! API Calls
164
Bad Token
3
165
Get Auth Controller
166
Client Resource Server
API Request with Access Token
Bad Token
AKAuthController
Unauthenticate Account
167
Log Out Account168
And... Wait How will the app react?
169
That’s where Auth UI comes in.
170
Auth UI
3
171
Container View Controller
172
Application Container View Controller
Unauthenticated View Controller
Authenticated View Controller
173
1
2
3
Children View Controllers
Installation
Flows
174
Children
175
Installation
176
Code Demo
177
Flows
178
Log In
179
Container Auth ControllerChild Controller
beginAuthenticationAttempt
beginAuthenticationAttempt
authControllerAccount:didAuthenticate:
transition into authenticated view controller
180
Log Out
181
Container Auth ControllerChild Controller
authControllerAccount:didUnauthenticate:
transition into unauthenticated view controller
182
That’s AuthUI
183
Whew! Those are the
Patterns
184
Back in SFO...
185
image by adamjackson1984
186
187
And the winner is...
188
189
190
10 years later...
191
192
John opens a hookah bar...
193
YES...a hookah bar
194
and
195
JUST MARRIED!
196
The End
197
So what’s the point?
198
Auth Sucks
199
Auth Takes Time
200
It gets in the way
201
TIMEDon’t spend
on auth
202
FeaturesSpend time on
203
Benefits
204
Save Time and
Effort
205
Consistent Interface
206
It’s simple
207
Future
208
Future of iOS
209
Future of CocoaAuth
&Auth Kit
210
Resources
211
/RCacheaux/AuthKit
212
214