How to Build the Schlage Employee Badge Mobile Credential iOS App

How to Build the Schlage Employee Badge Mobile Credential iOS App

Last modified: 01.11.2025

 

The purpose of this guide is to walk a software development team through the steps necessary to build the Schlage Employee Badge Mobile Credential iOS App. The Schlage Employee Badge Quick Start App, along with the Allegion Mobile Access SDK, allows organizations to understand how to build their own app that delivers NFC-based Schlage Credentials to the Apple Wallet (iOS) for use as a replacement or alongside physical card-based credentials. This guide covers the steps for building a Quick Start app. With the information covered in this guide, a software team is prepared to implement their own production ready version of the app.

If you're already familiar with the high-level details of an Employee Badge project and are looking for implementation specifics you can jump to the Building the Employee Badge Quick Start App for iOS section of this guide.

If you're looking for a detailed code review of the Quick Start App code you can jump to the Employee Badge Quick Start App Code Walkthrough located at the end of this guide.

 

ℹ️ Google Wallet App Available in late 2023
If you're looking for how to implement Schlage Employee Badge Mobile Credentials on Google Wallet, that guide will be available in late 2023.

 

The Employee Badge Mobile Credentials App is a fairly simple to use, and the application code is not very complex, however; the process to build the app involves a significant amount of up-front setup and configuration work. This guide seeks to walk through all requirements, dependencies and setup steps to complete the process in a straight-forward and easy-to-consume manner. Where necessary, references to other relevant guides will be linked to ensure no gaps exist to completing integration.

This guide does not assume the reader has advance knowledge of Wallet-based iOS app development. The reader may choose to skip ahead as necessary where topics are already known or dependencies are already in place. Dependencies are listed in the Dependencies section of this guide.

Target Audience for this Guide

This guide is intended to be read and used by anyone who is responsible for technical implementation of a Schlage Employee Badge Mobile Credential project, including mobile app developers, backend developers and project managers. It will also be useful for technical resources responsible for provisioning credential management systems and technical administrators responsible for managing credentials.

Glossary of Terms

Since not everyone who reads this guide will be familiar with language used in physical security and access management, this section covers definitions for terms commonly used in the space.

Term Definition
Access Control System (ACS)  An Access Control System is a software platform that manages access rights of physical spaces and resources based on predefined rules, policies and user access rights. ACSs provide a unified platform for managing access to spaces and resources across an enterprise and capture real-time information related to who is attempting to use/access spaces and resources at all times. Access control systems work alongside access control devices such as locks, credential readers and modules to control physical space access and govern assignment of credentials to support access control management policies.
Bluetooth Low Energy (BLE) BLE is a short-range wireless networking protocol based on Bluetooth, designed especially for short-range communication and used extensively in security, IoT and other applications where device-to-device communication is a requirement. BLE is useful where device battery life is prioritized over high data transfer requirements. Most smart phones available today are BLE-compatible. BLE (beacons) has an indoor broadcast signal range of 10-30 meters.
Credential  In access control, a credential is a piece of data, document or physical object owned by or granted to an individual by a third party that establishes the individual's identity and authority within a given physical and digital environment. Examples of credentials are plastic employee badges, pin codes, physical door keys, or a person's fingerprint or retina. 
Near-Field Communication (NFC)  NFC is a very close proximity wireless communication standard, NFC based on the Radio Frequency Identification (RFID) standard, designed especially for near-physical communication and used extensively in security, IoT and other applications where device-to-device communication is a requirement. Most smart phones available today are NFC-compatible. NFC (tags) has a broadcast range of 4 centimeters. 
Patron  In access control, a patron is a bearer and user of a credential. 
Reader (or Module)  A reader is a device that controls access to a given space or resource. Readers communicate with and 'read' credentials presented to them and work alongside an Access Control System to determine if a patron has authorization to the resource or space it controls. Readers communicate access requests to an access control system, including unauthorized access requests, tamper attempts and breaches. 

Overview of an Employee Badge Mobile Credentials Project

This section covers the high-level process overview of the Employee Badge implementation project and description of each phase of the project.

Discovery, Requirements Analysis & Gap Analysis

 

High Level Employee Badge Project Overview


  1. The company will sign the Apple Participating Partner Agreement to begin receiving access to proprietary documentation and processes as part of initial discovery.

  2. Allegion and the company will conduct a site survey and discovery meetings to determine all requirements, relevant systems and dependencies for implementing a mobile access project. This will include evaluating existing hardware to determine all firmware requirements and configuration updates. This may also include onsite hardware testing and demonstration of readiness.

  3. A company's developers will be granted access to the Schlage Mobile Access NFC SDK and Allegion Mobile Access APIs and the Schlage NFC Quick Start app for iOS. The quick start app will be particularly useful in understanding the structure of an app.

  4. After requirements have been collected, Allegion and company will work together to confirm project goals and determine solutions for any identified gaps.

Scoping & Project Planning

  1. Allegion and company will develop a project plan (based on a standard project) and define scope and timing for the project.

  2. Project resources will be identified and assigned tasks and deliverables. Work hours will be established.

  3. Project kick-off will occur, including sharing contact details and establish regular project meeting cadence.

Implementation & Testing

  1. Project work begins including development work against Schlage APIs and SDKs:

    1. The company will work with Allegion to request access to Apple Wallet-specific developer entitlements for Apple mobile development. These entitlements are granted by Apple only during implementation of an Apple Wallet-based project.

    2. Development work will commence to connect the Allegion Cloud with the company's access control system. This work allows the company to send new patron records to Allegion and receive back a record of a new credential for that patron.

  2. Company hardware (locks, readers) will be configured and prepared for use with Apple Wallet-based mobile credentials

  3. Patron training materials will be developed from template content including how-to guides, FAQs and other supporting documentation

  4. Testing - including end-to-end testing and user acceptance testing - will be completed. Testing will also require review, validation and certification of test cases by Allegion.

Launch & Ongoing Support

  1. Existing credential support staff will be trained on the use of the new wallet-based mobile credential technology and prepared for inbound patron technical support requests.

  2. Production support plan will be implemented based on previously defined and agreed support requirements.

  3. A pilot will be conducted to with a subset of patrons to validate the solution is working and address any outstanding issues with the solution.

  4. The full launch will commence.

Who is involved in an Employee Badge Project?

Implementing an Employee Badge project involves work and coordination across the following organizations and resources:

  • Allegion - provides software and hardware to support implementation. Allegion will also assign a Project Manager and Technical Account Manager to every Mobile Credentials project.

  • Integrator - The integrator is typically responsible for access control hardware installations, management and firmware updates. Employee Badge projects will always include the integrator as they will have critical information and important responsibilities necessary to prepare and configure hardware to support the project.

  • Mobile App Developers - If an app is being built to support this project, mobile app developers will be engaged to complete development. The mobile app is used to authorize the patron, associate the patron with a credential and store newly provisioned credentials into the Apple Wallet.

  • Cloud Developers - An engineer will need to implement an integration between an existing Access Control System and the Allegion Cloud. This integration is required to provision new credentials.

  • Cloud System Engineers - An engineer or technical resource will need to configure single sign-on with the corporate identity service used to manage patron identity. This resource will also support ensuring all systems are able to communicate with each other and supporting activities such as system configurations, whitelisting of IP addresses, etc.

  • Project Manager - A project manager will manage this project and will manage not only the implementation but also support testing, documentation development, support process development, employee/patron training and system launch.

Requirements & Dependencies for an Employee Badge Project

This section covers the required and/or supported hardware, software as well as developer tools and development experience required to implement an Employee Badge on iOS.

Minimum Developer Experience Requirements

Because this is a technical solution and requires development to implement, the development topics in this guide cover topics at a level that expect developers to have knowledge of iOS development processes, tools and technology, including experience with the XCode IDE and use of Cocoapods Dependency Manager. It also assumes developers have had previous experience developing and distributing iOS mobile applications to the Apple App store.

Enterprise Software Requirements

Schlage Employee Badge solutions are deployed within and supported by a corporate information technology environment and infrastructure. There are some technologies that need to exist in that corporate environment to support this solution:

  • Physical Access Control System (PACS) - The organization must manage their locks and readers using a PACS. Allegion can support all major PACS for Employee Badge. Your Allegion Customer Success engineer can provide full details on PACS requirements, the scope of which is not covered in this guide.

  • Identity Management System (IdM) and Single Sign-On (SSO) - The organization must have an IdM deployed that validates employee identity and authenticates/authorizes employee access to corporate applications and systems. SSO must be supported for user authentication.

