📜 ⬆️ ⬇️

Automatically generated passwords in iOS 12

If your application has a registration function that includes the ability or necessity to enter a new username and password, you will most likely be interested in the innovation in “iOS 12” , which I would like to describe. This is a service that comes up with new passwords for the user, automatically inserts them into the required fields and safely stores them in Keychain .

Automatically generated system passwords are the most resistant to selection (being randomly generated sequences of characters - adjusted for customizable restrictions, but more on that later), relieve application users from having to invent a sequence on their own and flexibly adjust to the needs of a particular application. Support for new functionality is quite easily provided, but not without features. But first things first.

Rights and obligations


First of all, the application must declare its desire to use this functionality. In the “Capabilities” list of the corresponding “Target”, you must first have a domain in the “Associated Domains” list. Strangely enough, the application must have an “Associated Domain” in order to be able to use the generated passwords and store them in the user's Keychain (these two functions are interconnected, and generation cannot be used separately from storage).

If the application already supports the use of shared accounts with your site (the so-called "Shared Credentials") , then this step is already behind. It may also be already behind, and if the application supports Universal Links or another mechanism for handling external URLs .

Anyway, after adding this compatibility, the application will have a new “Entitlement” .

In addition to this more general compatibility, the application should also have “Capatibility” “AutoFill Credential Provider” - this allows the application, if it has permission from the user, to use the system logins and passwords. Adding this compatibility will cause the “AutoFill Credential Provider Entitlement” permission to appear .
By the way, adding this and other features is available only to members of the Apple Developer Program .
The two functions listed must also be included in the Provisioning Profile application.

Dependencies used


Adding the appropriate compatibility will cause the “AuthenticationServices” framework to appear in the Linked Frameworks and Libraries list of the corresponding “target”. This moment has some features that are worth mentioning.

Firstly, the automatic addition of the associated framework may not “work” the first time: when you run the application on a real device from my instance of Xcode version 10.1, the application immediately “crashed” due to the lack of “AuthenticationServices”. Manual removal of the framework and adding it back to the list of related components solved the problem.

Secondly, the automatic addition of the framework marks it as “Required”. If your application implies the ability to work "under" "iOS" versions below 12, it will also cause it to crash at the launch stage "from under" operating systems of lower versions. "AuthenticationServices" are available only for version 12th systems. This problem is solved by marking the framework as “Optional” .

Support in text fields


To support the functionality of the text fields, the textContentType protocol's UITextInputTraits variable is used. The UITextField class, which is most likely used to enter the username and password in the application, already implements the requirements of the protocol we need.

textContentType is a field of type UITextContentType containing only a set of constants. The one we need at the moment is newPassword , which is used to enter a new password currently being invented (not to be confused with just the password used to enter an already existing password).

 let passwordTextField = UITextField() if #available(iOS 12, *) { passwordTextField.textContentType = .newPassword } 

Setting the textContentType value textContentType wrapped in an “API” availability check, because, like the general functionality, this constant is only available starting from “iOS 12”.

In addition to the content type, the text field must ensure secure data entry:

 passwordTextField.isSecureTextEntry = true 

Although the application may well provide the functionality popular in our time to show and hide the entered password, the generated password will be offered only if at this moment the flag is true .

An interesting moment is connected with the content type of the text field: if there is no other field on the screen, with the content type username , the automatically-generated password will not be offered. This is due to the fact that the functionality is based not only on the specified content type of the text field, but on the heuristic analysis of the screen contents .

It seems that the password generation “breaks” the logic of the screens that require you to enter a new password for verification twice. At least, I have not yet found a way to use these two functionalities together. And it seems that I am not alone .

It is worth mentioning that if the login semantically is an email address (and, therefore, really want to have the appropriate type of keyboard), the keyboard and content types can be combined:

 let userNameTextField = UITextField() userNameTextField.keyboardType = .emailAddress userNameTextField.textContentType = .username 

Password Requirements


Often, user passwords must comply with certain rules (have a certain length, include certain characters, etc.). These rules can be specified so that the system takes them into account when generating passwords. This is done through the UITextInputTraits passwordRules property. For example:

 if #available(iOS 12, *) { passwordTextField.passwordRules = UITextInputPasswordRules(descriptor: "required: upper; required: lower; required: digit; minlength: 8;") } 

The property is also available only starting with "iOS 12".

Property Type - UITextInputPasswordRules . Initialization - using the string-handle. The descriptor has an uncomplicated syntax and consists of simple password requirements, separated by a semicolon. Each requirement is a key-value pair, separated by a colon. A key is a type of a rule (for example, “necessarily includes” - required ), and a value is an element that must follow this rule (for example, numbers - digit ).

In the example above, the descriptor means:


A detailed listing of possible keys and values ​​can be found in a nice article published on the NSHipster website .

And “Apple” offers a rather convenient assistant for writing descriptors , which provides not only a convenient way of constructing them, but also checking the generated descriptors in the form of an unlimited number of generated examples. There you can see which rules are applied by default.

Validation


Just in case, it should be clarified that the password generation mechanism does not provide validation of the data entered by the user - you need to take care of this yourself. Which, of course, is quite logical, since The user of the application can reject the proposed auto-generated password or even prohibit the generation of passwords and auto-complete fields.

Interface builder


What is remarkable and in the spirit of our time, all of the listed text field settings can be set in “Interface Builder” , up to “Password Rule”:

image

Functionality check


The functionality is not complicated, but it has a number of nuances: when setting it up, you can easily forget something. In this case, in the “debug” assemblies, when the corresponding text field is activated, the reason for which the functionality is not currently in effect will be displayed in the console.

For example:

 [AutoFill] Cannot show Automatic Strong Passwords for app bundleID: <...> due to error: Cannot save passwords for this app. Make sure you have set up Associated Domains for your app and AutoFill Passwords is enabled in Settings 

You should also always keep in mind that this type of functionality is among the actions for which user permission is required. In this case, as many as two are required:

1. iCloud Keychain;
2. AutoFill.

Conclusion


This seems to be all that should be addressed while providing support for the new functionality. If someone in the process of working on this has encountered other interesting features, I will comment once and, if necessary, will definitely supplement the article.

The feature is quite interesting and, if used properly, is quite capable of improving the user experience of your application!

Source: https://habr.com/ru/post/438580/