Kurz: Přihlášení uživatelů a volání Microsoft Graphu z aplikace pro iOS nebo macOS
V tomto kurzu vytvoříte aplikaci pro iOS nebo macOS, která se integruje s platformou Microsoft Identity Platform pro podepisování uživatelů a získání přístupového tokenu pro volání rozhraní Microsoft Graph API.
Po dokončení kurzu vaše aplikace přijímá přihlášení k osobním účtům Microsoft (včetně outlook.com, live.com a dalších) a pracovních nebo školních účtů z libovolné společnosti nebo organizace, která používá ID Microsoft Entra. Tento kurz platí pro aplikace pro iOS i macOS. Některé kroky se mezi těmito dvěma platformami liší.
V tomto kurzu:
- Vytvoření projektu aplikace pro iOS nebo macOS v Xcode
- Registrace aplikace v Centru pro správu Microsoft Entra
- Přidání kódu pro podporu přihlášení a odhlášení uživatele
- Přidání kódu pro volání rozhraní Microsoft Graph API
- Otestování aplikace
Požadavky
Jak aplikace tutorial funguje
Aplikace v tomto kurzu se může přihlásit uživatele a získat data z Microsoft Graphu jejich jménem. K datům se přistupuje prostřednictvím chráněného rozhraní API (v tomto případě rozhraní Microsoft Graph API), které vyžaduje autorizaci a je chráněno platformou Microsoft Identity Platform.
Konkrétně:
- Vaše aplikace se přihlásí uživatele prostřednictvím prohlížeče nebo Microsoft Authenticatoru.
- Koncový uživatel přijme oprávnění, která vaše aplikace požadovala.
- Vaše aplikace je vystavena přístupový token pro rozhraní Microsoft Graph API.
- Přístupový token je součástí požadavku HTTP na webové rozhraní API.
- Zpracování odpovědi Microsoft Graphu
Tato ukázka používá knihovnu MSAL (Microsoft Authentication Library) k implementaci ověřování. MSAL automaticky prodlouží tokeny, zajistí jednotné přihlašování (SSO) mezi jinými aplikacemi na zařízení a spravuje účty.
Pokud si chcete stáhnout dokončenou verzi aplikace, kterou vytvoříte v tomto kurzu, najdete obě verze na GitHubu:
Vytvoření nového projektu
- Otevřete Xcode a vyberte Vytvořit nový projekt Xcode.
- U aplikací pro iOS vyberte aplikaci pro jedno zobrazení pro iOS>a vyberte Další.
- V případě aplikací pro macOS vyberte macOS>Cocoa App a vyberte Další.
- Zadejte název produktu.
- Nastavte jazyk na Swift a vyberte Další.
- Vyberte složku, do které chcete aplikaci vytvořit, a vyberte Vytvořit.
Registrace aplikace
Tip
Postup v tomto článku se může mírně lišit v závislosti na portálu, od který začínáte.
- Přihlaste se do Centra pro správu Microsoft Entra jako alespoň vývojář aplikací.
- Pokud máte přístup k více tenantům, pomocí ikony Nastavení v horní nabídce přepněte na tenanta, ve kterém chcete aplikaci zaregistrovat z nabídky Adresáře a předplatná.
- Přejděte k aplikacím> identit>Registrace aplikací.
- Vyberte Nová registrace.
- Zadejte název aplikace. Uživatelé vaší aplikace můžou vidět tento název a později ho můžete změnit.
- V části Podporované typy účtů vyberte účty v libovolném organizačním adresáři (jakýkoli adresář Microsoft Entra – Víceklient) a osobní účty Microsoft (např. Skype, Xbox).
- Vyberte Zaregistrovat.
- V části Spravovat vyberte Možnost Přidat ověřování>pro platformu>iOS/macOS.
- Zadejte ID sady prostředků projektu. Pokud jste si stáhli ukázku kódu, ID sady je
com.microsoft.identitysample.MSALiOS
. Pokud vytváříte vlastní projekt, vyberte projekt v Xcode a otevřete kartu Obecné . Identifikátor sady se zobrazí v části Identita . - Vyberte Konfigurovat a uložte konfiguraci MSAL, která se zobrazí na stránce konfigurace MSAL, abyste ji mohli zadat při pozdější konfiguraci aplikace.
- Vyberte Hotovo.
Přidání knihovny MSAL
Zvolte jeden z následujících způsobů instalace knihovny MSAL ve vaší aplikaci:
CocoaPods
Pokud používáte CocoaPods, nainstalujte nejprve
MSAL
prázdný soubor s názvem podfile ve stejné složce jako soubor .xcodeproj vašeho projektu. Do souboru podfile přidejte následující položky:use_frameworks! target '<your-target-here>' do pod 'MSAL' end
Nahraďte
<your-target-here>
názvem projektu.V okně terminálu přejděte do složky, která obsahuje soubor podfile , který jste vytvořili, a spusťte
pod install
instalaci knihovny MSAL.Zavřete Xcode a otevřete
<your project name>.xcworkspace
ho, aby se projekt znovu načítá v Xcode.
Kartágo
Pokud používáte Carthage, nainstalujte MSAL
ho přidáním do souboru Cartfile:
github "AzureAD/microsoft-authentication-library-for-objc" "master"
V okně terminálu ve stejném adresáři jako aktualizovaný cartfile spusťte následující příkaz, aby Carthage aktualizoval závislosti v projektu.
Ios:
carthage update --platform iOS
macOS:
carthage update --platform macOS
Ručně
Můžete také použít Git Submodule nebo si prohlédnout nejnovější verzi, která se má použít jako architektura ve vaší aplikaci.
Přidání registrace aplikace
Dále přidáme registraci vaší aplikace do kódu.
Nejprve přidejte následující příkaz importu do horní části souboru ViewController.swift a buď AppDelegate.swift , nebo SceneDelegate.swift:
import MSAL
Dále přidejte následující kód do ViewController.swift před:viewDidLoad()
// Update the below to your client ID. The below is for running the demo only
let kClientID = "Your_Application_Id_Here"
let kGraphEndpoint = "https://graph.microsoft.com/" // the Microsoft Graph endpoint
let kAuthority = "https://login.microsoftonline.com/common" // this authority allows a personal Microsoft account and a work or school account in any organization's Azure AD tenant to sign in
let kScopes: [String] = ["user.read"] // request permission to read the profile of the signed-in user
var accessToken = String()
var applicationContext : MSALPublicClientApplication?
var webViewParameters : MSALWebviewParameters?
var currentAccount: MSALAccount?
Jedinou hodnotou, kterou upravíte, je hodnota přiřazená kClientID
jako ID vaší aplikace. Tato hodnota je součástí konfiguračních dat MSAL, která jste uložili během kroku na začátku tohoto kurzu pro registraci aplikace.
Konfigurace nastavení projektu Xcode
Přidejte novou skupinu řetězce klíčů do možností podepisování a funkcí projektu. Skupina řetězce klíčů by měla být com.microsoft.adalcache
v iOSu a com.microsoft.identity.universalstorage
v macOS.
Pouze pro iOS nakonfigurujte schémata adres URL.
V tomto kroku se zaregistrujete CFBundleURLSchemes
, aby se uživatel po přihlášení mohl přesměrovat zpět do aplikace. Mimochodem, LSApplicationQueriesSchemes
umožňuje vaší aplikaci používat Microsoft Authenticator.
V Xcode otevřete Soubor Info.plist jako soubor zdrojového <dict>
kódu a do části přidejte následující kód. Nahraďte [BUNDLE_ID]
hodnotou, kterou jste použili dříve. Pokud jste kód stáhli, identifikátor sady je com.microsoft.identitysample.MSALiOS
. Pokud vytváříte vlastní projekt, vyberte projekt v Xcode a otevřete kartu Obecné . Identifikátor sady se zobrazí v části Identita .
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>msauth.[BUNDLE_ID]</string>
</array>
</dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>msauthv2</string>
<string>msauthv3</string>
</array>
Pouze pro macOS nakonfigurujte Sandbox aplikace.
- Přechod na kartu>Možnosti nastavení >projektu Xcode – Sandbox aplikace
- Zaškrtněte políčko Odchozí připojení (klient).
Vytvoření uživatelského rozhraní aplikace
Teď vytvořte uživatelské rozhraní, které obsahuje tlačítko pro volání rozhraní Microsoft Graph API, jiného pro odhlášení a textové zobrazení, které zobrazí nějaký výstup přidáním následujícího kódu do ViewController
třídy:
Uživatelské rozhraní iOS
var loggingText: UITextView!
var signOutButton: UIButton!
var callGraphButton: UIButton!
var usernameLabel: UILabel!
func initUI() {
usernameLabel = UILabel()
usernameLabel.translatesAutoresizingMaskIntoConstraints = false
usernameLabel.text = ""
usernameLabel.textColor = .darkGray
usernameLabel.textAlignment = .right
self.view.addSubview(usernameLabel)
usernameLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 50.0).isActive = true
usernameLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -10.0).isActive = true
usernameLabel.widthAnchor.constraint(equalToConstant: 300.0).isActive = true
usernameLabel.heightAnchor.constraint(equalToConstant: 50.0).isActive = true
// Add call Graph button
callGraphButton = UIButton()
callGraphButton.translatesAutoresizingMaskIntoConstraints = false
callGraphButton.setTitle("Call Microsoft Graph API", for: .normal)
callGraphButton.setTitleColor(.blue, for: .normal)
callGraphButton.addTarget(self, action: #selector(callGraphAPI(_:)), for: .touchUpInside)
self.view.addSubview(callGraphButton)
callGraphButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
callGraphButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 120.0).isActive = true
callGraphButton.widthAnchor.constraint(equalToConstant: 300.0).isActive = true
callGraphButton.heightAnchor.constraint(equalToConstant: 50.0).isActive = true
// Add sign out button
signOutButton = UIButton()
signOutButton.translatesAutoresizingMaskIntoConstraints = false
signOutButton.setTitle("Sign Out", for: .normal)
signOutButton.setTitleColor(.blue, for: .normal)
signOutButton.setTitleColor(.gray, for: .disabled)
signOutButton.addTarget(self, action: #selector(signOut(_:)), for: .touchUpInside)
self.view.addSubview(signOutButton)
signOutButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
signOutButton.topAnchor.constraint(equalTo: callGraphButton.bottomAnchor, constant: 10.0).isActive = true
signOutButton.widthAnchor.constraint(equalToConstant: 150.0).isActive = true
signOutButton.heightAnchor.constraint(equalToConstant: 50.0).isActive = true
let deviceModeButton = UIButton()
deviceModeButton.translatesAutoresizingMaskIntoConstraints = false
deviceModeButton.setTitle("Get device info", for: .normal);
deviceModeButton.setTitleColor(.blue, for: .normal);
deviceModeButton.addTarget(self, action: #selector(getDeviceMode(_:)), for: .touchUpInside)
self.view.addSubview(deviceModeButton)
deviceModeButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
deviceModeButton.topAnchor.constraint(equalTo: signOutButton.bottomAnchor, constant: 10.0).isActive = true
deviceModeButton.widthAnchor.constraint(equalToConstant: 150.0).isActive = true
deviceModeButton.heightAnchor.constraint(equalToConstant: 50.0).isActive = true
// Add logging textfield
loggingText = UITextView()
loggingText.isUserInteractionEnabled = false
loggingText.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(loggingText)
loggingText.topAnchor.constraint(equalTo: deviceModeButton.bottomAnchor, constant: 10.0).isActive = true
loggingText.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 10.0).isActive = true
loggingText.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -10.0).isActive = true
loggingText.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 10.0).isActive = true
}
func platformViewDidLoadSetup() {
NotificationCenter.default.addObserver(self,
selector: #selector(appCameToForeGround(notification:)),
name: UIApplication.willEnterForegroundNotification,
object: nil)
}
@objc func appCameToForeGround(notification: Notification) {
self.loadCurrentAccount()
}
uživatelské rozhraní macOS
var callGraphButton: NSButton!
var loggingText: NSTextView!
var signOutButton: NSButton!
var usernameLabel: NSTextField!
func initUI() {
usernameLabel = NSTextField()
usernameLabel.translatesAutoresizingMaskIntoConstraints = false
usernameLabel.stringValue = ""
usernameLabel.isEditable = false
usernameLabel.isBezeled = false
self.view.addSubview(usernameLabel)
usernameLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 30.0).isActive = true
usernameLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -10.0).isActive = true
// Add call Graph button
callGraphButton = NSButton()
callGraphButton.translatesAutoresizingMaskIntoConstraints = false
callGraphButton.title = "Call Microsoft Graph API"
callGraphButton.target = self
callGraphButton.action = #selector(callGraphAPI(_:))
callGraphButton.bezelStyle = .rounded
self.view.addSubview(callGraphButton)
callGraphButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
callGraphButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 50.0).isActive = true
callGraphButton.heightAnchor.constraint(equalToConstant: 34.0).isActive = true
// Add sign out button
signOutButton = NSButton()
signOutButton.translatesAutoresizingMaskIntoConstraints = false
signOutButton.title = "Sign Out"
signOutButton.target = self
signOutButton.action = #selector(signOut(_:))
signOutButton.bezelStyle = .texturedRounded
self.view.addSubview(signOutButton)
signOutButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
signOutButton.topAnchor.constraint(equalTo: callGraphButton.bottomAnchor, constant: 10.0).isActive = true
signOutButton.heightAnchor.constraint(equalToConstant: 34.0).isActive = true
signOutButton.isEnabled = false
// Add logging textfield
loggingText = NSTextView()
loggingText.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(loggingText)
loggingText.topAnchor.constraint(equalTo: signOutButton.bottomAnchor, constant: 10.0).isActive = true
loggingText.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 10.0).isActive = true
loggingText.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -10.0).isActive = true
loggingText.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -10.0).isActive = true
loggingText.widthAnchor.constraint(equalToConstant: 500.0).isActive = true
loggingText.heightAnchor.constraint(equalToConstant: 300.0).isActive = true
}
func platformViewDidLoadSetup() {}
Dále v rámci ViewController
třídy nahraďte metodu viewDidLoad()
tímto:
override func viewDidLoad() {
super.viewDidLoad()
initUI()
do {
try self.initMSAL()
} catch let error {
self.updateLogging(text: "Unable to create Application Context \(error)")
}
self.loadCurrentAccount()
self.platformViewDidLoadSetup()
}
Použití knihovny MSAL
Inicializace knihovny MSAL
ViewController
Do třídy přidejte metoduinitMSAL
:
func initMSAL() throws {
guard let authorityURL = URL(string: kAuthority) else {
self.updateLogging(text: "Unable to create authority URL")
return
}
let authority = try MSALAADAuthority(url: authorityURL)
let msalConfiguration = MSALPublicClientApplicationConfig(clientId: kClientID, redirectUri: nil, authority: authority)
self.applicationContext = try MSALPublicClientApplication(configuration: msalConfiguration)
self.initWebViewParams()
}
Stále ve ViewController
třídě a za metodou initMSAL
přidejte metodu initWebViewParams
:
Kód iOS:
func initWebViewParams() {
self.webViewParameters = MSALWebviewParameters(authPresentationViewController: self)
}
Kód macOS:
func initWebViewParams() {
self.webViewParameters = MSALWebviewParameters()
}
Zpracování zpětného volání přihlášení (jenom iOS)
Otevřete soubor AppDelegate.swift. Chcete-li zpracovat zpětné volání po přihlášení, přidejte MSALPublicClientApplication.handleMSALResponse
do appDelegate
třídy takto:
// Inside AppDelegate...
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String)
}
Pokud používáte Xcode 11, měli byste místo toho umístit zpětné volání MSAL do sceneDelegate.swift . Pokud podporujete JAK UISceneDelegate, tak UIApplicationDelegate kvůli kompatibilitě se starším iOSem, bude nutné zpětné volání MSAL umístit do obou souborů.
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let urlContext = URLContexts.first else {
return
}
let url = urlContext.url
let sourceApp = urlContext.options.sourceApplication
MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: sourceApp)
}
Získání tokenů
Teď můžeme implementovat logiku zpracování uživatelského rozhraní aplikace a interaktivně získat tokeny prostřednictvím knihovny MSAL.
MSAL zveřejňuje dvě primární metody pro získání tokenů: acquireTokenSilently()
a acquireTokenInteractively()
.
acquireTokenSilently()
pokusí se přihlásit uživatele a získat tokeny bez zásahu uživatele, pokud je k dispozici účet.acquireTokenSilently()
vyžadovat platnouMSALAccount
hodnotu, kterou lze načíst pomocí některého z rozhraní API výčtu účtů MSAL. Tento kurz používáapplicationContext.getCurrentAccount(with: msalParameters, completionBlock: {})
k načtení aktuálního účtu.acquireTokenInteractively()
při pokusu o přihlášení uživatele se vždy zobrazí uživatelské rozhraní. K zajištění interaktivního jednotného přihlašování může používat soubory cookie relace v prohlížeči nebo účet v authenticatoru Microsoftu.
Do třídy přidejte následující kód ViewController
:
func getGraphEndpoint() -> String {
return kGraphEndpoint.hasSuffix("/") ? (kGraphEndpoint + "v1.0/me/") : (kGraphEndpoint + "/v1.0/me/");
}
@objc func callGraphAPI(_ sender: AnyObject) {
self.loadCurrentAccount { (account) in
guard let currentAccount = account else {
// We check to see if we have a current logged in account.
// If we don't, then we need to sign someone in.
self.acquireTokenInteractively()
return
}
self.acquireTokenSilently(currentAccount)
}
}
typealias AccountCompletion = (MSALAccount?) -> Void
func loadCurrentAccount(completion: AccountCompletion? = nil) {
guard let applicationContext = self.applicationContext else { return }
let msalParameters = MSALParameters()
msalParameters.completionBlockQueue = DispatchQueue.main
applicationContext.getCurrentAccount(with: msalParameters, completionBlock: { (currentAccount, previousAccount, error) in
if let error = error {
self.updateLogging(text: "Couldn't query current account with error: \(error)")
return
}
if let currentAccount = currentAccount {
self.updateLogging(text: "Found a signed in account \(String(describing: currentAccount.username)). Updating data for that account...")
self.updateCurrentAccount(account: currentAccount)
if let completion = completion {
completion(self.currentAccount)
}
return
}
self.updateLogging(text: "Account signed out. Updating UX")
self.accessToken = ""
self.updateCurrentAccount(account: nil)
if let completion = completion {
completion(nil)
}
})
}
Interaktivní získání tokenu
Následující fragment kódu získá token poprvé vytvořením objektu MSALInteractiveTokenParameters
a voláním acquireToken
. Dále přidáte kód, který:
- Vytvoří
MSALInteractiveTokenParameters
s obory. - Volání
acquireToken()
s vytvořenými parametry. - Zpracovává chyby. Další podrobnosti najdete v průvodci zpracováním chyb MSAL pro iOS a macOS.
- Zpracuje úspěšný případ.
Do třídy ViewController
přidejte následující kód.
func acquireTokenInteractively() {
guard let applicationContext = self.applicationContext else { return }
guard let webViewParameters = self.webViewParameters else { return }
// #1
let parameters = MSALInteractiveTokenParameters(scopes: kScopes, webviewParameters: webViewParameters)
parameters.promptType = .selectAccount
// #2
applicationContext.acquireToken(with: parameters) { (result, error) in
// #3
if let error = error {
self.updateLogging(text: "Could not acquire token: \(error)")
return
}
guard let result = result else {
self.updateLogging(text: "Could not acquire token: No result returned")
return
}
// #4
self.accessToken = result.accessToken
self.updateLogging(text: "Access token is \(self.accessToken)")
self.updateCurrentAccount(account: result.account)
self.getContentWithToken()
}
}
Vlastnost promptType
MSALInteractiveTokenParameters
konfiguruje chování ověřování a výzvy k vyjádření souhlasu. Podporovány jsou následující hodnoty:
.promptIfNecessary
(výchozí) – Uživatel se zobrazí pouze v případě potřeby. Prostředí jednotného přihlašování je určeno přítomností souborů cookie ve webovém zobrazení a typem účtu. Pokud je přihlášeno více uživatelů, zobrazí se prostředí pro výběr účtu. Toto je výchozí chování..selectAccount
– Pokud není zadaný žádný uživatel, zobrazí ověřovací webové zobrazení seznam aktuálně přihlášených účtů, ze které má uživatel vybírat..login
– Vyžaduje, aby se uživatel ověřil ve webovém zobrazení. Pokud tuto hodnotu zadáte, může být současně přihlášen pouze jeden účet..consent
– Vyžaduje, aby uživatel souhlasil s aktuální sadou oborů žádosti.
Bezobslužné získání tokenu
Pokud chcete získat aktualizovaný token bezobslužně, přidejte do ViewController
třídy následující kód. MSALSilentTokenParameters
Vytvoří objekt a voláníacquireTokenSilent()
:
func acquireTokenSilently(_ account : MSALAccount!) {
guard let applicationContext = self.applicationContext else { return }
/**
Acquire a token for an existing account silently
- forScopes: Permissions you want included in the access token received
in the result in the completionBlock. Not all scopes are
guaranteed to be included in the access token returned.
- account: An account object that we retrieved from the application object before that the
authentication flow will be locked down to.
- completionBlock: The completion block that will be called when the authentication
flow completes, or encounters an error.
*/
let parameters = MSALSilentTokenParameters(scopes: kScopes, account: account)
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) {
DispatchQueue.main.async {
self.acquireTokenInteractively()
}
return
}
}
self.updateLogging(text: "Could not acquire token silently: \(error)")
return
}
guard let result = result else {
self.updateLogging(text: "Could not acquire token: No result returned")
return
}
self.accessToken = result.accessToken
self.updateLogging(text: "Refreshed Access token is \(self.accessToken)")
self.updateSignOutButton(enabled: true)
self.getContentWithToken()
}
}
Volání rozhraní Microsoft Graph API
Jakmile máte token, může ji vaše aplikace použít v hlavičce HTTP k vytvoření autorizovaného požadavku do Microsoft Graphu:
klíč záhlaví | hodnota |
---|---|
Autorizace | Nosný <přístupový token> |
Do třídy přidejte následující kód ViewController
:
func getContentWithToken() {
// Specify the Graph API endpoint
let graphURI = getGraphEndpoint()
let url = URL(string: graphURI)
var request = URLRequest(url: url!)
// Set the Authorization header for the request. We use Bearer tokens, so we specify Bearer + the token we got from the result
request.setValue("Bearer \(self.accessToken)", forHTTPHeaderField: "Authorization")
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
self.updateLogging(text: "Couldn't get graph result: \(error)")
return
}
guard let result = try? JSONSerialization.jsonObject(with: data!, options: []) else {
self.updateLogging(text: "Couldn't deserialize result JSON")
return
}
self.updateLogging(text: "Result from Graph: \(result))")
}.resume()
}
Další informace o rozhraní Microsoft Graph API najdete v rozhraní Microsoft Graph API.
Použití knihovny MSAL k odhlášení
Dále přidejte podporu pro odhlášení.
Důležité
Odhlášení pomocí knihovny MSAL odebere všechny známé informace o uživateli z aplikace a také odebere aktivní relaci na svém zařízení, pokud je povolená konfigurace zařízení. Uživatele můžete také volitelně odhlásit z prohlížeče.
Pokud chcete přidat funkci odhlášení, přidejte do ViewController
třídy následující kód.
@objc func signOut(_ sender: AnyObject) {
guard let applicationContext = self.applicationContext else { return }
guard let account = self.currentAccount else { return }
do {
/**
Removes all tokens from the cache for this application for the provided account
- account: The account to remove from the cache
*/
let signoutParameters = MSALSignoutParameters(webviewParameters: self.webViewParameters!)
signoutParameters.signoutFromBrowser = false // set this to true if you also want to signout from browser or webview
applicationContext.signout(with: account, signoutParameters: signoutParameters, completionBlock: {(success, error) in
if let error = error {
self.updateLogging(text: "Couldn't sign out account with error: \(error)")
return
}
self.updateLogging(text: "Sign out completed successfully")
self.accessToken = ""
self.updateCurrentAccount(account: nil)
})
}
}
Povolení ukládání tokenů do mezipaměti
Ve výchozím nastavení MSAL ukládá tokeny vaší aplikace do mezipaměti v klíčence pro iOS nebo macOS.
Povolení ukládání tokenů do mezipaměti:
- Ujistěte se, že je vaše aplikace správně podepsaná.
- Přejděte na kartu>Možnosti nastavení >projektu Xcode Povolit sdílení řetězce klíčů.
- Vyberte + a zadejte jednu z následujících skupin řetězce klíčů:
- Ios:
com.microsoft.adalcache
- macOS:
com.microsoft.identity.universalstorage
- Ios:
Přidání pomocných metod
Přidejte do ViewController
třídy následující pomocné metody pro dokončení ukázky.
Uživatelské rozhraní iOS:
func updateLogging(text : String) {
if Thread.isMainThread {
self.loggingText.text = text
} else {
DispatchQueue.main.async {
self.loggingText.text = text
}
}
}
func updateSignOutButton(enabled : Bool) {
if Thread.isMainThread {
self.signOutButton.isEnabled = enabled
} else {
DispatchQueue.main.async {
self.signOutButton.isEnabled = enabled
}
}
}
func updateAccountLabel() {
guard let currentAccount = self.currentAccount else {
self.usernameLabel.text = "Signed out"
return
}
self.usernameLabel.text = currentAccount.username
}
func updateCurrentAccount(account: MSALAccount?) {
self.currentAccount = account
self.updateAccountLabel()
self.updateSignOutButton(enabled: account != nil)
}
uživatelské rozhraní macOS:
func updateLogging(text : String) {
if Thread.isMainThread {
self.loggingText.string = text
} else {
DispatchQueue.main.async {
self.loggingText.string = text
}
}
}
func updateSignOutButton(enabled : Bool) {
if Thread.isMainThread {
self.signOutButton.isEnabled = enabled
} else {
DispatchQueue.main.async {
self.signOutButton.isEnabled = enabled
}
}
}
func updateAccountLabel() {
guard let currentAccount = self.currentAccount else {
self.usernameLabel.stringValue = "Signed out"
return
}
self.usernameLabel.stringValue = currentAccount.username ?? ""
self.usernameLabel.sizeToFit()
}
func updateCurrentAccount(account: MSALAccount?) {
self.currentAccount = account
self.updateAccountLabel()
self.updateSignOutButton(enabled: account != nil)
}
Jenom iOS: získání dalších informací o zařízeních
Pomocí následujícího kódu si můžete přečíst aktuální konfiguraci zařízení, včetně toho, jestli je zařízení nakonfigurované jako sdílené:
@objc func getDeviceMode(_ sender: AnyObject) {
if #available(iOS 13.0, *) {
self.applicationContext?.getDeviceInformation(with: nil, completionBlock: { (deviceInformation, error) in
guard let deviceInfo = deviceInformation else {
self.updateLogging(text: "Device info not returned. Error: \(String(describing: error))")
return
}
let isSharedDevice = deviceInfo.deviceMode == .shared
let modeString = isSharedDevice ? "shared" : "private"
self.updateLogging(text: "Received device info. Device is in the \(modeString) mode.")
})
} else {
self.updateLogging(text: "Running on older iOS. GetDeviceInformation API is unavailable.")
}
}
Vícefaktorové aplikace
Tato aplikace je vytvořená pro scénář jednoho účtu. MSAL také podporuje scénáře s více účty, ale vyžaduje více práce s aplikací. Musíte vytvořit uživatelské rozhraní, které uživatelům pomůže vybrat účet, který chtějí použít pro každou akci, která vyžaduje tokeny. Alternativně může vaše aplikace implementovat heuristiku pro výběr účtu, který se má použít, dotazováním všech účtů z KNIHOVNY MSAL. Podívejte se accountsFromDeviceForParameters:completionBlock:
například na rozhraní API.
Testování aplikace
Sestavte a nasaďte aplikaci do testovacího zařízení nebo simulátoru. Měli byste být schopni se přihlásit a získat tokeny pro účty Microsoft Entra ID nebo osobní účty Microsoft.
Když se uživatel poprvé přihlásí k vaší aplikaci, vyzve ho identita Microsoftu k vyjádření souhlasu s požadovanými oprávněními. Většina uživatelů sice může souhlasit, ale někteří tenanti Microsoft Entra zakázali souhlas uživatele, což vyžaduje, aby správci souhlasili jménem všech uživatelů. Pokud chcete tento scénář podporovat, zaregistrujte rozsahy vaší aplikace.
Po přihlášení aplikace zobrazí data vrácená z koncového bodu Microsoft Graphu /me
.
Další kroky
Přečtěte si další informace o vytváření mobilních aplikací, které volají chráněná webová rozhraní API v naší řadě scénářů s více částmi.