Mobile Hardware & Software Dependencies

  • Compatible hardware

    • iPhone SE, iPhone 6s, iPhone 6s Plus or later running iOS 15.6 or later

    • Apple Watch Series 3 or later running the latest version of watchOS 8.6 or later

  • Device settings

    • T&Cs with Apple must be accepted

    • iCloud Terms and Conditions must be accepted

    • Passcode, Face ID or Fingerprint must be enabled

    • 2FA -- Two Factor Authentication must be enabled for account login

Lock & Reader Hardware Dependencies

Lock Hardware Dependencies

The table below lists all Schlage locks that support the Mobile Credentials solution:

Locks that support Apple NFC Hardware Version Info Firmware Version for Initial Apple NFC Certification Certification Status
Schlage Control B Locks All hardware versions support Apple NFC 04.12.00 Complete
Schlage Control BM Locks All hardware versions support Apple NFC 05.11.39 Complete
Schlage Control Locks Not pursuing Apple NFC Certification n/a n/a
Schlage NDE Locks All hardware versions support Apple NFC 02.12.72 Complete
Schlage LE Locks All hardware versions support Apple NFC 01.07.67 Complete
Schlage NDEB Locks All hardware versions support Apple NFC 03.07.01 Complete
Schlage LEB Locks All hardware versions support Apple NFC 03.07.01 Complete
Schlage NDEB Si Locks All hardware versions support Apple NFC 03.09.07 Complete
Schlage LEB Si Locks All hardware versions support Apple NFC 03.09.07 Complete
Schlage AD300 Must have MT2/MTK2 Reader AD.A.125 Complete
Schlage AD400 Must have MT2/MTK2 Reader AD AD.A.125 Complete

Readers & Modules Hardware Dependencies

The table below lists all Schlage readers & modules that support the Mobile Credentials solution:

Readers that support Apple NFC Hardware Version Info Firmware Version for Initial Apple NFC Certification Certification Status
Schlage RC Reader Controller
(RC11, RC15, RCK15)
All hardware versions support Apple NFC 01.08.02 In process
Schlage MTB Readers
(MTB11, MTB15, MTBK15)
All hardware versions support Apple NFC 60.47.14,
60.47.27
In process
Schlage MT15, MTK15, MT11, MTMS15, MTMSK15 Readers All hardware versions support Apple NFC 22.02 Complete
Schlage OEM200 Modules All hardware versions support Apple NFC 2.01 Complete
Schlage MT20 Enrollment Readers All hardware versions support Apple NFC 9.02 Complete

 

Employee Badge High-Level Architecture

Employee Badge High-Level Architecture

Schlage Mobile Credentials give patrons the ability to use an NFC-based credential - known as a pass - stored in their phone's/watch's Apple Wallet - to gain access to secured spaces managed by an Access Control System (ACS).

Schlage Employee Badge Mobile Credentials for Apple Wallet are implemented using two technologies from Schlage:

  • The Schlage Mobile Access NFC SDK for iOS - hosted in a Github repository, this SDK brokers interactions between the Allegion Cloud, the patron's Apple Wallet and the PACS Single Sign-On and Corporate Identity Service. Its purpose is to support securely getting Employee Badge mobile credential pass into the Apple Wallet. The Schlage NFC Quick Start App for iOS uses the Mobile Access SDK to demonstrate for engineers how to build an app.

 

ℹ️ Why is a mobile app even required to get an NFC Credential into the Apple Wallet?
As of May 2023, the only means that Apple provides to deliver NFC credentials into the Apple Wallet relies on Apple SDKs. In the future this may change, but for now, an app is required to provision the credential and deliver it to a patron's wallet. This means if you are building a new app for the purpose of delivering credentials (as opposed to modifying an existing app that already does other things in your organization), the app is simple and won't do anything beyond provisioning credentials.

 

  • The Schlage Employee Badge Product API - hosted in the Schlage Cloud, this API exposes the following capabilities:

    • Creation of a patron record and user access rights in the Allegion Cloud (also known as ingress)

    • Gives the PACS partner the ability to suspend, resume and delete user credentials (and propagates these changes with Apple)

    • Gives the PACS partner the ability to update information on the pass including name, photo, email address and other patron information.

Other components needed for implementation include:

  • A Physical Access Control System (PACS - may be provided by Allegion)

  • An Identity Management Platform/Service

  • A Single Sign-On solution (Apple requirement)

  • An endpoint established to capture inbound data responses from the Schlage Cloud

  • Compatible iPhone with Apple Wallet using personal Apple IDs (not Managed Apple IDs)

  • Compatible hardware (locks and readers)

 

ℹ️ An important consideration as you build your app is the method of distribution. Will the app be publicly available in the Apple App Store or available only by a direct link using unlisted app distribution? The distribution method chosen will be an important part of testing and documentation development as you complete your app.

 

The remainder of this document will focus on implementation development activities and is intended for a technical audience (Developers, System Administrators).

 

Building the Employee Badge Quick Start App for iOS

The steps in this topic will focus on preparing your environment and then building the Employee Badge Quick Start app for iOS. This guide assumes the developers working to build the app meet the following minimum dependencies for completing such a task:

  1. Developers have access to the latest version of the Apple XCode IDE.

  2. Developers have a paid Apple Developer Account and access to the Apple Developer Portal

  3. Developers have experience building Apple mobile apps.

  4. Developers have experience using the Cocoapods dependency manager to manage code.

 

Step 1 - Create an Allegion Developer Account and Request a Mobile SDK Subscription Key

If you have not already done so, you'll need to create an account in the Allegion Developer Portal in order to gain access to the API and SDK documentation for the Allegion Employee Badge product. You'll also need this account to obtain a Mobile SDK Subscription Key, which is required to initialize and use the SDK within your app.

 

⚠️ Important: The Mobile SDK Subscription Key is different from the API Subscription Key

As you build an Employee Badge solution, your team will be working with APIs and SDKs across two different projects. Each project outlines specific areas of development effort and uses a different subscription key to interact with Allegion. For this guide/project, we'll be focused on mobile app development and so we'll be using the Mobile SDK Subscription Key to interact with Allegion SDKs.

When building the integration between an Access Control System and Allegion Cloud (the subject of a different guide), an API Subscription Key is used. These are each different keys with different permissions, and are not interchangeable. Mixing/matching keys will result in errors and frustration, so we'll make this callout in several places throughout this and other guides.

 

Follow these steps to create your account and request your Mobile SDK Subscription Key:

 

  1. Click here to reach the Allegion Developer Portal

     

    Allegion Developer Portal Login Page

  2. Click the Sign In link in the top right corner of the landing page.

  3. If you have an account, enter your account details and click Login to log in.

    Allegion Developer Portal Login Challenge

    If you don't have an account, click the Create Profile button to create an account. Enter required details to create an account and complete the email verification step to continue. You'll also need to complete profile details to proceed.

  4. Once you have your profile you'll be directed to your Account Profile page. This is the area where you'll see Product subscriptions to which you've been granted access. If you've never requested access to use Allegion Products then you'll see an empty list here that displays, "No results found":

    Allegion Developer User Profile Page

     

  5. To obtain a key, send an email to Allegion Customer Success requesting a "Mobile SDK Product Subscription Key (developer.support@allegion.com) for the Employee Badge iOS Mobile App. Expect to get a response in no less than 24-48 hours.

     

  6. ℹ️ Limit One Mobile SDK Subscription Key and one API Subscription Key per Company
    Allegion will only grant one Mobile SDK Subscription Key and one API Subscription Key per Company. If multiple developers on your team have an Allegion Developer Account, you'll want to choose one of those accounts to receive the subscription. Only one key is needed for development, regardless of the number of apps you plan to build.

  7. Once a response from Allegion is received confirming your subscription key is created, navigate back to your Allegion Developer Account Profile (from the Allegion Developer Portal home click your name, then Profile) and you'll see your newly granted subscription listed.

     

    Allegion Developer User Profile Page with subscriptions

     

Step 2 - Request Access to the Schlage Employee Badge Quick Start App, Allegion CocoaPods and NFC SDK for iOS (Allegion Github Repository)


