SwiftUI-MSALSample

I could not find a good walkthrough on how to implement MSAL with SwiftUI, everything is written for UIKit unfortunately and even then it wasn’t clear IMO.

I started following the walkthrough Microsoft Authentication Library for iOS and macOS on github and then pieced together the rest using Stack Overflow.

There is still some work to be done. Please feel free to open a PR for any code improvements or adding features!

Getting Started the Short Version.

  1. Download the project.
  2. Follow the instructions listed on the AzureAD github to register your app within the Azure Portal.
  3. You will also want to follow the steps listed on adding MSAL to your project listed here.
  4. Updated clientID and redirectUri in MSALLogin.swiftMSALPublicClientApplicationConfig(clientId: clientID, redirectUri: redirectUri, authority: authority) with the information you got from when you registered your app in the azure portal.

Getting Started:

Installation

  1. I followed the instructions listed on the AzureAD github to register your app within the Azure Portal.
  2. You will also want to follow the steps listed on adding MSAL to your project listed here.

After step 2 is a bit where I got lost so I’m hoping this sample project will help.

Using This Sample Project

  1. Majority of the code is MSALLogin.swift and the big chuck of the code below is how you will login with MSAL.
  2. You’ll want to replace clientID and redirectUri in MSALPublicClientApplicationConfig(clientId: clientID, redirectUri: redirectUri, authority: authority) with the information you got from when you registered your app in the azure portal. (Note: I have this info stored in a file that I did not upload.)
  3. Depending on your project you’ll may also need to update your scopes in let interactiveParameters = MSALInteractiveTokenParameters(scopes: ["user.read"], webviewParameters: webViewParameters)

        do {
            let authority = try MSALB2CAuthority(url: URL(string: "https://login.microsoftonline.com/common")!)
            let pcaConfig = MSALPublicClientApplicationConfig(clientId: clientID, redirectUri: redirectUri, authority: authority)
            let application = try MSALPublicClientApplication(configuration: pcaConfig)
            let webViewParameters = MSALWebviewParameters(authPresentationViewController: self)
            let interactiveParameters = MSALInteractiveTokenParameters(scopes: ["user.read"], webviewParameters: webViewParameters)
            application.acquireToken(with: interactiveParameters) { (result, error) in

                guard let result = result else {
                    print("error \(error?.localizedDescription)")
                    return
                }
                if let account = result.account.username {
                    print("logging \(account)")
//                    accountName = account
                    msalModel.accountName = account
                    msalModel.scopes = result.scopes
                    print("logging \(result.account.description)")
                    UIApplication.shared.windows.first {
                        $0.isKeyWindow
                    }!.rootViewController = UIHostingController(rootView: ContentView())
                }
            }
        } catch {
            print("\(#function) logging error \(error)")
        }
  1. The rest of the code within MSALLogin.swift are methods and classes so UIKit and SwiftUI can work together.

Getting this to work with SwiftUI

  1. In ContentView.swift I declated a @StateObject linking back to MSALScreenViewModel() that I created in MSALLogin.swift.
  2. Within ContentView.swift I created a button that calls msalModel.loadMSALScreen() and then added the UIKit view MSALScreenView_UI(viewModel: msalModel). Just a heads up, but depending on how you implament this you will need to adjust the frame.

Challenges and Learning

  1. I’m not sure how I can dump result.account.username into the @Published var to use in other views. This will be beneficial for tokens to make other calls within MSFT products.
  2. I have not explored adding a sign out option.
  3. I’m unsure of how long the token would be for without having a silent refresh implemented.
  4. The biggest thing I learned is that Microsoft is not quite ready for SwiftUI and their documentation is lacking IMO for developers at least compared to Google Firebase. I do hope this changes in time.

Pictures of Repro

Video of Repro

Simulator.Screen.Recording.-.iPhone.13.-.2022-01-10.at.21.36.37.gifv.mp4


GitHub

View Github