iOS 12 Password Tools: Improving User Security and Experience

Learn how iOS password and security tools can help you generate and securely save passwords, and synchronize passwords between your mobile apps and website.

Version

  • Swift 4.2, iOS 12, Xcode 10
Update note: Lyndsey Scott updated this tutorial for iOS 12, Xcode 10 and Swift 4.2. Matt Luedke wrote the original.

Do any of the following scenarios sound familiar?

  • An app requires you to create a new iOS password and you proceed to type in your cat’s name, as you’ve done with every single site and app that you’ve ever used.
  • You already have an account with a website when you download its app. Your credentials autofill on web, but you can’t remember them when you try to log in on mobile.
  • An app requires that new iOS passwords contain at least 99 characters — with at least one letter, five non-sequential numbers and a prime number of punctuation symbols, excluding ! and *.
  • You keep leaving an app to check the two-step verification code text message it sent you, but can’t seem to remember the random string of characters each time you return.

As users, these types of scenarios make anyone see exceptionally vivid shades of red and perhaps utter equally colorful shades of blue. :]

As developers, this makes iOS password handling a balancing act: On one hand, it’s critical to make the login process as simple as possible; every password requirement you add will increase your users’ motivation to uninstall your app. At the same time, developers have a responsibility to help users stay secure; hackers and abusers stage never-ending attacks on activists, celebrities and John Q. Public.

iOS Password Tools to the Rescue!

But fear not! iOS Password AutoFill, automatic strong passwords and security code autofill are all at your service!

In this tutorial, you’ll put these iOS 12 security tools to work, enabling your users to:

  • Share and synchronize passwords between your website and your app.
  • Save and update iOS passwords.
  • Auto-generate secure passwords.
  • Access verification security codes sent via text message without leaving the app.
Note: This tutorial requires that you have a paid iOS Developer Program membership.

While this tutorial requires very little coding on your end, it assumes that you have some familiarity with Xcode and Terminal.

Getting Started

Download the materials for this tutorial using the Download Materials button found at the top and bottom of this page. Unzip the UltraMotivator files and open UltraMotivator-starter/UltraMotivator.xcodeproj in Xcode. Then, build and run the starter app on your simulator.

A view of the starter's login screen.

Starter project login screen, sign-up screen, and sign-up error.

Starting on the login screen, tap the Sign Up button in the bottom-right corner to navigate to the sign-up page. Enter a username and password, then tap Sign Up. An Error dialog should pop up. In the app’s current state, you can’t yet log in because the app’s back end doesn’t yet exist.

Note: Even if you haven’t set your text field content types, iOS still may recognize your fields as login-related. It does so by analyzing your placeholders, UI elements and on-screen text. This means that, while iOS may automatically offer iOS password autofill, strong password generation or code autofill, this behavior isn’t guaranteed, so it’s best to put these features in place explicitly.

Sadly, unauthenticated users can’t access on-demand encouragement, so the starter app is rather uninspiring for now. But, lucky for them, you’re about to code their path to inspirational quotation enlightenment!

iOS Password

A Peek at the Web App

Switch back to Finder and navigate to UltraMotivator-starter ▸ Motivational-Server. This directory contains the server app that you’ll deploy to the web to get the iOS app up and running.

Like the iOS app, the server app is written in Swift using Vapor, a modern web framework for Swift. While you won’t cover the details of Vapor here, you can check out our Video Course and book if you’d like to learn more.

Take a moment to get a bird’s-eye view of the web app’s structure. Most notably, this includes:

  • Resources ▸ Views: Contains Vapor’s Leaf files, which lay out the web page templates.
  • Sources ▸ App: Contains the server app logic. This logic will handle authentication and random motivational quote generation.

For this tutorial, you’ll deploy your server app to Heroku, since it offers a quick, easy and free solution. If you don’t already have a Heroku account, sign up to create one at https://signup.heroku.com/. Make note of your password, because you’ll need it later.

Creating a Heroku App

