Włączanie uwierzytelniania we własnej aplikacji Swift dla systemu iOS przy użyciu usługi Azure AD B2C

W tym artykule przedstawiono sposób dodawania uwierzytelniania usługi Azure Active Directory B2C (Azure AD B2C) do własnej aplikacji mobilnej Swift dla systemu iOS. Dowiedz się, jak zintegrować aplikację Swift systemu iOS z biblioteką Microsoft Authentication Library (MSAL) dla systemu iOS.

Skorzystaj z tego artykułu z tematem Konfigurowanie uwierzytelniania w przykładowej aplikacji Swift dla systemu iOS, zastępując przykładową aplikację Swift dla systemu iOS własną aplikacją Swift dla systemu iOS. Po wykonaniu instrukcji opisanych w tym artykule aplikacja zaakceptuje logowania za pośrednictwem usługi Azure AD B2C.

Wymagania wstępne

Zapoznaj się z wymaganiami wstępnymi i instrukcjami integracji w temacie Konfigurowanie uwierzytelniania w przykładowej aplikacji Swift dla systemu iOS przy użyciu usługi Azure AD B2C.

Tworzenie projektu aplikacji Swift dla systemu iOS

Jeśli nie masz jeszcze aplikacji Swift dla systemu iOS, skonfiguruj nowy projekt, wykonując następujące czynności:

  1. Otwórz program Xcode, a następnie wybierz pozycję Plik>nowy>projekt.
  2. W przypadku aplikacji systemu iOS wybierz pozycjęAplikacjadla systemu iOS>, a następnie wybierz pozycję Dalej.
  3. W obszarze Wybierz opcje nowego projektu podaj następujące elementy:
    1. Nazwa produktu, na przykład MSALiOS.
    2. Identyfikator organizacji, taki jak contoso.com.
    3. W obszarze Interfejs wybierz pozycję Scenorys.
    4. W cyklu życia wybierz pozycję Delegat aplikacji UIKit.
    5. W polu Język wybierz pozycję Swift.
  4. Wybierz opcję Dalej.
  5. Wybierz folder, w którym chcesz utworzyć aplikację, a następnie wybierz pozycję Utwórz.

Krok 1. Instalowanie biblioteki MSAL

  1. Zainstaluj bibliotekę MSAL za pomocą narzędzia CocoaPods . W tym samym folderze co plik xcodeproj projektu, jeśli plik podfile nie istnieje, utwórz pusty plik i nadaj mu nazwę podfile. Dodaj następujący kod do pliku podfile :

    use_frameworks!
    
    target '<your-target-here>' do
       pod 'MSAL'
    end
    
  2. Zastąp <your-target-here> ciąg nazwą projektu (na przykład MSALiOS). Aby uzyskać więcej informacji, zobacz Dokumentacja składni podfile.

  3. W oknie terminalu przejdź do folderu zawierającego plik podfile , a następnie uruchom instalację zasobnika , aby zainstalować bibliotekę MSAL.

  4. Po uruchomieniu polecenia zostanie utworzony plik project name.xcworkspace>.<pod install Aby ponownie załadować projekt w programie Xcode, zamknij program Xcode, a następnie otwórz <plik project name.xcworkspace>.

Krok 2. Ustawianie schematu adresu URL aplikacji

Podczas uwierzytelniania użytkowników Azure AD B2C wysyła kod autoryzacji do aplikacji przy użyciu identyfikatora URI przekierowania skonfigurowanego w rejestracji aplikacji Azure AD B2C.

Domyślny format identyfikatora URI przekierowania biblioteki MSAL to msauth.[Your_Bundle_Id]://auth. Przykładem może być msauth.com.microsoft.identitysample.MSALiOS://auth, gdzie msauth.com.microsoft.identitysample.MSALiOS jest schemat adresu URL.

W tym kroku zarejestruj schemat adresów URL przy użyciu tablicy CFBundleURLSchemes . Aplikacja nasłuchuje schematu adresów URL dla wywołania zwrotnego z Azure AD B2C.

