Självstudie: Logga in användare och anropa Microsoft Graph från en iOS- eller macOS-app
I den här självstudien skapar du en iOS- eller macOS-app som integreras med Microsoft platforma za identitete för att signera användare och få en åtkomsttoken för att anropa Microsoft Graph API.
När du har slutfört självstudien godkänner ditt program inloggningar med personliga Microsoft-konton (inklusive outlook.com, live.com och andra) och arbets- eller skolkonton från alla företag eller organisationer som använder Microsoft Entra-ID. Den här självstudien gäller för både iOS- och macOS-appar. Vissa steg skiljer sig mellan de två plattformarna.
I den här självstudien:
- Skapa ett iOS- eller macOS-appprojekt i Xcode
- Registrera appen i administrationscentret för Microsoft Entra
- Lägga till kod för att stödja användarinloggning och utloggning
- Lägga till kod för att anropa Microsoft Graph API
- Testa appen
Förutsättningar
Så här fungerar självstudieappen
Appen i den här självstudien kan logga in användare och hämta data från Microsoft Graph för deras räkning. Dessa data nås via ett skyddat API (Microsoft Graph API i det här fallet) som kräver auktorisering och skyddas av Microsoft platforma za identitete.
Mer specifikt:
- Appen loggar in användaren antingen via en webbläsare eller Microsoft Authenticator.
- Slutanvändaren godkänner de behörigheter som programmet har begärt.
- Din app utfärdas en åtkomsttoken för Microsoft Graph-API:et.
- Åtkomsttoken ingår i HTTP-begäran till webb-API:et.
- Bearbeta Microsoft Graph-svaret.
Det här exemplet använder Microsoft Authentication Library (MSAL) för att implementera autentisering. MSAL förnyar automatiskt token, levererar enkel inloggning (SSO) mellan andra appar på enheten och hanterar kontona.
Om du vill ladda ned en färdig version av appen som du skapar i den här självstudien kan du hitta båda versionerna på GitHub:
- iOS-kodexempel (GitHub)
- macOS-kodexempel (GitHub)
Skapa ett nytt projekt
- Öppna Xcode och välj Skapa ett nytt Xcode-projekt.
- För iOS-appar väljer du iOS>Enkel visningsapp och väljer Nästa.
- För macOS-appar väljer du macOS>Cocoa App och väljer Nästa.
- Ange ett produktnamn.
- Ange Språket till Swift och välj Nästa.
- Välj en mapp för att skapa din app och välj Skapa.
Registrera programmet
Dricks
Stegen i den här artikeln kan variera något beroende på vilken portal du börjar från.
- Logga in på administrationscentret för Microsoft Entra som minst programutvecklare.
- Om du har åtkomst till flera klienter använder du ikonen Inställningar på den översta menyn för att växla till den klientorganisation där du vill registrera programmet från menyn Kataloger + prenumerationer.
- Bläddra till Appregistreringar för identitetsprogram>>.
- Välj Ny registrering.
- Ange ett namn för ditt program. Användare av din app kan se det här namnet och du kan ändra det senare.
- Välj Konton i valfri organisationskatalog (Alla Microsoft Entra-kataloger – Multitenant) och personliga Microsoft-konton (t.ex. Skype, Xbox) under Kontotyper som stöds.
- Välj Registrera.
- Under Hantera väljer du Autentisering>Lägg till en plattforms-iOS>/macOS.
- Ange projektets paket-ID. Om du har laddat ned kodexemplet är
com.microsoft.identitysample.MSALiOS
paket-ID : . Om du skapar ett eget projekt väljer du projektet i Xcode och öppnar fliken Allmänt . Paketidentifieraren visas i avsnittet Identitet . - Välj Konfigurera och spara MSAL-konfigurationen som visas på MSAL-konfigurationssidan så att du kan ange den när du konfigurerar appen senare.
- Välj Klar.
Lägg till MSAL
Välj något av följande sätt att installera MSAL-biblioteket i din app:
CocoaPods
Om du använder CocoaPods installerar
MSAL
du genom att först skapa en tom fil med namnet podfile i samma mapp som projektets .xcodeproj-fil. Lägg till följande i poddfile:use_frameworks! target '<your-target-here>' do pod 'MSAL' end
Ersätt
<your-target-here>
med namnet på projektet.I ett terminalfönster navigerar du till mappen som innehåller poddfilen som du skapade och kör
pod install
för att installera MSAL-biblioteket.Stäng Xcode och öppna
<your project name>.xcworkspace
för att läsa in projektet igen i Xcode.
Karthago
Om du använder Carthage installerar MSAL
du genom att lägga till det i din Cartfile:
github "AzureAD/microsoft-authentication-library-for-objc" "master"
Från ett terminalfönster kör du följande kommando i samma katalog som den uppdaterade Cartfile för att låta Carthage uppdatera beroendena i projektet.
iOS:
carthage update --platform iOS
macOS:
carthage update --platform macOS
Manuellt
Du kan också använda Git-undermodulen eller kolla in den senaste versionen för att använda som ett ramverk i ditt program.
Lägg till appregistreringen
Därefter lägger vi till din appregistrering i koden.
Lägg först till följande importinstruktion högst upp i filen ViewController.swift och antingen AppDelegate.swift eller SceneDelegate.swift:
import MSAL
Lägg sedan till följande kod i ViewController.swift före i 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?
Det enda värde som du ändrar är värdet som tilldelats till kClientID
ditt program-ID. Det här värdet är en del av de MSAL-konfigurationsdata som du sparade under steget i början av den här självstudien för att registrera programmet.
Konfigurera Xcode-projektinställningar
Lägg till en ny nyckelringsgrupp i projektets signerings- och funktioner. Nyckelringsgruppen ska finnas com.microsoft.adalcache
i iOS och com.microsoft.identity.universalstorage
på macOS.
Endast för iOS konfigurerar du URL-scheman
I det här steget registrerar CFBundleURLSchemes
du så att användaren kan omdirigeras tillbaka till appen efter inloggningen. Förresten, LSApplicationQueriesSchemes
gör det också möjligt för din app att använda Microsoft Authenticator.
I Xcode öppnar du Info.plist som en källkodsfil och lägger till följande i <dict>
avsnittet. Ersätt [BUNDLE_ID]
med det värde som du använde tidigare. Om du laddade ned koden är com.microsoft.identitysample.MSALiOS
paketidentifieraren . Om du skapar ett eget projekt väljer du projektet i Xcode och öppnar fliken Allmänt . Paketidentifieraren visas i avsnittet Identitet .
<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>
Endast för macOS konfigurerar du appens sandbox-miljö
- Gå till fliken>Funktioner för Xcode-projektinställningar >Appsandlåda
- Markera kryssrutan Utgående anslutningar (klient ).
Skapa appens användargränssnitt
Skapa nu ett användargränssnitt som innehåller en knapp för att anropa Microsoft Graph API, en annan för att logga ut och en textvy för att se vissa utdata genom att lägga till följande kod i ViewController
klassen:
iOS-användargränssnitt
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()
}
macOS-användargränssnitt
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() {}
I klassen ersätter viewDidLoad()
du sedan ViewController
metoden med:
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()
}
Använda MSAL
Initiera MSAL
Lägg till metoden i ViewController
initMSAL
klassen:
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()
}
Lägg till metoden i ViewController
klassen och efter initMSAL
- initWebViewParams
metoden:
iOS-kod:
func initWebViewParams() {
self.webViewParameters = MSALWebviewParameters(authPresentationViewController: self)
}
macOS-kod:
func initWebViewParams() {
self.webViewParameters = MSALWebviewParameters()
}
Hantera återanropet för inloggning (endast iOS)
Öppna filen AppDelegate.swift. Om du vill hantera återanropet efter inloggningen lägger du till MSALPublicClientApplication.handleMSALResponse
i appDelegate
klassen så här:
// 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)
}
Om du använder Xcode 11 bör du placera MSAL-återanrop till SceneDelegate.swift i stället. Om du stöder både UISceneDelegate och UIApplicationDelegate för kompatibilitet med äldre iOS måste MSAL-motringning placeras i båda filerna.
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)
}
Hämta token
Nu kan vi implementera programmets UI-bearbetningslogik och hämta token interaktivt via MSAL.
MSAL exponerar två primära metoder för att hämta token: acquireTokenSilently()
och acquireTokenInteractively()
.
acquireTokenSilently()
försöker logga in en användare och hämta token utan användarinteraktion så länge ett konto finns.acquireTokenSilently()
kräver ett giltigtMSALAccount
, som kan hämtas med någon av MSAL:s api:er för kontouppräkning. I den här självstudien användsapplicationContext.getCurrentAccount(with: msalParameters, completionBlock: {})
för att hämta det aktuella kontot.acquireTokenInteractively()
visar alltid användargränssnittet när du försöker logga in användaren. Den kan använda sessionscookies i webbläsaren eller ett konto i Microsoft-autentiseringen för att tillhandahålla en interaktiv SSO-upplevelse.
Lägg till följande kod i ViewController
klassen:
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)
}
})
}
Hämta en token interaktivt
Följande kodfragment hämtar en token för första gången genom att skapa ett MSALInteractiveTokenParameters
objekt och anropa acquireToken
. Därefter lägger du till kod som:
- Skapar
MSALInteractiveTokenParameters
med omfång. - Anrop
acquireToken()
med de skapade parametrarna. - Hanterar fel. Mer information finns i felhanteringsguiden för MSAL för iOS och macOS.
- Hanterar det lyckade fallet.
Lägg till följande kod i klassen ViewController
.
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()
}
}
Egenskapen promptType
MSALInteractiveTokenParameters
för konfigurerar beteendet för autentisering och medgivandefråga. Följande värden stöds:
.promptIfNecessary
(standard) – Användaren uppmanas endast om det behövs. SSO-upplevelsen bestäms av förekomsten av cookies i webbvyn och kontotypen. Om flera användare är inloggade visas upplevelsen för val av konto. Det här är standardbeteendet..selectAccount
– Om ingen användare har angetts visar webbvyn för autentisering en lista över konton som användaren kan välja mellan för närvarande inloggade konton..login
– Kräver att användaren autentiserar i webbvyn. Endast ett konto kan loggas in i taget om du anger det här värdet..consent
– Kräver att användaren godkänner den aktuella uppsättningen omfång för begäran.
Hämta en token tyst
Om du vill hämta en uppdaterad token tyst lägger du till följande kod i ViewController
klassen. Det skapar ett MSALSilentTokenParameters
objekt och anropar 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()
}
}
Anropa Microsoft Graph API
När du har en token kan appen använda den i HTTP-huvudet för att göra en auktoriserad begäran till Microsoft Graph:
rubriknyckel | värde |
---|---|
Auktorisering | <Ägaråtkomsttoken> |
Lägg till följande kod i ViewController
klassen:
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()
}
Mer information om Microsoft Graph API finns i Microsoft Graph API .
Använda MSAL för utloggning
Lägg sedan till stöd för utloggning.
Viktigt!
När du loggar ut med MSAL tas all känd information om en användare bort från programmet, samt en aktiv session på enheten tas bort när den tillåts av enhetskonfigurationen. Du kan också logga ut användaren från webbläsaren.
Lägg till följande kod i ViewController
klassen för att lägga till utloggningsfunktionen.
@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)
})
}
}
Aktivera cachelagring av token
Som standard cachelagrar MSAL appens token i iOS- eller macOS-nyckelringen.
Så här aktiverar du cachelagring av token:
- Kontrollera att programmet är korrekt signerat
- Gå till fliken>Funktioner för Xcode-projektinställningar >Aktivera nyckelringsdelning
- Välj + och ange någon av följande nyckelringsgrupper:
- Ios:
com.microsoft.adalcache
- macOS:
com.microsoft.identity.universalstorage
- Ios:
Lägga till hjälpmetoder
Lägg till följande hjälpmetoder i ViewController
klassen för att slutföra exemplet.
iOS-användargränssnitt:
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)
}
macOS-användargränssnitt:
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)
}
Endast iOS: hämta ytterligare enhetsinformation
Använd följande kod för att läsa den aktuella enhetskonfigurationen, inklusive om enheten är konfigurerad som delad:
@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.")
}
}
Program med flera konton
Den här appen är skapad för ett enskilt kontoscenario. MSAL stöder även scenarier med flera konton, men det krävs mer programarbete. Du måste skapa användargränssnitt för att hjälpa användare att välja vilket konto de vill använda för varje åtgärd som kräver token. Du kan också implementera en heuristisk app för att välja vilket konto som ska användas genom att fråga alla konton från MSAL. Se till exempel accountsFromDeviceForParameters:completionBlock:
API
Testa din app
Skapa och distribuera appen till en testenhet eller simulator. Du bör kunna logga in och hämta token för Microsoft Entra-ID eller personliga Microsoft-konton.
Första gången en användare loggar in på din app uppmanas de av Microsoft-identiteten att samtycka till de begärda behörigheterna. Även om de flesta användare kan samtycka har vissa Microsoft Entra-klienter inaktiverat användarmedgivande, vilket kräver att administratörer samtycker för alla användares räkning. För att stödja det här scenariot registrerar du appens omfång.
När du har loggat in visar appen data som returneras från Microsoft Graph-slutpunkten /me
.
Nästa steg
Läs mer om att skapa mobilappar som anropar skyddade webb-API:er i vår scenarioserie i flera delar.