Visit https://dashboard.heroku.com and log in to Heroku.

In the upper right-hand corner, click the button labeled New, then select Create new app.

Heroku new app button

On the next screen, either enter a unique app name or leave the App name field blank. Then, choose the deployment region.

Heroku new app screen

If you leave App name blank, Heroku will automatically generate a unique slug to identify the app for you. Whether you create a name or Heroku assigns you one, make note of your app name because you’ll need it later when configuring your app. Click Create app.

After creating your app, Heroku redirects you to your app’s page.

Heroku application page

Select the Resources tab near the top of the page. Under the section entitled Add-ons, enter postgre and you’ll see an option for Heroku Postgres; select this option.

Heroku search for postgres

This takes you to one more screen that asks what type of database to provision.

Heroku provisioning screen

Choose the Hobby Dev — Free Plan name. Click the Provision button, and Heroku will do the rest.

Once you’ve finished, the database will appear under the Resources tab, indicating that your web app has been successfully created.

Heroku resources tab

Getting Your App’s Identifiers

Now that you’ve set up Heroku to host your web app, it’s time to share Ultra Motivator’s credentials between web and mobile. To do this, you’ll need to set up a two-way association between your iOS app and the web server.

First, you’ll make your iOS app identifiable and grant it the necessary permissions. Sign in to Apple’s Developer Portal. In Member Center, select Certificates, Identifiers & Profiles.

Apple Certificates, Identifiers and Profiles overview

Go to Identifiers ▸ App IDs and select the Add button. Enter an App ID Description, then scroll down to the App ID Suffix ▸ Explicit App ID section and create a Bundle ID; this will be your App ID. Scroll down to the App Services section and enable the Associated Domains and AutoFill Credential Provider services.

Apple App Services options

Scroll down and click Continue to save. On the summary page, you’re presented with next, confirm that Associated Domains and AutoFill Credential Provider are both enabled. Then, scroll to the bottom and click Register. You should then see a Registration Complete page confirming that you’ve successfully completed this step.

Apple: Summary of changes

Make note of the Prefix in the app’s header information display, to the right of the ID icon. This is your Team ID.

Adding App Identifiers to the Web App (Locally)

Now, open Terminal and cd into UltraMotivator-starter/Motivational-Server. For example, if you’ve unzipped the UltraMotivator files onto your desktop, you can enter:

cd ~/Desktop/UltraMotivator-starter/Motivational-Server

This sets Motivational-Server — the directory containing the server app — as the working directory.

Within Motivational-Server, create a Public directory and then a nested .well-known directory within it by entering the terminal command:

mkdir -p Public/.well-known/

Then, while replacing with your Team ID and with your App ID, enter the following:

echo '{"webcredentials": {"apps": ["<#Team Identifier#>.<#App Bundle ID#>"]}}' \
  > Public/.well-known/apple-app-site-association
Note: The apps array can hold multiple “.” strings. This allows you to set up two-way associations between multiple iOS apps and a single domain.

It’s important to use the exact filename apple-app-site-association as iOS will be looking for a file with this precise name.

Switch to Finder and navigate to UltraMotivator-starter/Motivational-Server/Public/.well-known/apple-app-site-association. If you’re unable to see .well-known, use the shortcut Command+Shift+. to toggle hidden file visibility. Open the association file in a text editor to confirm that it contains the specified JSON.

Setting Up Heroku CLI

Now that your mobile app’s IDs are in place, you’ll upload these to your web app. To do this, you’ll need the help of Heroku’s command line interface tools — Heroku CLI.

You’ll need Homebrew to install Heroku CLI. If Homebrew isn’t already installed on your computer, install it by entering the following into Terminal:

/usr/bin/ruby -e \
  "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Now, you can install Heroku CLI via Homebrew with terminal command:

brew install heroku/brew/heroku

Once you’ve installed Heroku CLI, log in to your account by entering the following into your terminal:

heroku login

Then, enter your Heroku credentials, when prompted.