W programie Xcode otwórz plik Info.plist jako plik kodu źródłowego. <dict> W sekcji dodaj następujący fragment kodu XML:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>msauth.com.microsoft.identitysample.MSALiOS</string>
        </array>
    </dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>msauthv2</string>
    <string>msauthv3</string>
</array>

Krok 3. Dodawanie kodu uwierzytelniania

Przykładowy kod składa się UIViewController z klasy. Klasa:

  • Definiuje strukturę interfejsu użytkownika.
  • Zawiera informacje o dostawcy tożsamości usługi Azure AD B2C. Aplikacja używa tych informacji do ustanowienia relacji zaufania z Azure AD B2C.
  • Zawiera kod uwierzytelniania umożliwiający uwierzytelnianie użytkowników, uzyskiwanie tokenów i weryfikowanie ich.

Wybierz miejsce, w UIViewController którym użytkownicy się uwierzytelniają. W pliku UIViewControllerscal kod z kodem podanym w usłudze GitHub.

Krok 4. Konfigurowanie aplikacji Swift dla systemu iOS

Po dodaniu kodu uwierzytelniania skonfiguruj aplikację Swift dla systemu iOS przy użyciu ustawień usługi Azure AD B2C. Azure AD ustawienia dostawcy tożsamości B2C są konfigurowane w UIViewController klasie wybranej w poprzedniej sekcji.

Aby dowiedzieć się, jak skonfigurować aplikację Swift dla systemu iOS, zobacz Konfigurowanie uwierzytelniania w przykładowej aplikacji Swift dla systemu iOS przy użyciu usługi Azure AD B2C.

Krok 5. Uruchamianie i testowanie aplikacji mobilnej

  1. Skompiluj i uruchom projekt za pomocą symulatora połączonego urządzenia z systemem iOS.
  2. Wybierz pozycję Zaloguj się, a następnie zarejestruj się lub zaloguj się przy użyciu konta lokalnego lub społecznościowego usługi Azure AD B2C.
  3. Po pomyślnym uwierzytelnieniu na pasku nawigacyjnym zobaczysz nazwę wyświetlaną.

Krok 6. Dostosowywanie bloków konstrukcyjnych kodu

W tej sekcji opisano bloki konstrukcyjne kodu, które umożliwiają uwierzytelnianie aplikacji Swift dla systemu iOS. Zawiera listę metod UIViewController i omówiono sposób dostosowywania kodu.

Krok 6.1. Utworzenie wystąpienia publicznej aplikacji klienckiej

Publiczne aplikacje klienckie nie są zaufane, aby bezpiecznie przechowywać wpisy tajne aplikacji i nie mają wpisów tajnych klienta. W pliku viewDidLoad utwórz wystąpienie biblioteki MSAL przy użyciu publicznego obiektu aplikacji klienckiej.

Poniższy fragment kodu swift pokazuje, jak zainicjować bibliotekę MSALPublicClientApplicationConfig MSAL za pomocą obiektu konfiguracji.

Obiekt konfiguracji zawiera informacje o środowisku Azure AD B2C. Na przykład udostępnia identyfikator klienta, identyfikator URI przekierowania i urząd do tworzenia żądań uwierzytelniania w celu Azure AD B2C. Aby uzyskać informacje o obiekcie konfiguracji, zobacz Konfigurowanie przykładowej aplikacji mobilnej.

do {

    let signinPolicyAuthority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)
    let editProfileAuthority = try self.getAuthority(forPolicy: self.kEditProfilePolicy)
    
    let pcaConfig = MSALPublicClientApplicationConfig(clientId: kClientID, redirectUri: kRedirectUri, authority: signinPolicyAuthority)
    pcaConfig.knownAuthorities = [signinPolicyAuthority, editProfileAuthority]
    
    self.applicationContext = try MSALPublicClientApplication(configuration: pcaConfig)
    self.initWebViewParams()
    
    } catch {
        self.updateLoggingText(text: "Unable to create application \(error)")
    }

