Microsoft Entra ID

Add sign-up in an iOS/macOS app by using native authentication

In brief

Learn how to sign up users with email one-time passcode or email and password, and collect user attributes including a username (alias), in an iOS/macOS app by using native authentication.

What Entra admins need to know

Review the documentation change to determine whether it affects tenant configuration, security posture, or rollout plans.

This editorial summary was generated by AI from the documentation changes. Verify important details in the full Microsoft Learn article.

Documentation change

Open on Microsoft Learn ↗

The comparison below is an extract of the Microsoft Learn article showing only the changed content. Open the full article for complete context.

Tutorial: Add sign-up in an iOS/macOS app by using native authentication

[!INCLUDE applies-to-external-only]

This tutorial demonstrates how to sign up a user by using email one-time passcode or username (email) and password, and collects user attributespassword in your iOS/macOS app by using native authentication. You also learn how to collect user attributes during sign-up, including a username (alias), and handle errors.

In this tutorial, you:

[!div class="checklist"]

  • Sign up a user by using email one-time passcode or username (email) and password.
  • Collect user attributes during sign-up.up, including a username (alias).
  • Handle sign-up errors.

Prerequisites

Sign up a user

To sign up a user by using the email one-time passcode or username (email) and password, you collect an email from the user, then send an email containing an email one-time passcode to the user. The user enters a valid email one-time passcode to validate their username.

To sign up a user, you need to:

  • Collect an email from the user. Add validation to your inputs to make sure the user enters a valid email address.
  • Collect a password if you sign up with username (email) and password.
  • Collect a username (alias) if your app supports alias-based sign-in.
  • Collect an email one-time passcode from the user.
  • If needed, collect user attributes.
  • Resend one-time passcode if the user doesn't receive it. } ```
- To sign up a user using **Email one-time-passcode**, we use the library's `signUp(parameters:delegate)` method, which responds asynchronously by calling one of the methods on the passed delegate object, which must implement the `SignUpStartDelegate` protocol. The following line of code initiates the user sign-up process:

    ```swift
    nativeAuth.signUp(parameters: parameters, delegate: self)
    ```

   In the `signUp(parameters:delegate)` method, we pass a `MSALNativeAuthSignUpParameters` instance containing the user's email address from the submission form alongside the delegate (a class that implements the `SignUpStartDelegate` protocol).