Once you’ve signed in, confirm your login was successful by entering:

heroku auth:whoami

This confirms that whoami outputs the correct email address.

Deploying the Server App

Heroku will deploy your Vapor app via Git, so you’ll need to put your server app into a Git repository.

In Terminal, confirm that Motivational-Server is still your working directory. To do so, enter the command pwd for the full directory address. Then, enter these commands while replacing with the Heroku app name that you set earlier in the “Creating a Heroku App” section of this tutorial:

git init
git add .
git commit -m "Vapor server"
heroku git:remote -a <Heroku app name>

With these commands, you’ve added your remote server app as a local Git repository.

Heroku uses a Buildpack to provide the recipe for building your app when you deploy it. Enter the following in Terminal:

heroku buildpacks:set https://github.com/vapor-community/heroku-buildpack

This sets the Buildpack for your app.

Finally, to deploy your app to Heroku, enter:

git push heroku master

This pushes your master branch to your Heroku remotely. You’ll have to wait several minutes as everything builds.

Note: If Heroku’s current deployment stack version is incompatible with the community buildpack, the push will fail. The error message will tell you exactly what happened and how to fix it. For example, you might see a message telling you to enter the command:
heroku stack:set heroku-16 -a <your-application-name>

Follow the instructions in the error message, then repeat the push command.

Heroku normally starts your app automatically when it finishes building. But, for safe measure, to manually start running your app, enter:

heroku ps:scale web=1

Then, to open your web app, enter heroku open. You can also find your web app URL listed in the Heroku dashboard underneath Settings ▸ Domains and certificates.

View of Heroku app running and displaying a log in screen

Congrats! You’re now the proud owner of a website capable of recognizing your iOS app via apple-app-site-association file. You can view your apple-app-site-association file at https://[your domain]/.well-known/apple-app-site-association. You’ve conquered the first half of your two-way association: Take a moment to bask in the glory!

iPhone enjoying a well-deserved iOS Password celebration!

Time for a well-deserved celebration!

Completing the Two-Way Association

OK, bub, that’s enough basking! Now, it’s time to configure your iOS app to recognize your website, thus completing the two-way association. Before moving on, make note of your Heroku app domain in your browser’s Location bar, as you’ll need it in a moment.

Open UltraMotivator in Xcode, select your target at the top of the left-hand Project navigator, and click on the General tab.

Xcode General tab

In the Identity section, set the Bundle Identifier to your App ID. In the Signing section, check Automatically manage signing, then select the Team associated with the app: Xcode should now generate a provisioning profile and signing certificate. Any errors on your General page should now vanish.

At the bottom of the page, add AuthenticationServices.framework to Linked Frameworks and Libraries. You’ll need AuthenticationServices to integrate iOS password autofill.

Xcode Linked Frameworks and Libraries

Next, click the Capabilities tab. Find the option for Associated Domains and switch it ON to activate this capability.

Xcode: Enabling Associated Domains

Now, click +, then add your Heroku app’s domain to the list using the following format:

webcredentials:[your domain]

Assuming you’ve set up your App ID’s capabilities correctly, check-marked labels should appear below your listed domain. These check marks confirm that you’ve added the associated domain feature to both your entitlement file and app ID.

Xcode: Checkmarks showing successful Entitlements results

You should now be able to see UltraMotivator.entitlements in the left-hand Project navigator. This entitlements file contains the data you just entered, wrapped in a property list.

Xcode: Entitlements plist

iOS uses this Entitlements File to check your code-signing identity and provisioning profile.

Return to Target ▸ Capabilities, locate Autofill Credential Provider, and switch it to ON.

Xcode: Autofill Credential Provider set to On

Once again, check marks should appear — this time, confirming that you’ve added the autofill credential provider feature to both your App ID and entitlements file. It also confirms that you’ve included the AuthenticationServices.framework.

Putting It All Together

Phew! That’s a lot of micro steps! Happily, now it’s time to wire everything up. :]