Metoda initWebViewParams konfiguruje środowisko uwierzytelniania interakcyjnego .

Poniższy fragment kodu swift inicjuje webViewParameters składową klasy za pomocą widoku internetowego systemu. Aby uzyskać więcej informacji, zobacz Dostosowywanie przeglądarek i elementów WebView dla systemu iOS/macOS.

func initWebViewParams() {
    self.webViewParameters = MSALWebviewParameters(authPresentationViewController: self)
    self.webViewParameters?.webviewType = .default
}

Krok 6.2. Uruchamianie interakcyjnego żądania autoryzacji

Żądanie autoryzacji interakcyjnej to przepływ, w którym użytkownicy są monitowani o zarejestrowanie się lub zalogowanie przy użyciu systemowego widoku internetowego. Gdy użytkownicy wybierają przycisk Zaloguj się, wywoływana authorizationButton jest metoda.

Metoda authorizationButton przygotowuje MSALInteractiveTokenParameters obiekt z odpowiednimi danymi dotyczącymi żądania autoryzacji. Metoda acquireToken używa metody MSALInteractiveTokenParameters do uwierzytelniania użytkowników za pośrednictwem systemowego widoku internetowego.

Poniższy fragment kodu pokazuje, jak uruchomić interakcyjne żądanie autoryzacji:

let parameters = MSALInteractiveTokenParameters(scopes: kScopes, webviewParameters: self.webViewParameters!)
parameters.promptType = .selectAccount
parameters.authority = authority

applicationContext.acquireToken(with: parameters) { (result, error) in

// On error code    
guard let result = result else {
    self.updateLoggingText(text: "Could not acquire token: \(error ?? "No error information" as! Error)")
    return
}

// On success code
self.accessToken = result.accessToken
self.updateLoggingText(text: "Access token is \(self.accessToken ?? "Empty")")
}

Po pomyślnym lub nieudanym zakończeniu przepływu autoryzacji przez użytkowników wynik zostanie zwrócony do zamknięciaacquireToken metody.

Metoda acquireToken zwraca result obiekty i error . Użyj tego zamknięcia, aby:

  • Zaktualizuj interfejs użytkownika aplikacji mobilnej przy użyciu informacji po zakończeniu uwierzytelniania.
  • Wywoływanie usługi internetowego interfejsu API przy użyciu tokenu dostępu.
  • Obsługa błędów uwierzytelniania (na przykład gdy użytkownik anuluje przepływ logowania).

Krok 6.3. Wywoływanie internetowego interfejsu API

Aby wywołać internetowy interfejs API autoryzacji opartej na tokenach, aplikacja potrzebuje prawidłowego tokenu dostępu. Aplikacja wykonuje następujące czynności:

  1. Uzyskuje token dostępu z wymaganymi uprawnieniami (zakresami) dla internetowego punktu końcowego interfejsu API.
  2. Przekazuje token dostępu jako token elementu nośnego w nagłówku autoryzacji żądania HTTP przy użyciu następującego formatu:
Authorization: Bearer <access-token>

Gdy użytkownicy uwierzytelniają się interaktywnie, aplikacja otrzyma token dostępu w acquireToken zamknięciu. W przypadku kolejnych wywołań internetowego interfejsu API użyj metody uzyskiwania tokenu dyskretnego (acquireTokenSilent), zgodnie z opisem w tej sekcji.

Metoda acquireTokenSilent wykonuje następujące akcje:

  1. Próbuje pobrać token dostępu z żądanymi zakresami z pamięci podręcznej tokenu. Jeśli token jest obecny i nie wygasł, token zostanie zwrócony.
  2. Jeśli token nie znajduje się w pamięci podręcznej tokenu lub wygasł, biblioteka MSAL próbuje użyć tokenu odświeżania w celu uzyskania nowego tokenu dostępu.
  3. Jeśli token odświeżania nie istnieje lub wygasł, zwracany jest wyjątek. W takim przypadku należy monitować użytkownika o zalogowanie się interaktywnie.

