Page 1
© 2014 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple.
#WWDC14
Your App, Your Website, and SafariEnsuring continuity of user experience
Session 506 Ricky Mondello Safari and WebKit Engineer
Media
Page 3
Continuity |ˌkäntnˈ(y)o͞oətē| noun (pl. continuities) the unbroken and consistent existence oroperation of something over a period of time
Continuity
Page 4
Continuity |ˌkäntnˈ(y)o͞oətē| noun (pl. continuities) the unbroken and consistent existence oroperation of something over a period of time
Page 6
Related Sessions
• Adopting Handoff on iOS and OS X Mission Wednesday 2:00PM
Page 14
What You Will Learn
How to: • Use Safari credentials in your iOS apps
• Make Safari AutoFill work better on your website
• Help Safari promote your website
• Make your website consistent across devices
Page 15
Credentials in SafariAnd how your app can use them
Page 23
iPad iPhone
Safari AutoFill
Page 24
Credentials in Safari
iPad iPhone
Mac
Page 25
Credentials in Safari
iPad iPhone
Mac
Page 26
Credentials in Safari
iPad iPhone
Mac
Page 27
iPad iPhone
Mac
Credentials in Safari
iPhone
Page 28
iPad iPhone
Mac
Credentials in Safari
iPhone
Page 29
Credentials in Safari
Page 30
Credentials in Safari
Page 31
Safari Credentials in Native Apps
Andrew Whalley Core OS Security Engineering
Page 32
Password Security
Page 33
Password Security
Page 34
Password Security
Page 35
Password Security
afz-zma-9JX-puLandrew
Page 37
Overview
Associate your app and website
Page 38
Overview
Associate your app and website• One file on your website
Page 39
Overview
Associate your app and website• One file on your website
• One new entitlement
Page 40
Overview
Associate your app and website• One file on your website
• One new entitlement
Simple APIs
Page 41
Overview
Associate your app and website• One file on your website
• One new entitlement
Simple APIs• Ask for credentials
Page 42
Overview
Associate your app and website• One file on your website
• One new entitlement
Simple APIs• Ask for credentials
• Create or update credentials
Page 43
Associating App and Website
Page 44
Associating App and Website
Page 45
Associating App and Website
Page 46
Associating App and Website
Page 47
Associating App and Website
App Website Status
Shiny App example.com Pending
Foo Client foo.com Approved
Foo Admin App foo.com Approved
Page 48
example.com
Shiny App
Associating App and Website
example.com
Page 49
example.com
Shiny App
Associating App and Website
example.com
Page 50
Associating App and Website
Shiny App example.com
https://example.com/apple-app-site-association
Page 51
Associating App and Website
Shiny App example.com
https://example.com/apple-app-site-association
Page 52
Associating App and Website
Shiny App example.com
https://example.com/apple-app-site-association
Page 53
Associating App and Website
Shiny App example.com
https://
Page 54
example.com
Associating App and Website
Shiny App
Page 55
example.com
Associating App and Website
Shiny App
Shiny App
Page 56
Associating App and Website
example.comShiny App
Shiny App
Page 57
Associating App and Website
example.comShiny App
Shiny App Shiny App
Page 58
App Website Status
Pending
Foo Client foo.com Approved
Foo Admin App foo.com Approved
Associating App and Website
Shiny App example.com
Page 59
App Website Status
Pending
Foo Client foo.com Approved
Foo Admin App foo.com Approved
Associating App and Website
Shiny App example.comShiny App example.com
Page 60
Associating App and Website
App Website Status
Approved
Foo Client foo.com Approved
Foo Admin App foo.com Approved
Shiny App example.com
Page 61
Determining App IntentEntitlements
Page 62
Determining App IntentEntitlements
application-identifier
Page 63
Determining App IntentEntitlements
application-identifier
teamid.bundle-identifier
Page 64
Determining App IntentEntitlements
application-identifier
teamid.bundle-identifier
YWBN8XTPBJ.com.example.Shiny
Page 65
Determining App IntentEntitlements
application-identifier
teamid.bundle-identifier
YWBN8XTPBJ.com.example.Shiny
Page 66
Determining App IntentEntitlements
application-identifier
teamid.bundle-identifier
YWBN8XTPBJ.com.example.Shiny
Page 67
Determining App IntentEntitlements
application-identifier
teamid.bundle-identifier
YWBN8XTPBJ.com.example.Shiny
Page 68
Determining App IntentEntitlements
application-identifier
teamid.bundle-identifier
YWBN8XTPBJ.com.example.Shiny
com.apple.developer.associated-domains
Page 69
Determining App IntentEntitlements
application-identifier
teamid.bundle-identifier
YWBN8XTPBJ.com.example.Shiny
com.apple.developer.associated-domains
service:fully.qualified.domain.name[:port number]
Page 70
Determining App IntentEntitlements
application-identifier
teamid.bundle-identifier
YWBN8XTPBJ.com.example.Shiny
com.apple.developer.associated-domains
service:fully.qualified.domain.name[:port number]
webcredentials:example.com
Page 71
associated-domains EntitlementXcode
Page 72
Associating App and Website
Page 73
Associating App and Website
Page 74
d75a94362690a3386d55ef16f95182eb5a334efabcf3f803cecb930d559f397e6966c1996f24aeea8574fe7d209166d1022ea2c2df3de47d734a3c7513047d7b1a5812ae845feb69327921c7fdc4eedd10283939dd729790203010001a38201ab308201a7301f0603551d230418301680146b693d6a18424add8f026539fd35248678911630300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302301b0603551d1104143012821063727970746f71756f7465732e6e657430430603551d1f043c303a3038a036a0348632687474703a2f2f726170696473736c2d63726c2e67656f74727573742e636f6d2f63726c732f726170696473736c2e63726c301d0603551d0e041604142de1c9ff521bc3210a260fedaf7745837112d27a300c0603551d130101ff04023000307806082b06010505070101046c306a302d06082b060105050730018621687474703a2f2f726170696473736c2d6f6373702e67656f74727573742e636f6d303906082b06010505073002862d687474703a2f2f726170696473736c2d6169612e67656f
Determining Website Intent
https://example.com/apple-app-site-association
Page 75
http://example.com/apple-app-site-association !
!
{ "webcredentials": { "apps": [ "YWBN8XTPBJ.com.example.Shiny", "YWBN8XTPBJ.com.example.ShinyUploader" ] } }
30820bd806092a864886f70d010702a0820bc930820bc5020101310b300906052b0e03021a05003082013c06092a864886f70d010701a082012d048201297b226163746976697479636f6e74696e756174696f6e223a7b2261707073223a5b22573252545650354541392e636f6d2e6170706c652e4469616c6f6754657374225d7d2c2277656263726564656e7469616c73223a7b2261707073223a5b22636f6d2e6170706c652e4469616c6f6754657374222c22573252545650354541392e636f6d2e6170706c652e4469616c6f6754657374222c225957424e38585450424a2e63727970746f7365632e51756f7465436c69656e74222c2266616b657465616d69642e63727970746f7365632e51756f7465436c69656e74222c22636f6d2e696f736672616d65776f726b7371612e4b43536861726572222c22636f6d2e696f736672616d65776f726b7371612e696e7465726e616c2e4b43536861726572225d7d7d0d0aa0820903308205263082040ea003020102020311566b300d06092a864886f70d01010b0500303c310b300906035504061302555331173015060355040a130e47656f54727573742c20496e632e311430120603550403130b526170696453534c204341301e170d3134303331373135353830385a170d3136303331393037343535385a3081bf3129302706035504051320466a373473554c3668392f3134504768653743644849304f574a624947542d7531133011060355040b130a475430363839363939343131302f060355040b1328536565207777772e726170696473736c2e636f6d2f7265736f75726365732f637073202863293134312f302d060355040b1326446f6d61696e20436f6e74726f6c2056616c696461746564202d20526170696453534c2
Determining Website Intent
https://example.com/apple-app-site-association
Page 76
http://example.com/apple-app-site-association !
!
{ "webcredentials": { "apps": [ "YWBN8XTPBJ.com.example.Shiny", "YWBN8XTPBJ.com.example.ShinyUploader" ] } }
Determining Website Intent
https://example.com/apple-app-site-association
Page 77
Determining Website Intent
https://example.com/apple-app-site-association !
!
{ "webcredentials": { "apps": [ "YWBN8XTPBJ.com.example.Shiny", "YWBN8XTPBJ.com.example.ShinyUploader" ] } }
Page 78
Determining Website Intent
https://example.com/apple-app-site-association !
!
{ "webcredentials": { "apps": [ "YWBN8XTPBJ.com.example.Shiny", "YWBN8XTPBJ.com.example.ShinyUploader" ] } }
Page 79
Determining Website Intent
Content-Type must be application/pkcs7-mime
Signed • Cryptographic Message Syntax
• S/MIME
Page 80
apple-app-site-association FileSigning the JSON
Page 81
apple-app-site-association FileSigning the JSON
echo '{"webcredentials":{"apps":["YWBN8XTPBJ.com.example.Shiny", "YWBN8XTPBJ.com.example.ShinyUploader"]}}' > json.txt
Page 82
apple-app-site-association FileSigning the JSON
echo '{"webcredentials":{"apps":["YWBN8XTPBJ.com.example.Shiny", "YWBN8XTPBJ.com.example.ShinyUploader"]}}' > json.txt
Page 83
apple-app-site-association FileSigning the JSON
!
!
cat json.txt | openssl smime -sign -inkey example.com.key -signer example.com.pem -certfile intermediate.pem -noattr -nodetach -outform DER > apple-app-site-association
Page 84
apple-app-site-association FileSigning the JSON
!
!
cat json.txt | openssl smime -sign -inkey example.com.key -signer example.com.pem -certfile intermediate.pem -noattr -nodetach -outform DER > apple-app-site-association
Page 85
apple-app-site-association FileSigning the JSON
!
!
cat json.txt | openssl smime -sign -inkey example.com.key -signer example.com.pem -certfile intermediate.pem -noattr -nodetach -outform DER > apple-app-site-association
Page 86
apple-app-site-association FileSigning the JSON
!
!
cat json.txt | openssl smime -sign -inkey example.com.key -signer example.com.pem -certfile intermediate.pem -noattr -nodetach -outform DER > apple-app-site-association
Page 87
Associating App and Website
Page 88
HTTP Status Service andIdentifier Match Signature Is Valid Approval State
200 Approved
200 Denied
300-499 n/a n/a Denied
500-599 n/a n/a Retry
Determining Website IntentReturn results
Page 89
HTTP Status Service andIdentifier Match Signature Is Valid Approval State
200 Approved
200 Denied
300-499 n/a n/a Denied
500-599 n/a n/a Retry
Determining Website IntentReturn results
Page 90
HTTP Status Service andIdentifier Match Signature Is Valid Approval State
200 Approved
200 Denied
300-499 n/a n/a Denied
500-599 n/a n/a Retry
Determining Website IntentReturn results
Page 91
HTTP Status Service andIdentifier Match Signature Is Valid Approval State
200 Approved
200 Denied
300-499 n/a n/a Denied
500-599 n/a n/a Retry
Determining Website IntentReturn results
Page 92
HTTP Status Service andIdentifier Match Signature Is Valid Approval State
200 Approved
200 Denied
300-499 n/a n/a Denied
500-599 n/a n/a Retry
Determining Website IntentReturn results
Page 93
HTTP Status Service andIdentifier Match Signature Is Valid Approval State
200 Approved
200 Denied
300-499 n/a n/a Denied
500-599 n/a n/a Retry
Determining Website IntentReturn results
Page 94
Native Apps with Accounts
Page 95
Native Apps with Accounts
Page 96
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check for Saved Credentials
Page 97
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check for Saved Credentials
Page 98
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check for Saved Credentials
Page 99
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check for Saved Credentials
Page 100
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check for Saved Credentials
Page 101
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check for Saved Credentials
Page 102
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check for Saved Credentials
Page 103
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check for Saved Credentials
Page 104
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check for Saved Credentials
Page 105
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check for Saved Credentials
Page 106
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check for Saved Credentials
Check Safari for Credentials
Page 107
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check Safari for Credentials
Check for Saved Credentials
Page 108
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check Safari for Credentials
Check for Saved Credentials
Page 109
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check Safari for Credentials
Check for Saved Credentials
Page 110
Native Apps with Accounts
Log In
Save Credentials
Prompt User
Check Safari for Credentials
Check for Saved Credentials
Page 111
Native Apps with Accounts
Log In
Save Credentials
Check Safari for Credentials
Check for Saved Credentials
Prompt User
Page 113
New APIs
SecRequestSharedWebCredential
SecAddSharedWebCredential
SecCreateSharedWebCredentialPassword
Page 114
New APIs
SecRequestSharedWebCredential
SecAddSharedWebCredential
SecCreateSharedWebCredentialPassword
Page 115
Obtaining Safari Credentials
SecRequestSharedWebCredential(CFSTR("example.com"), CFSTR("[email protected] "), ^(CFArrayRef credentials, CFErrorRef error) { });
Page 116
Obtaining Safari Credentials
SecRequestSharedWebCredential(CFSTR("example.com"), CFSTR("[email protected] "), ^(CFArrayRef credentials, CFErrorRef error) { });
Page 117
Obtaining Safari Credentials
SecRequestSharedWebCredential(CFSTR("example.com"), CFSTR("[email protected] "), ^(CFArrayRef credentials, CFErrorRef error) { });
Page 118
Obtaining Safari Credentials
SecRequestSharedWebCredential(CFSTR("example.com"), CFSTR("[email protected] "), ^(CFArrayRef credentials, CFErrorRef error) { });
Page 119
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, NULL, ^(CFArrayRef credentials, CFErrorRef error) { });
Page 120
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, ^(CFArrayRef credentials, CFErrorRef error) { });
Page 121
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { });
Page 122
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { ! });
Page 123
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { ! });
Page 124
Obtaining Safari Credentials
SecRequestSharedWebCredential NULL, ! });
Page 125
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { ! });
Page 126
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { ! });
Page 127
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { ! });
Page 128
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { });
Page 129
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { if (!error && CFArrayGetCount(credentials)) { CFDictionaryRef credential = CFArrayGetValueAtIndex(credentials, 0); NSString *username = CFDictionaryGetValue(credential, kSecAttrAccount); NSString *password = CFDictionaryGetValue(credential, kSecSharedPassword); dispatch_async(dispatch_get_main_queue(), ^{ [serverManager attemptLoginWithUsername:username password:password]; }); } else { dispatch_async(dispatch_get_main_queue(), ^{ [self showLoginUI]; }); } });
Page 130
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { if (!error && CFArrayGetCount(credentials)) { CFDictionaryRef credential = CFArrayGetValueAtIndex(credentials, 0); NSString *username = CFDictionaryGetValue(credential, kSecAttrAccount); NSString *password = CFDictionaryGetValue(credential, kSecSharedPassword); dispatch_async(dispatch_get_main_queue(), ^{ [serverManager attemptLoginWithUsername:username password:password]; }); } else { dispatch_async(dispatch_get_main_queue(), ^{ [self showLoginUI]; }); } });
Page 131
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { if (!error && CFArrayGetCount(credentials)) { CFDictionaryRef credential = CFArrayGetValueAtIndex(credentials, 0); NSString *username = CFDictionaryGetValue(credential, kSecAttrAccount); NSString *password = CFDictionaryGetValue(credential, kSecSharedPassword); dispatch_async(dispatch_get_main_queue(), ^{ [serverManager attemptLoginWithUsername:username password:password]; }); } else { dispatch_async(dispatch_get_main_queue(), ^{ [self showLoginUI]; }); } });
Page 132
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { if (!error && CFArrayGetCount(credentials)) { CFDictionaryRef credential = CFArrayGetValueAtIndex(credentials, 0); NSString *username = CFDictionaryGetValue(credential, kSecAttrAccount); NSString *password = CFDictionaryGetValue(credential, kSecSharedPassword); dispatch_async(dispatch_get_main_queue(), ^{ [serverManager attemptLoginWithUsername:username password:password]; }); } else { dispatch_async(dispatch_get_main_queue(), ^{ [self showLoginUI]; }); } });
Page 133
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { if (!error && CFArrayGetCount(credentials)) { CFDictionaryRef credential = CFArrayGetValueAtIndex(credentials, 0); NSString *username = CFDictionaryGetValue(credential, kSecAttrAccount); NSString *password = CFDictionaryGetValue(credential, kSecSharedPassword); dispatch_async(dispatch_get_main_queue(), ^{ [serverManager attemptLoginWithUsername:username password:password]; }); } else { dispatch_async(dispatch_get_main_queue(), ^{ [self showLoginUI]; }); } });
Page 134
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { if (!error && CFArrayGetCount(credentials)) { CFDictionaryRef credential = CFArrayGetValueAtIndex(credentials, 0); NSString *username = CFDictionaryGetValue(credential, kSecAttrAccount); NSString *password = CFDictionaryGetValue(credential, kSecSharedPassword); dispatch_async(dispatch_get_main_queue(), ^{ [serverManager attemptLoginWithUsername:username password:password]; }); } else { dispatch_async(dispatch_get_main_queue(), ^{ [self showLoginUI]; }); } });
Page 135
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { if (!error && CFArrayGetCount(credentials)) { CFDictionaryRef credential = CFArrayGetValueAtIndex(credentials, 0); NSString *username = CFDictionaryGetValue(credential, kSecAttrAccount); NSString *password = CFDictionaryGetValue(credential, kSecSharedPassword); dispatch_async(dispatch_get_main_queue(), ^{ [serverManager attemptLoginWithUsername:username password:password]; }); } else { dispatch_async(dispatch_get_main_queue(), ^{ [self showLoginUI]; }); } });
Page 136
Obtaining Safari Credentials
SecRequestSharedWebCredential(NULL, // use domains from entitlement NULL, // find all matching usernames ^(CFArrayRef credentials, CFErrorRef error) { if (!error && CFArrayGetCount(credentials)) { CFDictionaryRef credential = CFArrayGetValueAtIndex(credentials, 0); NSString *username = CFDictionaryGetValue(credential, kSecAttrAccount); NSString *password = CFDictionaryGetValue(credential, kSecSharedPassword); dispatch_async(dispatch_get_main_queue(), ^{ [serverManager attemptLoginWithUsername:username password:password]; }); } else { dispatch_async(dispatch_get_main_queue(), ^{ [self showLoginUI]; }); } });
Page 137
Telling Safari About Credentials
Page 138
Telling Safari About Credentials
SecAddSharedWebCredential(CFSTR("example.com"), username, password, ^(CFErrorRef error) { NSLog(@"%@", error); });
Page 139
Telling Safari About Credentials
SecAddSharedWebCredential(CFSTR("example.com"), username, password, ^(CFErrorRef error) { NSLog(@"%@", error); });
Page 140
Telling Safari About Credentials
SecAddSharedWebCredential(CFSTR("example.com"), username, password, ^(CFErrorRef error) { NSLog(@"%@", error); });
Page 141
Telling Safari About Credentials
SecAddSharedWebCredential(CFSTR("example.com"), username, password, ^(CFErrorRef error) { NSLog(@"%@", error); });
Page 142
Telling Safari About Credentials
SecAddSharedWebCredential(CFSTR("example.com"), username, password, ^(CFErrorRef error) { NSLog(@"%@", error); });
Page 143
Telling Safari About Credentials
SecAddSharedWebCredential(CFSTR("example.com"), username, password, ^(CFErrorRef error) { NSLog(@"%@", error); });
Page 144
Telling Safari About CredentialsUpdating a CredentialSecAddSharedWebCredential(CFSTR("example.com"), username, newPassword, ^(CFErrorRef error) { NSLog(@"%@", error); });
Page 145
Telling Safari About CredentialsUpdating a CredentialSecAddSharedWebCredential(CFSTR("example.com"), username, newPassword, ^(CFErrorRef error) { NSLog(@"%@", error); });
Page 146
Telling Safari About CredentialsDeleting a CredentialSecAddSharedWebCredential(CFSTR("example.com"), username, NULL, ^(CFErrorRef error) { NSLog(@"%@", error); });
Page 147
Telling Safari About CredentialsDeleting a CredentialSecAddSharedWebCredential(CFSTR("example.com"), username, NULL, ^(CFErrorRef error) { NSLog(@"%@", error); });
Page 148
Generating a Password
CFStringRef suggestedPwd = SecCreateSharedWebCredentialPassword();
Page 149
Generating a Password
CFStringRef suggestedPwd = SecCreateSharedWebCredentialPassword();
JVA-9cx-ZfT-c4Hk6S-kgS-c7E-hhK2H4-mVC-dx3-Vbv9uB-VC9-52L-9H5meR-7CK-d3B-em9mMJ-8LN-Wf4-Jsbwu4-PGe-gEQ-xTE645-3bY-7CG-3mn5B8-T8E-rRG-EtBESB-naN-PrF-s3rwN4-NUq-dHB-oU9Z7k-n3r-nqB-oNPT6h-JtS-e5L-UUfJJz-Yar-BXt-KY4
Page 150
Error Conditions
Condition CFErrorGetCode() CFErrorCopyDescription()
Missing entitlement errSecParam "No domain provided”
Missing entitlement errSecMissingEntitlement"example.com not found in
com.apple.developer.associated-domains entitlement"
Domain not approved errSecItemNotFound "no matching items found"
No saved credentials errSecItemNotFound "no matching items found"
Page 151
Error Conditions
Condition CFErrorGetCode() CFErrorCopyDescription()
Missing entitlement errSecParam "No domain provided”
Missing entitlement errSecMissingEntitlement"example.com not found in
com.apple.developer.associated-domains entitlement"
Domain not approved errSecItemNotFound "no matching items found"
No saved credentials errSecItemNotFound "no matching items found"
Page 152
Error Conditions
Condition CFErrorGetCode() CFErrorCopyDescription()
Missing entitlement errSecParam "No domain provided”
Missing entitlement errSecMissingEntitlement"example.com not found in
com.apple.developer.associated-domains entitlement"
Domain not approved errSecItemNotFound "no matching items found"
No saved credentials errSecItemNotFound "no matching items found"
Page 153
Error Conditions
Condition CFErrorGetCode() CFErrorCopyDescription()
Missing entitlement errSecParam "No domain provided”
Missing entitlement errSecMissingEntitlement"example.com not found in
com.apple.developer.associated-domains entitlement"
Domain not approved errSecItemNotFound "no matching items found"
No saved credentials errSecItemNotFound "no matching items found"
Page 154
Error Conditions
Condition CFErrorGetCode() CFErrorCopyDescription()
Missing entitlement errSecParam "No domain provided”
Missing entitlement errSecMissingEntitlement"example.com not found in
com.apple.developer.associated-domains entitlement"
Domain not approved errSecItemNotFound "no matching items found"
No saved credentials errSecItemNotFound "no matching items found"
Page 155
Error Conditions
Condition CFErrorGetCode() CFErrorCopyDescription()
Missing entitlement errSecParam "No domain provided”
Missing entitlement errSecMissingEntitlement"example.com not found in
com.apple.developer.associated-domains entitlement"
Domain not approved errSecItemNotFound "no matching items found"
No saved credentials errSecItemNotFound "no matching items found"
Page 156
DemoPutting it into practice
Page 157
Safari Credentials in Native Apps
iPad iPhone
Mac
iPhone
Page 158
Safari Credentials in Native Apps
iPad iPhone
Mac
iPhone
Page 159
Credentials on the Web
Ricky Mondello Safari and WebKit Engineer
Page 161
Expressing Intent
Page 162
Expressing Intent on the Web
Page 163
The Password Lifecycle
No Account
Logged Out
Logged In Change Password
Created Account
Page 164
Test Your Website with Safari AutoFill
Page 165
Testing Your Site and Safari AutoFillThe password lifecycle
No Account Logged In Change Password
Created Account
Logged Out
Page 166
Testing Your Site and Safari AutoFillCreating an account
No Account Logged In Change Password
Created Account
Logged Out
Page 167
Testing Your Site and Safari AutoFillCreating an account
No Account Logged In Change Password
Created AccountCreated Account
Logged Out
Page 168
Testing Your Site and Safari AutoFillLogging in with saved credentials
No Account Logged In Change Password
Created Account
Logged Out
Page 169
Testing Your Site and Safari AutoFillLogging in with saved credentials
No Account Logged In Change Password
Created Account
Logged OutLogged Out
Logged In
Page 170
Testing Your Site and Safari AutoFillChanging a password
No Account Logged In Change Password
Created Account
Logged OutLogged Out
Logged In
Page 171
Testing Your Site and Safari AutoFillChanging a password
No Account Logged In Change Password
Created Account
Logged OutLogged Out
Logged In Change PasswordLogged In
Page 172
Logged Out
Testing Your Site and Safari AutoFillResetting a password
No Account Logged In Change Password
Created Account
Page 173
Logged OutLogged Out
Testing Your Site and Safari AutoFillResetting a password
No Account Logged In Change Password
Created Account
Change Password
Page 174
Testing Your Site and Safari AutoFillLogging in for the first time
No Account Logged In Change Password
Created Account
Logged Out
Page 175
Testing Your Site and Safari AutoFillLogging in for the first time
No Account Logged In Change Password
Created Account
Logged OutLogged Out
Logged In
Page 176
Testing Your Site and Safari AutoFillWhat to do if something doesn’t work
No Account Logged In Change Password
Created Account
Logged Out
Page 177
Your Forms’ Intent
Page 178
Your Forms’ Intent
<input type="text" autocomplete="username"> !
<input type="password" autocomplete="current-password"> !
<input type="password" autocomplete="new-password">
New values for the autocomplete attribute
Page 179
<form id="login" action="login.php" method="post"> !
<input type="text" autocomplete="username"> !
<input type="password" autocomplete="current-password"> !
<input type="submit" value="Log in"> <form>
Logging in
Log in
Username
Password
Page 180
<form id="signup" action="signup.php" method="post"> !
<input type="text" autocomplete="username"> !
<input type="password" autocomplete="new-password"> !
<input type="submit" value="Sign up"> <form>
Signing up
Sign up
Username
Password
Page 181
<form id="signup" action="signup.php" method="post"> !
<input type="text" autocomplete="username"> !
<input type="password" autocomplete="new-password"> !
<input type="password" autocomplete="new-password"> !
<input type="submit" value="Sign up"> <form>
Signing upWith confirmation
Sign up
Username
Password
Confirm Password
Page 182
<form id="change-password" action="update-user.php" method="post"> !
<input type="text" autocomplete="username" readonly value="rmondello"> !
<input type="password" autocomplete="current-password"> !
<input type="password" autocomplete="new-password"> !
<input type="submit" value="Change Password"> <form>
Changing One’s PasswordWhile logged in
Change Password
Username
Current Password
New Password
rmondello
Page 183
Changing One’s PasswordWhile logged in
<form id="change-password" action="update-user.php" method="post"> !
<input type="text" autocomplete="username" readonly value="rmondello"> !
<input type="password" autocomplete="current-password"> !
<input type="password" autocomplete="new-password"> !
<input type="submit" value="Change Password"> <form>
Change Password
Username
Current Password
New Password
rmondello
Page 184
Change Password
Changing One’s PasswordWhile logged in
Current Password
New Password
<form id="change-password" action="update-user.php" method="post"> !
<input type="hidden" autocomplete="username" value="rmondello"> !
<input type="password" autocomplete="current-password"> !
<input type="password" autocomplete="new-password"> !
<input type="submit" value="Change Password"> <form>
Page 185
<form id="change-password" action="update-user.php" method="post"> !
<input type="text" autocomplete="username" readonly value="rmondello"> !
<input type="password" autocomplete="new-password"> !
<input type="submit" value="Change Password"> <form>
Changing One’s PasswordAfter forgetting the password
Change Password
Username
Password
rmondello
Page 186
Your Forms’ IntentThe autocomplete attribute
username current-password new-password name-full given-name middle-name family-name birthday-year birthday-month birthday-day
email street-address city state province postal-code country phone phone-area-code organization
Page 187
Testing Your Site and Safari AutoFill
No Account Logged In Change Password
Created Account
Logged Out
Page 190
Declaring a State TransitionHistory API
history.pushState !
history.replaceState
Page 191
Declaring a State TransitionHistory API
history.pushState(data, null, "page.html"); !
history.replaceState(data, null, "page.html");
Page 197
iCloud
iCloud Mail
Page 198
iCloud
iCloud Calendar
iCloud Mail
Page 199
iCloud
iCloud Calendar
Twitter
iCloud Mail
Page 200
iCloud
iCloud Calendar
Twitter
iCloud Mail
A User Profile
Page 201
iCloud
iCloud Calendar
Twitter
A User Profile
A Tweet
iCloud Mail
Page 202
Declaring a State TransitionHistory API
Home
Profile
AccountSettings
Page 203
Declaring a State Transition
history.pushState({ data: "yourData" }, null);
History API
Home
Profile
Account Settings
Password Updated
Page 206
Safari and Your Website’s ContentIconography and metadata
Page 212
Iconography
In-page markup: <head> <link rel="icon" type="image/png" href="http://www.example.com/favicon.png"> </head> !
Standard path: /favicon.ico
Favicon
Page 213
Iconography
Used on iOS home screen
In-page markup: <head> <link rel="apple-touch-icon" sizes="152x152" href="/apple-touch-icon.png"> </head>
See Configuring Web Applications on the Safari Web Content Guide
Apple Touch Icon
Page 214
Apple Touch Icon
Page 215
IconographyApple Touch Icon
Page 216
IconographyApple Touch Icon
Page 222
Your Site in Shared Links
Page 223
Your Site in Shared Links
Page 224
<channel> <title>Surfin' Safari</title> <item> <title>Introducing the WebKit FTL JIT</title> <link>https://www.webkit.org/blog/3362/introducing-the-webkit-ftl-jit/</link> <pubDate>Tue, 13 May 2014 02:52:42 GMT </pubDate> <content type="html"> <![CDATA[<p>Just a decade ago…</p>]]> </content> </item> </channel>
Your Site in Shared Links
Page 225
Your Site in Shared Links
Page 227
Reading List
@import SafariServices; !
NSURL *URL = [NSURL URLWithString:@"https://webkit.org/blog/…"]; !
[[SSReadingList defaultReadingList] addReadingListItemWithURL:URL title:@"Introducing the WebKit FTL JIT" previewText:@"Just a decade ago, JavaScript – the programming language…" error:NULL];
Adding from your iOS app
Page 228
Expressing Intent on the Web
Page 229
<head> <title>Surfin' Safari - Archive » Introducing the WebKit FTL JIT</title> </head>
Reading ListBetter titles and descriptions through metadata
Page 230
<head> <title>Surfin' Safari - Archive » Introducing the WebKit FTL JIT</title> !
<meta property="og:title" content="Introducing the WebKit FTL JIT" /> <meta property="og:description" content="Just a decade ago, JavaScript – the programming…" /> </head>
Reading ListBetter titles and descriptions through metadata
Page 231
<head> <title>Surfin' Safari - Archive » Introducing the WebKit FTL JIT</title> !
<meta property="og:title" content="Introducing the WebKit FTL JIT" /> <meta property="og:description" content="Just a decade ago, JavaScript – the programming…" /> </head>
Reading ListBetter titles and descriptions through metadata
Page 232
<head> <meta name="description" content="Just a decade ago, JavaScript – the programming…"> </head>
Reading ListBetter titles and descriptions through metadata
Page 233
Metadata Standards
OpenGraphhttp://ogp.me The Dublin Core® Metadata Initiativehttp://dublincore.org schema.orghttp://schema.org
Resources
Page 236
The Sticky Mobile Website
Page 237
The Sticky Mobile Website
Page 238
The Sticky Mobile Website
Page 239
The Sticky Mobile Website
Page 240
The Sticky Mobile Website
Page 241
The Sticky Mobile Website
m.example.com/articles/lorem
Page 242
The Sticky Mobile Website
Page 243
The Sticky Mobile Website
GET example.com/…example.com
Desktop Layout
Mobile Layout
m.example.com
Page 244
The Sticky Mobile Website
GET m.example.com/…
GET example.com/…example.com
Desktop Layout
Mobile Layout
m.example.com
Page 245
The Sticky Mobile WebsiteRelevant to Handoff
Page 246
The Sticky Mobile Website
GET m.example.com/…
GET example.com/…example.com
Desktop Layout
Mobile Layout
m.example.com
Page 247
The Sticky Mobile Website
GET m.example.com/…
GET example.com/…example.com
Desktop Layout
Mobile Layout
m.example.com
Page 248
Responsive DesignOne site for everyone
GET example.com/…
example.com
Responsive Layout
GET example.com/…
Page 249
Responsive DesignOne site for everyone
Page 250
Related Sessions
• Designing Responsive Web Experiences Marina Friday 10:15AM
Page 253
Related Sessions
• Advanced Media for the Web Nob Hill Tuesday 11:30AM
Page 255
Continuity |ˌkäntnˈ(y)o͞oətē| noun (pl. continuities) the unbroken and consistent existence oroperation of something over a period of time
Page 256
Summary
Use Safari credentials in your apps
Test Safari AutoFill with your website
Use the autocomplete attribute
Deploy high-quality website icons
Express intent with metadata
Unify mobile and desktop websites
Page 257
More Information
Evangelism [email protected]
!
Developer Technical Support http://developer.apple.com/contact
Apple Developer Forums http://devforums.apple.com
Page 258
Related Sessions
• Advanced Media for the Web Nob Hill Tuesday 11:30AM
• Keychain and Authentication with Touch ID Nob Hill Wednesday 10:15AM
• Adopting Handoff on iOS and OS X Mission Wednesday 2:00 PM
• Designing Responsive Web Experiences Marina Friday 10:15AM
Page 259
Labs
• Security Lab Core OS Lab B Wednesday 11:30AM
• Safari and WebKit Lab Media Lab B Wednesday 4:30PM
• Safari and WebKit Lab Media Lab B Thursday 2:00PM
• Security and Privacy Lab Core OS Lab B Thursday 3:15PM