Return to UltraMotivator.xcodeproj in Xcode, open API.swift and find the following code on line 46:

static let baseURL = URL(string: "https://[your domain]")

Replace “[your domain]” with the Heroku app name that you copied and used previously.

Note: When using Heroku, your domain will likely follow the format [your app name].herokuapp.com

API.swift contains API calls capable of communicating with the server app at your domain. These calls help perform user log in, registration, log out, password changes and random motivational-quote generation. Most of these calls are already integrated into the iOS app. Now that you’ve added your domain, authentication should work as intended.

Next, you’ll add iOS password autofill, strong password generation and security code autofill in Interface Builder. Open Main.storyboard to get started.

Select the Username field on the Login view controller. Open the Attributes inspector tab in the right-hand Inspector pane. Locate the Text Input Traits section and set Content Type to Username.

Inteface Builder: Adding iOS password form controls

Now, select the Password field and set its Content Type to Password.

Similarly, on the Signup view controller, change the Username field’s Content Type to Username. Then, change the New Password field’s Content Type to New Password so that this field will now autofill a strong password suggestion.

Finally, open OneTimeCodeViewController.swift. Insert the following at line 42:

oneTimeCodeField.textContentType = .oneTimeCode

By setting textContentType to .oneTimeCode, whenever iOS detects a security code in an incoming message while the user is viewing this two-factor authentication screen, the QuickType bar above the keyboard will autofill with the code. The user will then be able to enter this code with a single tap, without ever leaving the app.

Customizing iOS Password AutoFill Rules

You’re almost there. Before taking on the final steps, you need to take a final quick detour to learn about iOS Password AutoFill rules.

Apple’s default suggested passwords are 20 characters long and must contain all of the following character types: uppercase, lowercase, digits and hyphens. This produces a strong password that’s compatible with most web services.

In some cases, though, you may need or want to set custom rules for the suggested iOS password. You can add these custom rules to the Password Rule property of any field in which Content Type is set to New Password.

Interface Builder: New iOS Password and Password Rule fields

iOS Password AutoFill rules require the following format:

required: (<identifier> | <character-class>), ..., (<identifier> | <character-class>); 
allowed: (<identifier> | <character-class>), ..., (<identifier> | <character-class>); 
max-consecutive: <non-negative-integer>

They use these keywords:

  • required: Use “required” if the generated password must contain at least one member of the specified character class. To combine character classes, separate them with commas. For example, required: X, Y is equivalent to required: [XY] where X and Y represent character classes.
  • allowed: Use “allowed” if the restrictions specify a subset of allowed characters. If you don’t include the allowed property, and just include required, the password can only contain the required characters. If you only specify allowed and not required, then the password can only contain the characters that you’ve explicitly allowed. If you specify neither required or allowed, then your password can contain any ASCII printable characters.
  • max-consecutive: Follow “max-consecutive” with a positive integer to limit the number of times a character can appear consecutively.
  • minlength: Follow the “minlength” keyword with a positive integer to specify the minimum password length.
  • maxlength: Follow the “maxlength” keyword with a positive integer to specify the maximum password length.

You must use “allowed” and “required” alongside these permitted character classes:

  • upper: Represents uppercase letters A – Z.
  • lower: Represents lowercase letters a – z.
  • digit: Represents digits 0 – 9.
  • special: Includes -().&@?’#,/”+ and Space.
  • ascii-printable: Includes all ASCII characters.
  • unicode: Includes all unicode characters.
  • Or specify a custom character class by listing whichever ASCII characters that you’d like to include within square brackets. For example, “allowed: [a1,-]” allows characters “a”, “1”, “,” and “-“.

A Super Fun Happy Quiz? Oh, Boy!!