- To sign up a user using **Email with password**, use the following code snippets:

    }
    ```
    
    we use theThe library's `signUp(parameters:delegate)` method, whichmethod responds asynchronously by calling one of the methods on the passed delegate object, which must implement the `SignUpStartDelegate` protocol. The following line of code initiates the user sign-up process:
    

    ```swift
    nativeAuth.signUp(parameters: parameters, delegate: self)
    ```

    In the `signUp(parameters:delegate)` method, we pass a `MSALNativeAuthSignUpParameters` instance containing the user's email address and their password alongside the delegate (a class that implements the `SignUpStartDelegate` protocol).

- To implement the `SignUpStartDelegate` protocol as an extension to ouryour class, use:

    ```swift
    extension ViewController: SignUpStartDelegate {
    }
    ```

    The call to `signUp(parameters:delegate)`results in a call to either `onSignUpCodeRequired()` or `onSignUpStartError()` delegate methods. The `onSignUpCodeRequired(newState:sentTo:channelTargetType:codeLength)` is called to indicate that a code has been sent to verify the user's email address. Along with some details of where the code has been sent, and how many digits it contains, this delegate method also has a `newState` parameter of type `SignUpCodeRequiredState`, which gives usyou access to two new methods: 

    - `submitCode(code:delegate)`
    - `resendCode(delegate)`

    To submit the code that the user supplied us with,supplied, use: 
    
    ```swift
    newState.submitCode(code: userSuppliedCode, delegate: self)
    ```
    
    - To implement the `SignUpVerifyCodeDelegate` protocol as an extension to ouryour class, use: 
    
        ```swift
        extension ViewController: SignUpVerifyCodeDelegate {
        }
        ```

        The `submitCode(code:delegate)` accepts a delegate parameter and weyou must implement the required methods in the `SignUpVerifyCodeDelegate` protocol. In the most common scenario, weyou receive a call to `onSignUpCompleted(newState)` indicating that the user has been signed up and the flow is complete.

Collect user attributes during sign-up

The `signUp(parameters:delegate)`results in a call to either `onSignUpCodeRequired()` or `onSignUpStartError()` delegate methods, or in a call to `onSignUpAttributesInvalid(attributeNames: [String])` if it's implemented in the delegate.
  1. To implement the SignUpStartDelegate protocol as an extension to ouryour class, use the following code snippet:

    extension ViewController: SignUpStartDelegate {
    }
    

    If the attributes are invalid, the method onSignUpAttributesInvalid(attributeNames: [String]) is called. In this case, we display the list of invalid attributes to the user. Otherwise, the onSignUpCodeRequired(newState:sentTo:channelTargetType:codeLength) is called to indicate that a code has been sent to verify the user's email address. Apart from details such as the recipient of the code, and number of digits of the code, this delegate method has a newState parameter of type SignUpCodeRequiredState, which gives usyou access to two new methods:

    • submitCode(code:delegate)
    • resendCode(delegate)

User attributes across one or more pages

To spread the attributes across one or more pages, we must set the attributes weyou intend to collect across different pages as mandatory in the customer identity and access management (CIAM) tenant configuration.

We callCall signUp(parameters:delegate) without passing any attributes in the MSALNativeAuthSignUpParameters instance. The next step will beis to call newState.submitCode(code: userSuppliedCode, delegate: self) to verify the user's email.

We implementImplement the SignUpVerifyCodeDelegate protocol as an extension to ouryour class as before, but this time weyou must implement the optional method onSignUpAttributesRequired(attributes:newState) in addition to the required methods:

extension ViewController: SignUpVerifyCodeDelegate {
}

This delegate method has a newState parameter of type SignUpAttributesRequiredState, which gives usyou access to a new method:

  • submitAttributes(attributes:delegate)

To submit the attributes that the user supplied us with,supplied, use the following code snippet:

let attributes = [
newState.submitAttributes(attributes: attributes, delegate: self)

We'll alsoAlso implement the SignUpAttributesRequiredDelegate protocol as an extension to ouryour class:

extension ViewController: SignUpAttributesRequiredDelegate {
- `onSignUpAttributesInvalid`: indicates that one or more attributes that were sent failed input validation. This error contains an attributeNames parameter, which is a list of all attributes that were sent by the developer that failed input validation. 
- `onSignUpAttributesRequired`: indicates that the server requires one or more attributes to be sent, before the user account can be created. This happens when one or more attributes is set as mandatory in the tenant configuration. This result contains attributes parameter, which is a list of `MSALNativeAuthRequiredAttribute` objects, which outline details about the user attributes that the API requires. 
 
Both delegate methods contain a new state reference. We useUse the `newState` parameter to call `submitAttributes(attributes:delegate)` again with the new attributes. 


## Collect a username (alias) during sign-up

The username (alias) is a special user attribute. Like other attributes such as city or country, you collect it during sign-up. Unlike those attributes, the user can later use the alias to sign in. The alias (for example, "johndoe") gives users a shorter, friendlier way to sign in than their email address.

The username (alias) doesn't replace the username (email). During sign-up, the app must always collect the username (email) as the primary identifier, and it collects the alias as an attribute alongside the email. At sign-in, the user can then choose to sign in with either their username (email) or their username (alias).

When the **Username** built-in user attribute is enabled in your sign-up user flow, the SDK accepts it through the same attributes dictionary used for other attributes, as the `flatusername` key. You can pass the username (alias) directly in the `signUp` call so the user doesn't need to go through a separate attributes-required step.

To collect a username (alias), add an input field for the username in your sign-up UI alongside the email field, then pass the alias as an attribute in the sign-up call:

```swift
guard let email = emailTextField.text, !email.isEmpty,
      let password = passwordTextField.text, !password.isEmpty,
      let username = usernameTextField.text, !username.isEmpty else {
    showResultText("Please fill in all fields")
    return
}

let attributes: [String: Any] = [
    "flatusername": username
]

let parameters = MSALNativeAuthSignUpParameters(username: email)
parameters.password = password
parameters.attributes = attributes
nativeAuth.signUp(parameters: parameters, delegate: self)

For email one-time passcode flows (without password), pass the attributes without setting a password:

let parameters = MSALNativeAuthSignUpParameters(username: email)
parameters.attributes = attributes
nativeAuth.signUp(parameters: parameters, delegate: self)

When handling errors for username (alias) sign-up, the error.isUserAlreadyExists property also covers a duplicate alias, and error.isInvalidAttributes surfaces an invalid alias value.

Handle sign-up errors

During sign-up, not every action succeeds. For example, the user might try to sign up with an email address that's already in use, or submit an invalid code.

In ourthe earlier implementation of `SignUpStartDelegate`the SignUpStartDelegate protocol, wethe error was simply displayed when handling the error when we handled the `onSignUpStartError(onSignUpStartError(error)` delegate function.

To enhance the user experience by managing the particular error type, use the following code snippet: ##

Optional: Sign in after a sign-up flow

After a successful sign-up flow, you can sign-sign in a user without initiating a sign-in flow. If the user signed up with a username (alias), they can sign in by using either their email address or their alias. Learn more in the [Tutorial: Sign in user automatically after sign-up in an iOS/macOS app](tutorial-native-authentication-ios-macos-sign-in-user-after-sign-up.md)Tutorial: Sign in user automatically after sign-up in an iOS/macOS app article. ##

Next step