Next, we'll request access to the Schlage Employee Badge Quick Start App for iOS codebase. The app uses the Allegion Mobile Access NFC SDK alongside the Allegion Employee Badge APIs to demonstrate how to get an app built and running. It also relies on dependencies found in the Allegion CocoaPods repository. You'll need to request access to all 3 Github repositories. This Quick start app will serve as a reference app to follow along to while you build your own. To make the request just reach out to your Allegion Customer Success engineer and request this access (https://developersupport.allegion.com/hc/en-us/requests/new?ticket_form_id=32387239325844&tf_22658560153748=new_integration) and provide the Github username/email address associated with the Github account to which you need access granted.

 

ℹ️ CocoaPods Dependency Manager

The Allegion iOS SDK uses the Cocoapods Dependency Manager to manage code. If you are not familiar with Cocoapods or have not built apps using Cocoapods we recommend following the getting started guide at the CocoaPods website to understand more about how to use this tool.

 

Step 3 - Request and complete the Apple NDA & Participating Partner Terms and Conditions

If you have not already done so, you'll need to complete and sign Apple's Non-Disclosure Agreement and the Apple Participating Partner Terms and Conditions before you'll be granted access to Apple documentation and Wallet development assets. You can reach out to your Allegion Customer Success resource to begin this process, or contact your Apple representative if you are already working with Apple.

 

Step 4 - Request Apple Entitlements for building Contactless Provisioning features into an App

The next step is to obtain the necessary Apple Entitlements to build iOS/WatchOS apps that can interact with the Apple Wallet for provisioning mobile passes. This capability allows the app you are building to interact with Apple's wallet in order to push a pass into a patron's Apple Wallet so the pass can later be presented to a Schlage reader or lock for credentialed access. Apple's SLA for this is 5 days, if you haven't heard let us know and Allegion can follow up on your request.

 

⚠️ Important: As covered in the previous step, you must have a signed NDA and PPT to build an app before you can complete this request. Apple will not grant the necessary entitlements until these agreements are signed/completed. If your organization has not yet signed or received these agreements then please reach out to your Allegion partnerg manager or Customer Success Engineer to get this going.

 

These entitlements are not publicly available capabilities (such as iCloud, Push Notifications, etc) but rather need to be assigned by Apple to the developer's Apple Developer account. The entitlements to be requested are:

 

  • Contactless Pass Provisioning (SharableCredential) - com.apple.developer.contactless-payment-pass-provisioningDevelopment

  • Contactless Pass Provisioning access for MAIDs - com.apple.developer.contactless-payment-pass-provisioning.maids

 

To make the request to begin building with these features, please create an email using the following template and replacing anything in brackets with proper values/responses:

To: applepayentitlements@apple.com
Email Subject: Mobile Access NFC Entitlement Request: [Your Company Name]
Email Body:

Entitlement Team,

We are currently in the process of integrating digital keys with Apple Wallet for our platform working directly with Allegion. We are working with Allegion Developer Support on this request.

To be able to add keys to Wallet from our application we need special entitlement enabled for our Apple Developer account in App Store Connect. We are requesting access to:

 

  • Contactless Pass Provisioning (SharableCredential) - com.apple.developer.contactless-payment-pass-provisioningDevelopment
  •  

  • Contactless Pass Provisioning access for MAIDs - com.apple.developer.contactless-payment-pass-provisioning.maids
  •  

    Here are the details for our request:


    1. Organization name: [Your Company Name]

    2. Team ID: [Your Apple Developer Account Team ID]

    3. Adam ID: [Your App's Apple Store ID]

    4. Business headquarters country location: [County of your HQ]

    5. What are your proposed use cases for access pass provisioning? 

      We are building an app to support provisioning Schlage Mobile Credentials into Apple Wallet for use with our Access Control Solution and facilities we enable with our technology. We are aware of Apple's 100% use case requirement and intend to build our solution accordingly. [Add as much detail here as necessary.]

    Please respond back for answers to any additional questions.

    ℹ️ Important: If you are building a new app you may not yet have an Adam ID. You can obtain one by submitting your app to App Store Connect to have an Adam ID generated and assigned by Apple. A test flight build will suffice; the app does not need be available in the app store for you to obtain an Adam ID.

     

    While you wait for entitlements to be granted we'll go ahead and create/update your Employee Badge iOS app.

     

    Step 5 - Create a Sandbox Apple Account in Apple App Store Connect

    In order to test working with mobile credentials, you'll need access to a sandbox Apple account. A standard (production) Apple account cannot be used as it will not give your iOS device access to the Sandbox Apple Wallet. Sandbox Apple Accounts are created using Apple App Store Connect.

     

    1. Log into your developer account at Apple App Store Connect. Make sure you have the correct organization selected in the top right corner.

       

      Apple App Store Connect Landing Page

       

    2. Click on User and Access. To create a new sandbox Apple Account, click the + button and complete the pop-up form. Be sure to specify a unique email address not already associated with an existing Apple Account, and click the Create button to create the sandbox account.

       

      Apple App Store Connect User and Access

       

    3. Once you've created your Sandbox account you can us it login to an iOS device. Go to Settings ➡ Account Name and click Sign Out to sign out an active account. Signing out will disable Find My on the device. Once signed out, sign back in using the new Sandbox account login details.

       

    4. To confirm your account is a sandbox account, open the Apple Wallet and ensure that it says "Sandbox" in the upper area of the app.

      iOS Sandbox Wallet

    Once the iOS device is in Sandbox mode it is ready for testing.

     

    Step 6 - Download and Install Cocoapods

    If you have not already, download and install the Cocoapods dependency manager. If you have not already used CocoaPods with an XCode project you'll want to follow the guidance at the CocoaPods home to get CocoaPods dependency manager installed on your development machine. Directions for this can be found at the link provided but are not covered in this guide.

     

    Step 7 - Download the Schlage Mobile Credential Quick Start App for iOS Project

    Once you have access to the Allegion Github repository, you'll need to download the Quick Start App Project. Follow these instructions to download the app and set up your dependencies.

    1. Open XCode.

    2. Select Clone an existing project to clone the Employee Badge Quick Start App from Github

    3. For repository URL enter the Quick Start App Repository URL and click Clone. You'll be prompted to sign in to Github using your Github account name and Personal Access Token (PAN). You can generate a Github PAN for use here at Github under Settings ➡ Developer Settings ➡ Personal access tokens ➡ Tokens (classic)

      Github Login with token

      If - after logging in - XCode prompts that you don't have access to the repository, be sure you've completed the Request API Access step above. If that step is completed please contact your Allegion Customer Success engineer to troubleshoot access.

    4. Choose the main repository, click Clone and select the target home directory to clone the Quick Start App project locally.

    5. Once the project is cloned, open the Command Line/Terminal application and browse to the folder containing the newly cloned project. (As of Q2 2023 this folder is called PersonaManagerEnrollment. This may be in a subdirectory of the directory containing the cloned project. You are in the correct folder when you see a file called Podfile in the same directory.

    6. Update the project using the pod repo update command.

    7. Initialize the project using the pod install command.

      Running pod install command

    8. Next, open the project in XCode. Select a virtual device for simulation and build the project to ensure it runs successfully. The project is not completely configured but it should build nonetheless and reflect that configuration is incomplete.

    9. Virtual device loaded with expected config error

    With a successful build, you are now ready to continue.

    ⚠️ Important: Simulated devices do not have access to the Sandbox Wallet, so further down in this guide you'll need to be able to run this app on a physical iOS device connected to the build machine. To do that, you'll need to ensure your Apple developer certificate is installed on the iOS device.

    Alternative Step 7 - Adding Dependencies to an Existing Project

    If you are modifying an existing app to add Mobile Credential capability, you can follow these steps to add the necessary dependencies.

    1. Login to your Github account.

    2. Once logged into Github, click this link to reach the Allegion Github Repository hosting the iOS SDK.

      Note: If you reach a Github 404 error page instead of the repository this means your Github account doesn't have access to the repository. Please contact your Allegion Customer Success engineer with your Github username so you can be granted access.

      Github 404 error

    3. Once you've confirmed you have access to the SDK, add it your app build using the standard method for installing Podfiles:

      1. Open your project Podfile and add the following lines (if they aren't already there):

        source 'https://github.com/Allegion-Plc/AllegionCocoaPods'
        source 'https://cdn.cocoapods.org/'
        use_frameworks!
      2. Add the pod name and desired version number (all versions for the iOS SDK can be found here):

        pod 'Allegion.Access.MobileAccessSDK.iOS', :git => 'https://github.com/Allegion-Plc/AllegionAccessMobileAccessNFCSDK', :tag => '0.1.1'

        Note that the current version of the Podfile as of time of writing this guide is 3.0.0

      3. Save the Podfile.

     

    Step 8 - Configure your project to use Apple Contactless Pass Entitlements

    Once Apple has responded to your email request for necessary entitlements as outlined in the step above, you'll need to configure your project to use the new capabilities. Follow these steps to configure your project:

    1. Login to your Apple Developer Account and click Identifiers under Certificates, IDs & Profiles.

       

      Apple Certificates, Identifiers and Profiles page

    2.  

    3. From the Certificates, Identifiers & Profiles area, ensure App IDs is displaying under the identifiers droplist on the right. Click the + button next to the Identifiers header to add your application for configuration.

       

      Add an identifier on Apple identifiers page

    4.  

    5. Ensure App IDs is selected and click Continue.

       

      Register an Apple identifier

    6. Select App and click Continue.

       

      Register an identifier for an Apple app

    7.  

    8. Complete the following details to register the Quick Start App:

      Description: Enter a description such as "Schlage Employee Badge Quick Start App"

      Bundle ID: If you have not changed it, the original bundle identifier for the project is:

      com.allegion.PersonaManagerEnrollment

      Feel free to change the bundle id to one of your choosing in the project and use that here.

      Ensure the Explicit radio button is also selected:

    9. Associate an Apple app identifier with an app by bundle id

      Under the Capabilities section, check the following boxes:

      1. Associated Domains
      2. In App Purchase
      3. Wallet

      Apple App Capabilities

    1. Scroll back up and click on the Additional Capabilities section header. Note if you don't see the Additional Capabilities section then you have not yet been granted the entitlements by Apple.

       

      Apple Additional App Capabilities

    2.  

    3. From Additional Capabilities, check the Contactless Pass Provisioning (Shareable Credential) and Contactless Pass Provisioning access for MAIDs entitlements checkboxes and click the Save button.

       

      Add Contactless Pass Capabilities to the app

    4.  

    5. Click the Save button and save your app and click the Confirm button to Confirm your request to modify your app's capabilities.

       

      Confirm Modify Apple App Capabilities Prompt

    6.  

    7. Return to XCode. Now that you have entitlements granted, you will need the entitlements added to your project's entitlements property list file. Open your entitlements plist file (or create a file named <appName>.entitlements in the project main folder if it does not already exist) and ensure it includes the following content:

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
      "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
      <plist version="1.0">
         <dict>
            <key>com.apple.developer.contactless-payment-pass-provisioning</key>
            <true/>
         </dict>
      </plist>
    1. Save the file. The entitlements file should now exist in your project:

      Apple Project Properties List (plist) File

    Next we'll configure the app environment.

     

    Step 9 - General Application Flow & Configuring the App Environment

    At this point the app will run, but is not configured to run properly. This section will set environment details and provide more detail how the app works. Before we cover steps to configure the environment, it's important to understand what the app is designed to do.

    The purpose of this app is to create a digital credential for an authorized user/patron and deposit that credential into the Apple Wallet. The user's identify must be verified as valid in order for the app to progress to generating a credential on their behalf. The process of verifying identity relies on a corporate Identity Management System (IdM). The app will challenge the user to supply a username and password and have the IdM confirm the user as valid. Once the user has been authorized, the app will generate a digital credential and allow the user to deposit/store it in the Apple Wallet. The complete app flow is detailed below.

     

    General Application Flow

    This sequence diagram illustrates the flow of activities the Quick Start app follows in order to deposit a digital credential into the Apple Wallet, and is an appropriate best practice design for developers to follow as they build/modify their own application to include this capability. This flow covers activities across the mobile app, the Allegion Mobile Access SDK, a generic IdP and the Apple (iOS) wallet.

    A detailed code review of these steps is outlined at the end of this guide in the Employee Badge Quick Start App Code Walkthrough.

    Schlage Employee Badge App Sequence Flow Diagram

     

    Note that after a quick device-model check, the first task the app performs is a user authorization. The Quick Start app directs the users to an IdP in a standard OAuth flow to complete the authorization. (The Allegion Quick Start app happens to use Auth0 as the IdP.)

    After authorization, the app will do a series of checks to determine if a credential can be generated for the user. The remaining steps are simplified below:

    Credential Provisioning Decision Tree

    The flow diagram below outlines the decision tree an application should follow to determine if an available NFC should be provisioned to the wallet.

    Credential Provisioning Decision Tree

    Decision 1 - Is Current Device iPhone? - The device type needs to be determined as not all iOS devices (namely iPads) have NFC capabilities.

    Decision 2 - Is the Pass Library available? - The app cannot continue if it does not have necessary resources to generate the pass.

    Decision 3 - (If a credential already exists) - Is there a pass already provisioned? - This check is needed to provide a great user experience. If credential provisioning is attempted when a pass already exists, the wallet presents a generic error without a means to determine the "error" was actually a result of the pass (credential) already being provisioned.

    Decision 4 - (If a credential already exists) - Is the existing pass deactivated? - The app will not provision a credential if the existing credential has been deactivated.

    Decision 5 - (If a credential already exists) - Is the pass Suspended? - The pass can be suspended by the user through the iOS wallet app, through iCloud or by the Access Control system. If a pass is suspended, a link to the pass in the wallet can be provided to the user for further action on their part.

    Decision 6 - (If a credential already exists) - Is there a remote pass provisioned? - A remote pass (credential) can be provisioned to devices associated with the iOS device and the user, such as a watch. Being a remote device, the pass (credential) can be managed / removed from the watch independent of the iOS device. If the credential is on the iOS device but not on the remote device, provisioning can still be completed in order to add the pass to the remote device.

    Decision 7 - (If a credential already exists) - Can the configuration as built be provisioned? - The app will confirm that the configuration is still valid for provisioning pass.

    Provision Pass - If the app reaches this point, either from Decision 3 or Decision 7, it provisions the credential.

    Now that we've covered the application flow, we'll move to configuring the environment.

    Configuring the Environment

    1. Open the project in XCode.

    2. Open the Environment.plist file which is located in the Supporting Files folder.

      Apple XCode Project Navigator Environments Properties File


      We'll be populating this file with relevant configuration details for our environment based on the configuration you've done in previous steps up to this point. This project by default is set to look at Pilot environment variables. The Info.plist file in the top level project folder specifies which environment variables will be used when building the project.


    3. Expand the Pilot variables section.


    4. For SubscriptionKey, enter the value of your Employee Badge Mobile SDK Subscription Key. You can obtain your Mobile SDK Subscription key from the Allegion Developer Portal. Sign into the portal and then click on your name ➡ Profile. Click the Show link next to the Primary Key row to reveal the subscription key.

      (Note: If you don't have a Subscription Key listed, another developer on your team may have already been granted one. Allegion only grants one Mobile SDK Subscription Key and one API Subscription Key per organization, so check with your team if you think one may have already been created.)

      Copy and paste that key into the Environments file, SubscriptionKey variable, replacing the empty value with the value of your key. (Be sure to paste in the Pilot variables section.)

      ⚠️ Important: The Mobile SDK Subscription Key is different from the API Subscription Key

      As you build an Employee Badge solution, your team will be working with APIs and SDKs across two different projects. Each project outlines specific areas of development effort and uses a different subscription key to interact with Allegion. For this guide/project, we'll be focused on mobile app development and so we'll be using the Mobile SDK Subscription Key to interact with Allegion SDKs.

      When building the integration between an Access Control System and Allegion Cloud (the subject of a different guide), an API Subscription Key is used. These are each different keys with different permissions, and are not interchangeable. Mixing/matching keys will result in errors and frustration, so we'll make this callout in several places throughout this and other guides.


      Modify the Environments Properties File in XCode

    5. For IntegrationId, you'll populate this value with the Integration ID sent to your team by Allegion Customer Success This ID is created for your team by Allegion upon request for provisioning a Schlage Mobile Credentials PACS Configuration, which is covered in the Credential Lifecycle Management ACS Integration Guide. If you have yet requested a Configuration please review that guide for details or reach out to Allegion Customer Success for assistance.

    6. For Domain, you'll populate this with the domain URL of your Identity Management System. This can be obtained from your IdM's application-specific configuration settings.

    7. For ClientId, you'll populate this with a Client ID value obtained from your Identity Management System. This can be obtained from one of your IdM applications application-specific configuration settings.

    8. For Audience, you'll populate this with the following value: https://api.allegion.com/employeebadge


      This notes that Allegion's API is the audience, or target, for users making requests using tokens from this identity system.

    9. Save the environment file. While app configuration is now complete, the Identity Management system is not configured to allow authorization requests from the app. The next step will cover IdM configuration. If you try to run the app at this point, you'll get a bit further but still receive an error informing you of a callback URL mismatch:

      App Callback Mismatch

      This error is informing you of the fact that the app is not authorized to make authorization requests to the IdM. We must now configure the IdM to accept and process requests from our new app.

     

    Step 10 - Configure your IdM Callback & Logout URLs

    The Quick Start App was designed to use a standard OAuth flow to process authorization requests. You'll need to configure your Identity Management System to recognize requests coming from the Quick Start app in order for the OAuth process to properly flow. To do this, you'll need to specify your Quick Start App as a valid client for performing authorization requests, which involves designating the app's callback and logout URLs.

    The Quick Start app uses Auth0 for this purpose, so this guide will demonstrate where to make this change in Auth0, however any IdM will allow this setting to be applied.

    1. Log into Auth0.

    2. Browse to Applications and select the application associated with your app. If you have not created one then create a new application by clicking the Create Application button and following the prompts.


      Auth0 Applications


    3. Once in the Application details, scroll down to the Application URIs section. You'll be populating the Allowed Callback URL and Allowed Logout URL:


      Auth0 Application Config Details


    4. Populate the Allowed Callback URLs section with the following value:

      [App Bundle ID]://[IDM Domain]/ios/[App Bundle ID]/callback


      Replace both references of [App Bundle ID] with your App's Bundle Identifier and replacing [IDM Domain] with your Auth0 domain (found at the top of the Auth0 application details page). For instance, given Auth0 domain of myapp.us.auth0.com and App Bundle Identifier of com.mycompany.thisCompanyBadgeApp, you would populate the Allowed Callback URL as:


      com.mycompany.thisCompanyBadgeApp://myapp.us.auth0.com/ios/com.mycompany.thisCompanyBadgeApp/callback

      Auth0 Callback Config

    5. Populate the Allowed Logout URLs section with the following value:

      [App Bundle ID]://[Auth0 Domain]/ios/[App Bundle ID]/callback


      (Note: The Quick Start app happens to use /callback as the endpoint for both callback and logout URLs.)

       

      Replace both references of [App Bundle ID] with your App's Bundle Identifier and replacing [IDM Domain] with your Auth0 domain (found at the top of the Auth0 application details page). For instance, given Auth0 domain of myapp.us.auth0.com and App Bundle Identifier of com.mycompany.thisCompanyBadgeApp, you would populate the Allowed Callback URL as:


      com.mycompany.thisCompanyBadgeApp://myapp.us.auth0.com/ios/com.mycompany.thisCompanyBadgeApp/callback


      Auth0 Logout Config


    6. Scroll to the bottom of the page and click the Save Changes button to save the Auth0 application configuration changes.

      Auth0 Save Changes

     

    Step 11 - Create an API for your Identity Management Application


    Your Identity Management System will need to provide an API to Allegion so tokens generated in your mobile app can be validated for use with the Allegion Cloud service. Specifically, you'll need to create an API that represents Allegion as the target - or, Audience - for tokens representing this user. Auth0 uses the term Identifier to represent the Audience claim for an API. Your app will then specify a URL representing Allegion's Cloud Service as the Audience. This is a simple task in Auth0 but must be done before the Quick Start app will recognize token that Allegion's cloud will consider valid for processing user requests.


    1. From the Auth0 dashboard, browse to Applications --> APIs


      Auth0 APIs

    2. Click the Create API button.

       

      Auth0 APIs

    3. For the Name field, enter a name for your new API such as Allegion Employee Badge App API


    4. For the Identifier field, enter https://api.allegion.com/employeebadge/partner

      Notice this value matches the identifier value you specified in your app's audience environment variable value in the app environment configuration step above.

      Auth0 APIs

       

    5. Click the Create button to create the API. Once done, your API should be successfully created and ready to process requests from your app.


      Auth0 APIs

    Step 12 - Add a custom claim to your Access Token (JWT)

    Allegion relies on a custom claim sent within your access token (JWT) to capture the email address of the user attempting to add a mobile credential. The email address is an important piece of information because it's used as the key/unique identifier that ties identity of the user in the IdM and the Access Control System to a User Access Right record in Allegion's cloud. While other claims in access tokens generated by your IdM may already contain the user email address (such as emailor subclaims), there is no standard or requirement that an IdM must use a specific claim to assert email address. Allegion uses a custom claim to enforce a standard approach for asserting user email since it's important and required

     

    ℹ️ More on JWT Claims
    JWT claims are the pieces of information that make up contents of a JWT and assert details about a user. For example, an ID token can contain a claim called name that asserts that the name of the user authenticating is "Isaac Bond". Claim represent information as name/value pairs where the name is a string and the value can be any valid JSON value. Custom claims are claims that are added to the JWT and arenot part of any standard.

     

    Here's the structure of the custom claim that should be included in access JWTs when using this option:

    "https://api.allegion.com/email": [email]

    Where [email] is replaced by the email address of the user identified by the accessJWT.

    The process for adding a custom claim to your access JWT will be different depending on the IdM you use.

    If you happen to use Auth0 as your IdM provider, the recommended method for adding a custom claim is to add an Action to the Login Flow of your application with custom code to add the claim. Details on adding an action to the Login flow for an Auth0 application for Auth0 are detailed here and a demonstrable video is available here; you may use the following sample code as the basis for your login flow action:


    /**
    * Handler that will be called during the execution of a PostLogin flow.
    *
    * @param {Event} event - Details about the user and the context in which they are logging in.
    * @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
    */
    exports.onExecutePostLogin = async (event, api) => {
    
      // This rule adds the authenticated user's email address to the access and id tokens.
      if (event.authorization) {
    
        const namespace = "https://api.allegion.com";
    
        api.accessToken.setCustomClaim(namespace+"/email", event.user.email);
        api.idToken.setCustomClaim(namespace+"/email", event.user.email);
    	console.log("Adding custom claim -" + namespace+"/email:" + event.user.email);
      }
    };

    The code above defines an action that adds the custom claim to both the access token and ID token. It also outputs a message to the log regarding the additional claim value. If you're using Auth0 you can look at Auth0 logs to confirm your claim is being successfully processed:

    Auth0 Logs

     

    Step 13 - Build and run the app

    Once you've completed all steps above, you are ready to build and run the app.

    1. Open XCode.

    2. Ensure the Sandbox Apple Account (created in the step above) is logged in on the test iOS device.

    3. Plug the test iOS device into the build machine.

    4. Build and run the app, targeting the iOS device. To test adding a credential to Apple Wallet, you'll need to target a physical iOS device - simulated devices do not have access to a Sandbox Wallet, and development testing with mobile credentials requires the Sandbox Wallet. The app should load to the login screen and display the Schlage logo.

      Auth0 Applications


      ℹ️ Note: After a successful build of the app you can focus on changing the logo as well as card art by following our Guide on Employee Badge Card Art

       

    5. Click the Login link. This will load a screen requesting the user to allow an OAuth process to initialize, followed by an OAuth login screen.

      Auth0 Applications


    6. Enter a valid username and password from your IdM to log in. If you have not yet created an account then click the Sign up link to create one.

      ⚠️ Important: At this point you'll need to have a valid user already created in your Access Control System, and your Access Control System will have needed to update the Employee Badge Cloud with the credential records by executing the Create Access Rights API call for a user with the same email address. This guide covers the App side of Mobile Credentials implementation and does not cover Credential Lifecycle Management in detail. For details on Credential Lifecycle Management between you Access Control System and the Allegion Employee Badge cloud please see the PACS Integration Guide.


    7. Login and follow the prompts to provision a mobile credential into the Apple Wallet. This flow will continue, generating a mobile credential and prompting the user to authorize adding the credential to the wallet.

       

      Badge in Apple Wallet


    What do I do if the app displays the error "Authentication Error" after I log in?


    If after logging into the app you are presented with the error, "Authentication Error Additional error detail is not available...", this is potentially due to a misconfiguration of the Employee Badge cloud environment, misconfiguration of your XCode environment variables or misconfiguration of your Auth0 environment. To check the cause of the issue, open XCode and review the latest log output for the following error:


    {"errors":null,"errorCode":"IdTokenInvalid",
    "type":"https://api.allegion.com/errors/producers/MahApi/errorcodes/IdTokenInvalid",
    "details":"Invalid Open Id Token.","producerId":"MahApi","title":"The ID Token failed validation.",
    "instance":null,"status":400}

    This error points to a problem using the token obtained from the IdM to authorize the user as a valid PACS patron. To solve this problem you'll need to work with Allegion Customer Success to ensure your Employee Badge Cloud environment is properly configured based on the properties supplied to Allegion in the Request API Access step of this guide.


    Congratulations

    If all steps were successfully complete you should be able to run your app. From here your credential will need to be provisioned in the Physical Access Control System (PACS) in order to be used, which may be similar to the process for provisioning physical credentials. PACS Configuration is unique to your environment and beyond the scope of this document.


     

     

    Next steps : Building your own app

     

    Apple Wallet Functional Testing and Certification

    Allegion requires functional testing and certification to be completed for all implementations of mobile credentials before any production launch. The following table lists links to test and certification requirements for Google Wallet Mobile Credentials that will be required to be completed by partners before production certification and/or a site launch.

     

    Vertical Test Guidelines
    Functional Testing Guidelines for All Verticals
    Corporate Badge Corporate Badge Testing Checklist
    Campus ID TBD
    Multifamily TBD

     

     

    After a successful build of the app you can focus on changing the logo as well as card art by following our Guide on Employee Badge Card Art (TBD).


    Employee Badge Quick Start App Code Walkthrough

    This section details the Quick Start app as a walkthrough so developers can understand which sections of code are performing each of the tasks outlined in the sequence diagram above. The steps below directly reference the numbered steps in the General Application Flow sequence diagram.

    Step 1 - Authenticate User

    The Allegion Quick Start App enrollment application uses Auth0 as the Identity Provider (IdP) to authenticate the user. Auth0 provides a native SDK for integrating with their functionality. Note that any Identity Management System can be used here. The code for kicking off authentication appears in the AuthenticatedViewController.

    File: AuthenticatedViewController.swift - Project File

    Auth0
        .webAuth(clientId: configuration.clientId, domain: configuration.domain)
        .scope("openid email profile")
        .audience(configuration.audience)
        .start { result in
            switch result {
                case .failure(let error):
                    self.logWriter.log("Login failure - error:\(error)")
                    DispatchQueue.main.async { [self] in
                        let alertView = buildAlertViewWithOKButton(localizedTitle: .authenticateErrorTitle,
                                                                    localizedMessage: .authenticateError)
                        present(alertView, animated: true)
                    }
                case .success(let credentials):
                    self.logWriter.log("login success!!")
                    DispatchQueue.main.async { [self] in
                        showAuthenticatedViewController(credentials: credentials)
                    }
            }
        }

    On line 17, the credentials element contains an accessToken and an idToken. These two elements, along with the integrationId (which is maintained as a configuration property of the application) are provided to the SDK for authentication.

    Step 2 - Initialize SDK

    The SDK is initialized with a Employee Badge Mobile SDK Subscription Key (instructions on obtaining this key detailed above) and an optional TLS certificate pinning pinSet within a MobileAccessConfiguration instance. Please consult the MobileAccess SDK documentation for additional information on the initialize method. The call to the MobileAccessSDK's initialize method is in AuthenticatedViewController:

    File: AuthenticatedViewController.swift - Project File

    let mobileAccessConfiguration = MobileAccessConfiguration(subscriptionKey: parsedSubscriptionKey, pinSet: nil)
    try mobileAccessSDK!.initialize(configuration: mobileAccessConfiguration)
    

    Step 3 - SDK Authenticate

    Before initiating any processes using the MobileAccessSDK, it is necessary to first initialize, and then authenticate. It is necessary to authenticate at least once per SDK instance. It is possible to check the SDKs authentication status and authenticate if the SDK is not authenticated as follows:

    File: AuthenticatedViewController.swift - Project File

    if !mobileAccessSDK.isAuthenticated {
        // SDK is not authenticated - starting authenticate process
        let authenticateRequest = AuthenticateRequest(idToken: credentials.idToken,
                                                      accessToken: credentials.accessToken,
                                                      integrationID: integrationId)
    
       do {
            try mobileAccessSDK.authenticate(request: authenticateRequest, completion: self)
        } catch {
            // ERROR HANDLING
        }
    }
    

    Note the authenticate method takes request and completion parameters. The completion parameter should implement the AuthenticateDelegate protocol in the MobileAccessSDK:

    File: AuthenticateDelegate.swift - Allegion Mobile Access SDK Pod file

    import Foundation
    
    @objc public protocol AuthenticateDelegate {
        /// Callback for a successful result of issuing an authenticate request
        ///
        /// - Parameter stateUpdated: `AuthenticationState` represents the current state of authentication at the moment the update was sent
        @objc func authenticate(stateUpdated: AuthenticationState)
    
        /// Callback for an unsuccessful attempt of issuing an authenticate request
        ///
        /// - Parameter failed: `Error` object containing a description of the error encountered when issuing the request
        @objc func authenticate(failed: Error)
    }
    

    An implementation of the above delegate may look something like this:

    File: AuthenticatedViewController.swift - Project File

    extension AuthenticatedViewController: AuthenticateDelegate {
    
        func authenticate(stateUpdated: AuthenticationState) {
            // device authentication state updated
    
            if stateUpdated == .completed {
                DispatchQueue.main.async { [self] in
                    // REQUEST ACCESS RIGHTS
                }
            }
        }
    
        func authenticate(failed: Error) {
            // device authentication failed
    
            // ERROR HANDLING
        }
    }
    

    Note that other operations which use the SDK, such as request access rights, can only be requested until after authentication has reached the .completed state. This and other possible authentication states can be seen below:

    File: AuthenticationState.swift - Allegion Mobile Access SDK Pod file

    import Foundation
    
    @objc public enum AuthenticationState: Int {
    
        /// Represents a state where the SDK is creating a Device ID, Account, and ConnectedAccount
        case enrolling
    
        /// Represents a state where the SDK is creating a ConnectedAccount
        case creatingConnectedAccount
    
        /// Represents a state where the SDK is selecting the matching ConnectedAccount given the AuthenticationRequest params
        case selectingConnectedAccount
    
        /// Represents a state where the SDK has completed authentication and another operation may be requested by the client
        case completed
    }
    

    Step 4 - Request Access Rights

    After initializing and authenticating, the access rights for the current user can be retrieved via the MobileAccessSDK's retrieveAccessRights method:

    File: AuthenticatedViewController.swift - Project File

        private var mobileAccessSDKInstance: MobileAccessSDK?
        var mobileAccessSDK: MobileAccessSDK {
            if mobileAccessSDKInstance == nil {
                mobileAccessSDKInstance = MobileAccessFactory().sdk()
            }
            return mobileAccessSDKInstance!
        }
    
        private func retrieveAccessRights() {
    
            presentationCoordinator?.updateActivityIndicatorMessage(LocalizationService.getMessage(.retrievingAccessRights), displayActivityIndicatorIfNotPresented: true)
    
            do {
                try mobileAccessSDK.retrieveAccessRights(completion: self, ignoreCache: true)
            } catch {
                logWriter.log("SDK retrieveAccessRights threw an error - error says:[\(error)]")
                presentationCoordinator?.presentRetrieveAccessRightsError(error: error)
            }
       }
    

    The first parameter passed to retrieveAccessRights is a RetrieveAccessRightsDelegate:

    File: RetrieveAccessRightsDelegate.swift - Allegion Mobile Access SDK Pod file

    /// Delegate for the "retrieve access rights" operation
    @objc public protocol RetrieveAccessRightsDelegate: AnyObject {
    
       /// success response handler for the retrieve access rights operation
        ///
       /// - Parameter succeeded: `RetrieveAccessRightsResponse` response model with access rights for currently selected connected account
        @objc func retrieveAccessRights(succeeded: RetrieveAccessRightsResponse)
    
        /// error response handler for the retrieve access rights operation
        ///
        /// - Parameter failed: `[Error]` collection of errors encountered while issuing and transition from the request
        @objc func retrieveAccessRights(failed: [Error])
    }
    

    Step 5 - Process Response

    The RetrieveAccessRightsResponse has an accessRights member of type ConnectedAccountAccessRights:

    File: RetrieveAccessRightsResponse.swift - Allegion Mobile Access SDK Pod file

    public class RetrieveAccessRightsResponse: NSObject {
        @objc public let accessRights: ConnectedAccountAccessRights
    }
    

    The ConnectedAccountAccessRights type maintains collections of both NFC and BLE access rights:

    File: ConnectedAccountAccessRights.swift - Allegion Mobile Access SDK Pod file

    public class ConnectedAccountAccessRights: NSObject {
        /// `[AccessRight]` a collection of rights with nfc credentials.
        @objc public let nfcCredentialRights: [AccessRight]
    
        /// `[AccessRight]` a collection of rights with ble credentials.
        @objc public let bleCredentialRights: [AccessRight]
    }
    

    Step 6 - NFC Payload Available

    An access right is determined to have an NFC payload available when the nfcCredentialRights property in the ConnectedAccountAccessRights instance is not empty. The ConnectedAccountAccessRights instance is contained in the RetrieveAccessRightsResponse instance returned through the RetrieveAccessRightsDelegate. The code for checking the payload type of the access rights appears in AuthenticatedViewController:

    File: AuthenticatedViewController.swift - Project File

    func retrieveAccessRights(succeeded: RetrieveAccessRightsResponse) {
      let nfcCredentials = succeeded.accessRights.nfcCredentialRights
      if !nfcCredentials.isEmpty {
          // NFC RIGHTS FOUND!
          DispatchQueue.main.async {
              self.preparePushProvisioning(nfcAccessRight: nfcCredentials[0])
          }
      } else {
        // HANDLE CASE OF NO NFC RIGHTS AVAILABLE
      }
    }
    

    Step 7 - Prepare Push Provisioning

    Once an NFC access right is identified, a call to the MobileAccessSDK's preparePushProvisioning method can be completed. This returns the required credential metadata to be passed to the iOS wallet to eventually provision the pass (credential). This call occurs in the NFCCredentialProvisioningService:

    File: NFCCredentialProvisioningService.swift - Project File

    do {
      try mobileAccessSDK.preparePushProvisioning(nfcAccessRight: nfcAccessRight, completion: self)
    } catch {
      // HANDLE ERRORS
    }
    

    The call to preparePushProvisioning requires a PreparePushProvisioningDelegate passed via the completion parameter:

    File: PreparePushProvisioningDelegate.swift - Allegion Mobile Access SDK Pod file

    @objc public protocol PreparePushProvisioningDelegate: AnyObject {
        /// Callback for a successful result of issuing a prepare push provisioning request
        ///
        /// - Parameter succeeded: `PreparePushProvisioningResponse` response for a prepare push provisioning request
        @objc func preparePushProvisioning(succeeded: PreparePushProvisioningResponse)
    
        /// Callback for an unsuccessful attempt of issuing a prepare push provisioning request
        ///
        /// - Parameter failed: `Error` object containing a description of the error encountered when issuing the request
        @objc func preparePushProvisioning(failed: [Error])
    }
    

    The PreparePushProvisioningResponse contains the pass (credential) metadata needed by the iOS wallet to initiate pass (credential) provisioning:

    File: PreparePushProvisioningResponse.swift - Allegion Mobile Access SDK Pod file

    public class PreparePushProvisioningResponse: NSObject {
        @objc public let provisioningCredentialIdentifier: String
        @objc public let cardConfigurationIdentifier: String
        @objc public let sharingInstanceIdentifier: String
        @objc public let referenceIdentifier: String
        @objc public let passThumbnailImage: CGImage
        @objc public let ownerDisplayName: String
       @objc public let localizedDescription: String
    }
    

    Step 8 - 9 - Pass Library Check

    The next step in the provisioning process now that it has been determined an NFC credential is available for the user is to determine if the pass library is available on the iOS device. This is determined via a class level boolean exposed on the Apple class PKPassLibrary. This code is within the NCFPassUtility class:

    File: NFCPassUtility.swift - Project File

    guard PKPassLibrary.isPassLibraryAvailable() else {
      // HANDLE PASS LIBRARY NOT AVAILABLE
      return
    }
    

    Step 10 - Retrieve Passes

    File: NFCPassUtility.swift - Project File

    let passLibrary = PKPassLibrary()
    self.passes = passLibrary.passes()
    
    ℹ️ Passes retrieved via the passes() method on a PKPassLibrary instance represent those passes residing in the wallet on the local device.

    The code to retrieve passes exists in the NFCPassUtility class within the Allegion Quick Start App.

    Step 11 - Retrieve Remote Passes

    Similarly, passes available to the application residing on remote devices - such as an Apple Watch, can be retrieved from a PKPassLibrary instance.

    File: NFCPassUtility.swift - Project File

    let passLibrary = PKPassLibrary()
    self.remoteSecureElementsPasses = passLibrary.remoteSecureElementPasses
    
    ℹ️ Passes retrieved via the remoteSecureElementPasses propertyon a PKPassLibrary instance represent those passes residing in remote devices (such as a paired Apple Watch) associated with the local device.

    The code to retrieve remote passes exists in the NFCPassUtility class within the Allegion Quick Start App.

    Step 12 - Local Pass Exists

    Determine if a local pass exists for the current user is accomplished by searching the (local) pass array matching the primaryAccountIdentifier on the pass to the PreparePushProvisioningResponse.referenceIdentifier retrieved in the PreparePushProvisioning response from the MobileAccessSDK's preparePushProvisioning call.

    ℹ️ The collection returned from the PKPassLibrary's passes() method is of type [PKPass]. The application is looking for a PKPaymentPass type, as the primaryAccountIdentifier is only available on PKPaymentPass instances. PKPaymentPass extends PKPass; as part of the search a cast need to be completed.

    File: NFCPassUtility.swift - Project File

    func localPassExists() -> Bool {
    
      return passes.contains { pkPass in
        guard let paymentPass = pkPass as? PKPaymentPass else {
          return false
        }
    
        return paymentPass.isRemotePass == false &&
          paymentPass.primaryAccountIdentifier == primaryAccountIdentifier
      }
    }
    

    The code to determine the existence of a local payment pass resides in the NFCPassUtility class within the Allegion Quick Start App.

    Step 13 - Local Pass Deactivated

    If a local pass is found, the passActivationState indicates if the pass is deactivated.

    File: NFCPassUtility.swift - Project File

    func isLocalPassInDeactivatedState() -> Bool {
    
            return passes.contains { pkPass in
                guard let paymentPass = pkPass as? PKPaymentPass else {
                    return false
                }
                return paymentPass.isRemotePass == false &&
                paymentPass.primaryAccountIdentifier == primaryAccountIdentifier &&
                paymentPass.passActivationState == .deactivated
            }
    }
    
    ℹ️ This function repeats the pass search covered previously when determining if a pass is disabled. This approach reduces coupling by not requiring a pass be search be completed prior to this operation being called.

    The code to determine if a local payment pass is disabled appears in the NFCPassUtility class within the Allegion Quick Start App.

    Step 14 - Local Pass Suspended

    If a local pass exists it may be in a suspended state which would preclude provisioning the pass (credential) again.

    File: NFCPassUtility.swift - Project File

    func isLocalPassInSuspendedState() -> Bool {
    
      return passes.contains { pkPass in
        guard let paymentPass = pkPass as? PKPaymentPass else {
            return false
        }
        return paymentPass.isRemotePass == false &&
          paymentPass.primaryAccountIdentifier == primaryAccountIdentifier &&
          paymentPass.passActivationState == .suspended
      }
    }
    
    ℹ️ This function repeats the pass search covered previously when determining if a pass is disabled. This approach reduces coupling by not requiring a pass be search be completed prior to this operation being called.

    The code to determine if a local payment pass is suspended appears in the NFCPassUtility class within the Allegion Quick Start app.

    Step 15 - Remote Pass Exists

    If a local pass and remote pass both exist, attempting to provision the pass (credential) again will result in the iOS wallet returning a generic error. Checking for the existence of a remote pass prior to provisioning will allow the application to proactively notify the user the pass (credential) is already provisioned. The code to determine if a remote pass exists appears in the NFCPassUtility class:

    File: NFCPassUtility.swift - Project File

    func remotePassExists() -> Bool {
    
      return remoteSecureElementsPasses.contains { remoteSecureElementsPass in
    
        return remoteSecureElementsPass.isRemotePass == true &&
          remoteSecureElementsPass.primaryAccountIdentifier == primaryAccountIdentifier
      }
    }
    
    ℹ️ As with checking for the local pass existence, the primaryAccountIdentifier of the remote pass is used as a filter to identify the pass for the current user as passes for other users which are visible to this application may be contained in the remoteSecureElementsPasses collection.

    Step 16 - Create Sharable Pass Metadata

    If provisioning is good to move forward, the next step in the process is to create a PKShareablePassMetadata instance. This is completed in the NFCCredentialProvisioningService:

    File: NFCCredentialProvisioningService.swift - Project File

    guard let shareablePassMetaData = PKShareablePassMetadata(provisioningCredentialIdentifier: nfcCredentialProvisioningElements.provisioningCredentialIdentifier,
                                                              cardConfigurationIdentifier: nfcCredentialProvisioningElements.cardConfigurationIdentifier,
                                                              sharingInstanceIdentifier: nfcCredentialProvisioningElements.sharingInstanceIdentifier,
                                                              passThumbnailImage: nfcCredentialProvisioningElements.passThumbnailImage,
                                                              ownerDisplayName: nfcCredentialProvisioningElements.ownerDisplayName,
                                                              localizedDescription: nfcCredentialProvisioningElements.localizedDescription) else {
      // HANDLE ERRORS
    }
    

    The NFCCredentialProvisioningElements instance referenced in the above code is of type NFCCredentialProvisioningElements. The definition appears as:

    File: NFCCredentialProvisioningElements.swift - Project File

    struct NFCCredentialProvisioningElements {
        let provisioningCredentialIdentifier: String
        let cardConfigurationIdentifier: String
        let sharingInstanceIdentifier: String
        let passThumbnailImage: CGImage
        let ownerDisplayName: String
        let localizedDescription: String
    }
    

    The Allegion Quick Start App defines an extension on the MobileAccessSDK's PreparePushProvisioningResponse to create an NFCCredentialProvisioningElements:

    File: PreparePushProvisioningResponse+Transforms.swift - Project File

    extension PreparePushProvisioningResponse {
        func toNFCCredentialProvisioningElements() -> NFCCredentialProvisioningElements {
            return NFCCredentialProvisioningElements(provisioningCredentialIdentifier: self.provisioningCredentialIdentifier,
                                                     cardConfigurationIdentifier: self.cardConfigurationIdentifier,
                                                    sharingInstanceIdentifier: self.sharingInstanceIdentifier,
                                                     passThumbnailImage: self.passThumbnailImage,
                                                     ownerDisplayName: self.ownerDisplayName,
                                                     localizedDescription: self.localizedDescription)
        }
    }
    

    Step 17 - Create Sharable Pass Config

    The PKShareablePassMetadata is then used to create the PKAddShareablePassConfiguration. This code appears in the NFCCredentialProvisioningService:

    File: NFCCredentialProvisioningService.swift - Project File

    PKAddShareablePassConfiguration.forPassMetaData([passMetaData],
                                                            provisioningPolicyIdentifier: NFCCredentialProvisioningElementsConstants.provisioningPolicyIdentifier,
                                                            action: PKAddShareablePassConfigurationPrimaryAction.add,
                                                            completion: {(shareablePassConfiguration, error) in
      // PROCESS RESPONSE -> IMPORTANT TO CHECK THE error INSTANCE!!
    }
    

    The code sample above calls out checking the error argument passed to the completion handler. This error is an instance of NSError. When the value of the domain property is PKAddSecureElementPassErrorMapperDomain, the error code maps to the (enum) type PKAddSecureElementPassError.

    ⚠️ PKAddSecureElementPassError.pkasepeDeviceNotSupportedRecoverySuggestion indicates either the device does not have a passcode set or the device does not have an iCould account configured. An iCloud account and passcode are required to provision a secure pass (credential). The Allegion Quick Start App handles this conversion with user-friendly messaging in the PKAddSecureElementPassErrorMapper class. The recovery suggestion provided for the error code PKAddSecureElementPassError is "Please verify iCloud and Passcode are setup on current device.".

    Step 18 - Can Provision

    At this point, it is necessary to confirm with the PKAddSecureElementPassViewController that the configuration can be provisioned. The Apple class PKAddSecureElementPassViewController provides a class level method, canAddSecureElementPass(), that validates the PKAddShareablePassConfiguration can be used for provisioning:

    File: NFCCredentialProvisioningService.swift - Project File

    let canProvision = PKAddSecureElementPassViewController.canAddSecureElementPass(configuration: unwrappedShareablePassConfiguration)
    

    This code appears in the NFCCredentialProvisioningService.

    Step 19 - Create Add Pass View Controller

    The final step in preparing for provisioning is the create a PKAddSecureElementPassViewController that can be presented to the user to initiate adding the pass (credential) to then wallet. Creating is straight forward and appears in NFCCredentialProvisioningService.

    File: NFCCredentialProvisioningService.swift - Project File

    guard let addSecureElementPassViewController = PKAddSecureElementPassViewController(configuration: shareablePassConfiguration,
                                                                                        delegate: self.addSecureElementPassViewControllerDelegate) else {
      // HANDLE ERROR
    }
    

    Step 20 - Add to Wallet

    With a PKAddSecureElementPassViewController instance available, an add to wallet button (an instance of PKAddPassButton) can be displayed. When tapped, the button can present the PKAddSecureElementPassViewController instance which takes over the UI experience for adding the pass (credential) to the wallet.

    File: AuthenticatedViewController.swift - Project File

    @objc func onAddToWalletButton(_ sender: Any) {
    
      if let addToWalletVC = addToWalletVC {
        present(addToWalletVC, animated: true)
      }
    }
    

    The code to present the PKAddSecureElementPassViewController (represented by the class level addToWalletVC property) appears in AuthenticatedViewController

    NFCCredentialProvisioningService class

    The Allegion Quick Start App application provides the NFCCredentialProvisioningService class as well as supporting utility classes to make integrating with the iOS wallet app as well as the Mobile Access SDK simpler. It was designed with a goal of compartmentalizing as much of the wallet integration as possible allowing our partners to jump start their integrations. Using the NFCCredentialProvisioningService will requiring importing Allegion concepts around error handling - PersonaManagerEnrollmentError, utility classes such as NFCPassUtility and our logging implementation, Ecrivain.

    The class encapsulates Steps 7-20 in the preceding diagram. The createAddSecureElementPassViewController method kicks the process off:

    File: NFCCredentialProvisioningService.swift - Project File

    func createAddSecureElementPassViewController(
            nfcAccessRight: AccessRight,
            addSecureElementPassViewControllerDelegate: PKAddSecureElementPassViewControllerDelegate? ,
            delegate: CreateAddSecureElementPassViewControllerDelegate?) throws
    

    The method requires a previously retrieved Access Right which has an NFC payload. Also required is the Apple defined PKAddSecureElementPassViewControllerDelegate which will be assigned when the PKAddSecureElementPassViewController is successfully created.

    Once created, the PKAddSecureElementPassViewController instance is returned via the CreateAddSecureElementPassViewControllerDelegate which appears as:

    File: CreateAddSecureElementPassViewControllerDelegate.swift - Project File

    protocol CreateAddSecureElementPassViewControllerDelegate: AnyObject {
        func createAddSecureElementPassViewController(succeeded: PKAddSecureElementPassViewController, badgeImprintData: BadgeImprintData)
        func createAddSecureElementPassViewController(failed: Error)
    }
    

    The Error returned will be of type PersonaManagerEnrollmentError:

    File: PersonaManagerEnrollmentError.swift - Project File

    class PersonaManagerEnrollmentError: LocalizedError, Equatable, Hashable, CustomDebugStringConvertible {
    
        static let PersonaManagerEnrollmentDomain = "com.allegion.PersonaManagerEnrollment"
    
        let domain: String
        let errorCode: Int
        public internal (set) var source: PersonaManagerEnrollmentError?
        public internal (set) var errorDescription: String?
        public internal (set) var failureReason: String?
        public internal (set) var recoverySuggestion: String?
        public internal (set) var helpAnchor: String?
    }