Think you get the gist? Try your hand at the following exercise. For each password rule, determine whether Password AutoFill can generate A, B, C and/or D. Each answer may consist of none|any|all of the multiple-choice options:

  1. required: upper, digit; maxlength: 5; max-consecutive: 1;

    A. JEMSP
    B. 43jKL
    C. 39LS2
    D. 92JJK

    [spoiler title=”Answer #2″]Password rule #1 can generate passwords A and C.[/spoiler]

  2. required: lower; required: digit, [$#@]; allowed: upper; minlength: 9; max-consecutive: 2;

    A. jsoeebd1re
    B. Ys2jUJaaauREV
    C. js13&Lk2ja
    D. 29mn$#ki@nd

    [spoiler title=”Answer #1″]Password rule #2 can generate passwords A and D.[/spoiler]

  3. required: lower, special; required: digit, upper; allowed: unicode;

    A. I❤️U
    B. aJEK24
    C. 30 👩‍💻3420
    D. 3 0 4 2

    [spoiler title=”Answer #1″]Password rule #3 can generate passwords B, C and D.[/spoiler]

Congrats on getting through that exercise! That said, according to Apple:

The more restrictions you have on a password, the higher the likelihood that it can be guessed. The hardest-to-guess password rule is allowed: unicode. No password rule at all creates the second most-difficult-to-guess passwords.

So remember those complicated password rules you just painstakingly analyzed? As a general rule, you’ll usually want to avoid them when you can!

iOS Password

Putting Custom Password Rules to Use

That said, you took this quick detour for a very good reason. Whenever you’re integrating with a back end web service, chances are good that you’ll need to use iOS password rules to sync with any specific password requirements that service may impose.

For the sake of testing, imagine that your web back end:

  1. Doesn’t accept special characters.
  2. Needs to be at least 12 characters long.
  3. Requires an uppercase character.

To meet those requirements, open Main.storyboard, select the New Password field in the Signup View Controller Scene, then copy and paste this password rule into New Password Field’s Password Rule field:

required: upper;
allowed: lower, digit;
minlength: 12; 
maxlength: 20;
max-consecutive: 3;

This rule requires at least one uppercase character; it also allows lowercase characters and digits; it generates a password 12 to 20 characters long, and it prevents any character from appearing more than three times consecutively.

As you go forward implementing your own iOS Password AutoFill rules, you can confirm that they work as intended by entering them into Apple’s Password Rules Validation Tool. There, you can review a few a hundred, or even ten thousand, generated passwords to make sure your rules produce the results you need.

Taking It for a Spin

You’ve now set up authentication, strong password autofill, security code autofill and custom iOS password rules. Build and run your iOS app to test it all on a physical iOS device — iOS Password AutoFill won’t work on a simulator.

Tap Sign Up on the bottom-right of the login page to navigate to the sign-up view.

The username field Keyboard Type is “E-mail Address”; so, while the Username field is the first responder, the QuickType bar may suggest email addresses that you’ve used to log in to other services. This is because iOS recognizes this particular username field as a sign-up username field.

After entering a username, select the Password field. It should autofill with a strong password that conforms to the rules that you specified in the field’s Password Rule. Tap Use Strong Password to use the autofill-provided suggestion, then tap Sign Up. An alert will pop up to let you know if you’ve registered successfully.

iOS: Succesful login.

If you see the above alert, congrats! You’ve registered a new account. Tap OK and the sign-up view will dismiss itself to return to the login view.

Saving Your Passwords

There’s just one last piece of the puzzle: automatically saving your newly created credentials. As it turns out, for iOS to recognize that it needs to save a new set of credentials, you must:

  1. Remove the Username and Password fields from the View hierarchy after sign up occurs.
  2. Only clear the Username and Password fields after they’re no longer in the View hierarchy.

Since your app dismisses the sign-up view completely without deleting any fields, it already meets these requirements. Great! But how do you prevent your keychain from saving the credentials of a failed or incomplete sign-in attempt? Good question!

Open SignupViewController.swift, scroll down to viewWillDisappear(_:) and find this code snippet:

if API.token == nil {
  usernameField.text = nil
  passwordField.text = nil
} else {
  API.logout()
}

Here’s what this code does:

When a user signs up successfully, the server returns a token. UltraMotivator’s API.swift class stores this in the variable API.token.

If API.token is nil when the user navigates back to the login view, the sign-up action was not completed. In this case, you set the text fields to nil before leaving the View hierarchy, i.e., in viewWillDisappear(_:). This prevents these invalid credentials from being saved to the user’s keychain.

If API.token is not nil, the sign-up action has been completed successfully. In this case, you log out, leaving the fields’ text intact. iOS will then automatically save those credentials to the user’s keychain.

Checking Under the Hood

To confirm that your iOS password rules work, run the app on your iOS device (not a simulator) and sign up with a few different usernames. Open Keychain Access on your Mac. Select the login keychain, the Passwords category, then search your login passwords for your web app domain.

Keychain Access: iOS passwords stored for UltraMotivator

To view any of the passwords associated with your listed usernames, select it and tap the show password checkbox. Enter your keychain/computer password when prompted, and the password should appear.

Keychain Access: revealing a stored iOS password

According to my keychain, my usernames’ corresponding passwords are “rehnep0xasravezpUg”, “Qyddehziwzek2syhda” and “Qyddehziwzek2syhda.” All three of these conform to the custom password rules defined for the app.

To confirm that credentials aren’t saving when they shouldn’t, enter a username and password but press the Back button without signing up. Check Keychain Access’s login passwords once again to confirm that iOS didn’t save these invalid credentials to the keychain.

Once you’re satisfied that your credentials are saving as intended, return to your iOS device and attempt to log in to the app. Begin entering your username. Your username(s) should either appear in the QuickType bar automatically or after you tap the key symbol on its right side. Select your username and authenticate your keychain access using Touch ID, Face ID or device passcode when prompted. Your iOS password and username will autofill accordingly.

Images showing successful login into UltraMotivator

Submit those credentials and you should now see a two-step authentication screen:

UltraMotivator: 2-step authentication screen

Since two-step authentication is not set up on the back end, don’t wait for a code to automatically come through: You’ll have to test this feature manually.

To determine whether or not a text message contains a security code, iOS scans incoming texts for words like “code” or “passcode” with code string. So, to test this feature, keep Ultra Motivator open and text yourself via Apple’s desktop Messages app. Send yourself a code: “Your code is 1234.” The QuickType bar should then present you with the option to autofill “1234″ into the code field.

UltraMotivator: The QuickType bar presenting a 2-step authentication code

Note: iOS can recognize words equivalent to “code” or “passcode” in all supported iOS languages.

Tap Submit to display the Motivational view controller.

UltraMotivator, displaying a random motivational code

Password Ninja Enlightenment Attained!

Mighty congratulations! You, my friend, are a true and noble Ninja Password Warrior, of the order Geekii Securitus Extremicus!!! (Electronic pocket protector not included.)

iOS Password

Take a moment to get thoroughly inspired by your random motivational quote, then open Safari on your iOS device. Navigate to your login web page by replacing “[your domain]” with your actual domain in the following url:

https://[domain name]/login

Upon tapping the Username field, your web page should present you with the same credentials that you saved during sign up in your iOS app.

The web app login page, with Safari offering to enter the iOS password and username entered into the app

Likewise, if you create a new account via Safari at https://[domain name]/register and return to the iOS app to login, those credentials should autofill.

Where to Go From Here?

Whew! That was a lot of work, but you’ve achieved a lot for your efforts. You’ve now implemented iOS password autofill, generation and synchronization. The login action to your app is now secure, easy to use and integrated directly with your website!

If you haven’t already done so, download the tutorial materials using the Download Materials button at the bottom or top of this tutorial. Look through the final project to see how it compares to your version.

Check out WWDC 2017’s Introducing Password AutoFill for Apps video and WWDC 2018’s Automatic Strong Passwords and Security Code AutoFill video to gain a broader understanding of the features you just implemented.

Have any questions, comments or suggestions? Join the forum discussion below!

Contributors

Comments