Poniższy fragment kodu pokazuje, jak uzyskać token dostępu:

do {

// Get the authority using the sign-in or sign-up user flow
let authority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)

// Get the current account from the application context
guard let thisAccount = try self.getAccountByPolicy(withAccounts: applicationContext.allAccounts(), policy: kSignupOrSigninPolicy) else {
    self.updateLoggingText(text: "There is no account available!")
    return
}

// Configure the acquire token silent parameters
let parameters = MSALSilentTokenParameters(scopes: kScopes, account:thisAccount)
parameters.authority = authority
parameters.loginHint = "username"

// Acquire token silent
self.applicationContext.acquireTokenSilent(with: parameters) { (result, error) in
    if let error = error {
        
        let nsError = error as NSError
        
        // interactionRequired means we need to ask the user to sign in. This usually happens
        // when the user's Refresh Token is expired or if the user has changed their password
        // among other possible reasons.
        
        if (nsError.domain == MSALErrorDomain) {
            
            if (nsError.code == MSALError.interactionRequired.rawValue) {
                
                // Start an interactive authorization code
                // Notice we supply the account here. This ensures we acquire token for the same account
                // as we originally authenticated.
                
                ...
            }
        }
        
        self.updateLoggingText(text: "Could not acquire token: \(error)")
        return
    }
    
    guard let result = result else {
        
        self.updateLoggingText(text: "Could not acquire token: No result returned")
        return
    }
    
    // On success, set the access token to the accessToken class member. 
    // The callGraphAPI method uses the access token to call a web API  
    self.accessToken = result.accessToken
    ...
}
} catch {
self.updateLoggingText(text: "Unable to construct parameters before calling acquire token \(error)")
}

Metoda callGraphAPI pobiera token dostępu i wywołuje internetowy interfejs API, jak pokazano poniżej:

@objc func callGraphAPI(_ sender: UIButton) {
    guard let accessToken = self.accessToken else {
        self.updateLoggingText(text: "Operation failed because could not find an access token!")
        return
    }
    
    let sessionConfig = URLSessionConfiguration.default
    sessionConfig.timeoutIntervalForRequest = 30
    let url = URL(string: self.kGraphURI)
    var request = URLRequest(url: url!)
    request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
    let urlSession = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: OperationQueue.main)
    
    self.updateLoggingText(text: "Calling the API....")
    
    urlSession.dataTask(with: request) { data, response, error in
        guard let validData = data else {
            self.updateLoggingText(text: "Could not call API: \(error ?? "No error information" as! Error)")
            return
        }
        
        let result = try? JSONSerialization.jsonObject(with: validData, options: [])
        
        guard let validResult = result as? [String: Any] else {
            self.updateLoggingText(text: "Nothing returned from API")
            return
        }
        
        self.updateLoggingText(text: "API response: \(validResult.debugDescription)")
        }.resume()
}

Krok 6.4. Wylogowanie użytkowników

Wylogowywanie przy użyciu biblioteki MSAL usuwa wszystkie znane informacje o użytkownikach z aplikacji. Użyj metody wylogowania, aby wylogować użytkowników i zaktualizować interfejs użytkownika. Możesz na przykład ukryć chronione elementy interfejsu użytkownika, ukryć przycisk wylogowania lub wyświetlić przycisk logowania.

Poniższy fragment kodu pokazuje, jak wylogować użytkowników:

@objc func signoutButton(_ sender: UIButton) {
do {
    
    
    let thisAccount = try self.getAccountByPolicy(withAccounts: applicationContext.allAccounts(), policy: kSignupOrSigninPolicy)
    
    if let accountToRemove = thisAccount {
        try applicationContext.remove(accountToRemove)
    } else {
        self.updateLoggingText(text: "There is no account to signing out!")
    }
    
    ...
    
} catch  {
    self.updateLoggingText(text: "Received error signing out: \(error)")
}
}

Następne kroki

Instrukcje: