Öğretici: iOS veya macOS uygulamasından kullanıcılarda oturum açma ve Microsoft Graph'ı çağırma
Bu öğreticide, kullanıcıları imzalamak ve Microsoft Graph API'sini çağırmak için erişim belirteci almak için Microsoft kimlik platformu ile tümleşen bir iOS veya macOS uygulaması oluşturacaksınız.
Öğreticiyi tamamladığınızda, uygulamanız Microsoft Entra Id kullanan herhangi bir şirket veya kuruluştan kişisel Microsoft hesaplarının (outlook.com, live.com ve diğerleri dahil) ve iş veya okul hesaplarının oturum açmalarını kabul eder. Bu öğretici hem iOS hem de macOS uygulamaları için geçerlidir. Bazı adımlar iki platform arasında farklıdır.
Bu öğreticide:
- Xcode'da iOS veya macOS uygulama projesi oluşturma
- Uygulamayı Microsoft Entra yönetim merkezine kaydetme
- Kullanıcı oturum açma ve oturum kapatmayı desteklemek için kod ekleme
- Microsoft Graph API'sini çağırmak için kod ekleme
- Uygulamayı test etme
Önkoşullar
Öğretici uygulaması nasıl çalışır?
Bu öğreticideki uygulama, kullanıcılarda oturum açabilir ve kendi adlarına Microsoft Graph'ten veri alabilir. Bu verilere yetkilendirme gerektiren ve Microsoft kimlik platformu tarafından korunan bir korumalı API (bu örnekte Microsoft Graph API'si) aracılığıyla erişilir.
Daha açık belirtmek gerekirse:
- Uygulamanız bir tarayıcı veya Microsoft Authenticator aracılığıyla kullanıcıda oturum açar.
- Son kullanıcı, uygulamanızın istediği izinleri kabul eder.
- Uygulamanıza Microsoft Graph API için bir erişim belirteci verilir.
- Erişim belirteci, web API'sine http isteğine eklenir.
- Microsoft Graph yanıtını işleme.
Bu örnek, Kimlik Doğrulamasını uygulamak için Microsoft Kimlik Doğrulama Kitaplığı'nı (MSAL) kullanır. MSAL belirteçleri otomatik olarak yeniler, cihazdaki diğer uygulamalar arasında çoklu oturum açma (SSO) sunar ve hesapları yönetir.
Bu öğreticide oluşturduğunuz uygulamanın tamamlanmış bir sürümünü indirmek isterseniz gitHub'da her iki sürümü de bulabilirsiniz:
- iOS kod örneği (GitHub)
- macOS kod örneği (GitHub)
Yeni proje oluşturma
- Xcode'u açın ve Yeni Xcode projesi oluştur'u seçin.
- iOS uygulamaları için iOS>Tek görünüm Uygulaması'nı ve ardından İleri'yi seçin.
- macOS uygulamaları için macOS>Cocoa Uygulaması'nı ve ardından İleri'yi seçin.
- Bir ürün adı belirtin.
- Dil'i Swift olarak ayarlayın ve İleri'yi seçin.
- Uygulamanızı oluşturmak için bir klasör seçin ve Oluştur'u seçin.
Uygulamayı kaydetme
İpucu
Bu makaledeki adımlar, başladığınız portala göre biraz değişiklik gösterebilir.
- Microsoft Entra yönetim merkezinde en azından Uygulama Geliştiricisi olarak oturum açın.
- Birden çok kiracıya erişiminiz varsa, Dizinler + abonelikler menüsünden uygulamayı kaydetmek istediğiniz kiracıya geçmek için üst menüdeki Ayarlar simgesini kullanın.
- Kimlik>Uygulamaları'na> göz atın Uygulama kayıtları.
- Yeni kayıt öğesini seçin.
- Uygulamanız için bir Ad girin. Uygulamanızın kullanıcıları bu adı görebilir ve daha sonra değiştirebilirsiniz.
- Desteklenen hesap türleri altından herhangi bir kuruluş dizininde (Herhangi bir Microsoft Entra dizini - Çok Kiracılı) ve kişisel Microsoft hesaplarında (örneğin Skype, Xbox) Hesaplar'ı seçin.
- Kaydet'i seçin.
- Yönet'in altında Kimlik Doğrulaması>Platform>ekle iOS/macOS'ı seçin.
- Projenizin Paket Kimliğini girin. Kod örneği indirilirse Paket Kimliği olur
com.microsoft.identitysample.MSALiOS
. Kendi projenizi oluşturuyorsanız, Xcode'da projenizi seçin ve Genel sekmesini açın. Paket tanımlayıcısı Kimlik bölümünde görünür. - Yapılandır'ı seçin ve uygulamanızı daha sonra yapılandırırken girebilmeniz için MSAL yapılandırma sayfasında görüntülenen MSAL Yapılandırmasını kaydedin.
- Bitti'yi seçin.
MSAL Ekleme
MSAL kitaplığını uygulamanıza yüklemek için aşağıdaki yollardan birini seçin:
CocoaPods
CocoaPods kullanıyorsanız, önce projenizin .xcodeproj dosyasıyla aynı klasörde podfile adlı boş bir dosya oluşturarak yükleyin
MSAL
. Podfile'a aşağıdakileri ekleyin:use_frameworks! target '<your-target-here>' do pod 'MSAL' end
değerini projenizin adıyla değiştirin
<your-target-here>
.Terminal penceresinde, oluşturduğunuz pod dosyasını içeren klasöre gidin ve MSAL kitaplığını yüklemek için çalıştırın
pod install
.Xcode'ı kapatın ve projeyi Xcode'da yeniden yüklemek için açın
<your project name>.xcworkspace
.
Kartaca
Carthage kullanıyorsanız Cartfile dosyanıza ekleyerek yükleyinMSAL
:
github "AzureAD/microsoft-authentication-library-for-objc" "master"
Bir terminal penceresinde, güncelleştirilmiş Cartfile ile aynı dizinde, Carthage'ın projenizdeki bağımlılıkları güncelleştirmesini sağlamak için aşağıdaki komutu çalıştırın.
Ios:
carthage update --platform iOS
macOS:
carthage update --platform macOS
El ile
Ayrıca Git Submodule'i kullanabilir veya uygulamanızda çerçeve olarak kullanmak için en son sürüme göz atabilirsiniz.
Uygulama kaydını ekleme
Ardından uygulama kaydınızı kodunuza ekleyeceğiz.
İlk olarak, aşağıdaki içeri aktarma deyimini ViewController.swift dosyasının en üstüne ve AppDelegate.swift veya SceneDelegate.swift dosyasına ekleyin:
import MSAL
Ardından, aşağıdaki kodu viewcontroller.swift'e viewDidLoad()
ekleyin:
// 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?
Değiştirdiğiniz tek değer, Uygulama Kimliğiniz olarak atanan kClientID
değerdir. Bu değer, uygulamayı kaydetmek için bu öğreticinin başındaki adım sırasında kaydettiğiniz MSAL Yapılandırma verilerinin bir parçasıdır.
Xcode proje ayarlarını yapılandırma
Proje İmzalama ve Yeteneklerinize yeni bir anahtarlık grubu ekleyin. Anahtarlık grubu iOS ve com.microsoft.identity.universalstorage
macOS üzerinde olmalıdırcom.microsoft.adalcache
.
Yalnızca iOS için URL düzenlerini yapılandırın
Bu adımda, kullanıcının oturum açmadan sonra uygulamaya yeniden yönlendirilmesi için kaydolacaksınız CFBundleURLSchemes
. Bu arada, LSApplicationQueriesSchemes
uygulamanızın Microsoft Authenticator'ı kullanmasına da izin verir.
Xcode'da Info.plist dosyasını kaynak kod dosyası olarak açın ve bölümün <dict>
içine aşağıdakileri ekleyin. değerini daha önce kullandığınız değerle değiştirin [BUNDLE_ID]
. Kodu indirdiyseniz paket tanımlayıcısı olur com.microsoft.identitysample.MSALiOS
. Kendi projenizi oluşturuyorsanız, Xcode'da projenizi seçin ve Genel sekmesini açın. Paket tanımlayıcısı Kimlik bölümünde görünür.
<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>
Yalnızca macOS için Uygulama Korumalı Alanını yapılandırın
- Xcode Proje Ayarları >Özellikleri sekmesi>uygulama korumalı alanınıza gidin
- Giden Bağlantılar (İstemci) onay kutusunu seçin.
Uygulamanızın kullanıcı arabirimini oluşturma
Şimdi, sınıfına aşağıdaki kodu ViewController
ekleyerek Microsoft Graph API'sini çağırmak için bir düğme, oturumu kapatmak için başka bir düğme ve bazı çıktıları görmek için bir metin görünümü içeren bir kullanıcı arabirimi oluşturun:
iOS kullanıcı arabirimi
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 kullanıcı arabirimi
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() {}
Ardından, sınıfının içinde ViewController
de yöntemini şununla viewDidLoad()
değiştirin:
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()
}
MSAL kullanma
MSAL'ı başlatma
sınıfına ViewController
yöntemini ekleyin initMSAL
:
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()
}
ViewController
Hala sınıfında ve yönteminden initMSAL
sonra yöntemini ekleyininitWebViewParams
:
iOS kodu:
func initWebViewParams() {
self.webViewParameters = MSALWebviewParameters(authPresentationViewController: self)
}
macOS kodu:
func initWebViewParams() {
self.webViewParameters = MSALWebviewParameters()
}
Oturum açma geri çağırmasını işleme (yalnızca iOS)
AppDelegate.swift dosyasını açın. Oturum açmadan sonra geri çağırmayı işlemek için sınıfına appDelegate
şu şekilde ekleyinMSALPublicClientApplication.handleMSALResponse
:
// 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)
}
Xcode 11 kullanıyorsanız bunun yerine MSAL geri çağırmasını SceneDelegate.swift içine yerleştirmeniz gerekir. Eski iOS ile uyumluluk için hem UISceneDelegate hem de UIApplicationDelegate'i destekliyorsanız, MSAL geri çağırmanın her iki dosyaya da yerleştirilmesi gerekir.
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)
}
Belirteçleri Alma
Artık uygulamanın kullanıcı arabirimi işleme mantığını uygulayabilir ve MSAL aracılığıyla belirteçleri etkileşimli olarak alacağız.
MSAL, belirteçleri almak için iki birincil yöntem sunar: acquireTokenSilently()
ve acquireTokenInteractively()
.
acquireTokenSilently()
bir hesap mevcut olduğu sürece kullanıcı etkileşimi olmadan bir kullanıcıda oturum açmayı ve belirteçleri almayı dener.acquireTokenSilently()
MSAL'nin hesap numaralandırma API'lerinden biri kullanılarak alınabilen geçerliMSALAccount
bir gerektirir. Bu öğreticide geçerli hesabı almak için kullanılırapplicationContext.getCurrentAccount(with: msalParameters, completionBlock: {})
.acquireTokenInteractively()
kullanıcı oturum açmaya çalışırken her zaman kullanıcı arabirimini gösterir. Etkileşimli bir SSO deneyimi sağlamak için tarayıcıda oturum tanımlama bilgilerini veya Microsoft kimlik doğrulayıcıdaki bir hesabı kullanabilir.
Sınıfına ViewController
aşağıdaki kodu ekleyin:
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)
}
})
}
Etkileşimli olarak belirteç alma
Aşağıdaki kod parçacığı, bir nesnesi oluşturup çağırarak acquireToken
ilk kez bir MSALInteractiveTokenParameters
belirteç alır. Ardından şu kodu eklersiniz:
- Kapsamlarla oluşturur
MSALInteractiveTokenParameters
. - Oluşturulan parametrelerle çağrılar
acquireToken()
. - Hataları işler. Daha fazla ayrıntı için iOS ve macOS için MSAL hata işleme kılavuzuna bakın.
- Başarılı olayı işler.
Aşağıdaki kodu ViewController
sınıfına ekleyin.
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()
}
}
promptType
özelliğiMSALInteractiveTokenParameters
, kimlik doğrulaması ve onay istemi davranışını yapılandırmaktadır. Aşağıdaki değerler desteklenir:
.promptIfNecessary
(varsayılan) - Kullanıcıdan yalnızca gerekirse istenir. SSO deneyimi, web görünümünde tanımlama bilgilerinin bulunmasına ve hesap türüne göre belirlenir. Birden çok kullanıcı oturum açtıysa hesap seçimi deneyimi sunulur. Bu, varsayılan davranıştır..selectAccount
- Kullanıcı belirtilmezse, kimlik doğrulama web görünümü kullanıcının seçecekleri oturum açmış hesapların listesini sunar..login
- Kullanıcının web görünümünde kimlik doğrulamasını gerektirir. Bu değeri belirtirseniz aynı anda yalnızca bir hesap oturum açabilir..consent
- Kullanıcının istek için geçerli kapsam kümesini onaylamasını gerektirir.
Belirteci sessizce alma
Güncelleştirilmiş belirteci sessizce almak için sınıfına ViewController
aşağıdaki kodu ekleyin. Bir MSALSilentTokenParameters
nesnesi oluşturur ve öğesini çağırır 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()
}
}
Microsoft Graph API'sini çağırma
Belirteci aldıktan sonra uygulamanız, Microsoft Graph'a yetkili bir istekte bulunmak için bu belirteci HTTP üst bilgisinde kullanabilir:
üst bilgi anahtarı | değer |
---|---|
Yetkilendirme | Taşıyıcı <erişim belirteci> |
Sınıfına ViewController
aşağıdaki kodu ekleyin:
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()
}
Microsoft Graph API'si hakkında daha fazla bilgi edinmek için bkz. Microsoft Graph API'si.
Oturumu kapatmak için MSAL kullanma
Ardından, oturumu kapatma desteği ekleyin.
Önemli
MSAL ile oturum kapatıldığında kullanıcı hakkındaki tüm bilinen bilgiler uygulamadan kaldırılır ve cihaz yapılandırmasına izin verildiğinde cihazında etkin bir oturum kaldırılır. İsterseniz kullanıcının tarayıcıdan oturumunu kapatabilirsiniz.
Oturum kapatma özelliği eklemek için sınıfına ViewController
aşağıdaki kodu ekleyin.
@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)
})
}
}
Belirteç önbelleğe almayı etkinleştirme
Varsayılan olarak MSAL, uygulamanızın belirteçlerini iOS veya macOS anahtar zincirinde önbelleğe alır.
Belirteç önbelleğe almayı etkinleştirmek için:
- Uygulamanızın düzgün imzalandığından emin olun
- Xcode Proje Ayarları >Özellikleri sekmenize>gidin Anahtarlık Paylaşımını Etkinleştir
- Aşağıdaki Anahtar Zinciri Gruplarından birini seçin + ve girin:
- Ios:
com.microsoft.adalcache
- macOS:
com.microsoft.identity.universalstorage
- Ios:
Yardımcı yöntemler ekleme
Örneği tamamlamak için sınıfına ViewController
aşağıdaki yardımcı yöntemleri ekleyin.
iOS kullanıcı arabirimi:
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 kullanıcı arabirimi:
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)
}
Yalnızca iOS: Ek cihaz bilgilerini alma
Cihazın paylaşılan olarak yapılandırılıp yapılandırılmadığı da dahil olmak üzere geçerli cihaz yapılandırmasını okumak için aşağıdaki kodu kullanın:
@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.")
}
}
Çok hesaplı uygulamalar
Bu uygulama tek bir hesap senaryosu için oluşturulmuş. MSAL, çok hesaplı senaryoları da destekler, ancak daha fazla uygulama çalışması gerektirir. Kullanıcıların belirteç gerektiren her eylem için kullanmak istedikleri hesabı seçmelerine yardımcı olmak için kullanıcı arabirimi oluşturmanız gerekir. Alternatif olarak, uygulamanız MSAL'den tüm hesapları sorgulayarak hangi hesabın kullanılacağını seçmek için bir buluşsal yöntem uygulayabilir. Örneğin, bkz. accountsFromDeviceForParameters:completionBlock:
API
Uygulamanızı test etme
Uygulamayı derleyin ve bir test cihazına veya simülatörüne dağıtın. Oturum açabilmeniz ve Microsoft Entra Id veya kişisel Microsoft hesapları için belirteçler alabilmeniz gerekir.
Bir kullanıcı uygulamanızda ilk kez oturum açtığında, microsoft kimliği tarafından istenen izinleri onaylaması istenir. Kullanıcıların çoğu onay verebilir ancak bazı Microsoft Entra kiracıları, yöneticilerin tüm kullanıcılar adına onay vermelerini gerektiren kullanıcı onayını devre dışı bırakmıştır. Bu senaryoya destek olmak için uygulamanızın kapsamlarını kaydedin.
Oturum açtığınızda uygulama, Microsoft Graph /me
uç noktasından döndürülen verileri görüntüler.
Sonraki adımlar
Çok parçalı senaryo serimizde korumalı web API'lerini çağıran mobil uygulamalar oluşturma hakkında daha fazla bilgi edinin.