MSAL - Failed to set item into keychain when trying to authenticate Microsoft Graph login
I am trying to integrate with Microsoft Graph in my iOS application. I am developing in Swift on XCode. I followed this tutorial:
https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-ios#register-your-application
When I click connect, enter my login details, It keeps giving me the error message below. I have tried debugging and it goes into the acquireTokenInteractively() and the error is printed.
I have registered my application on the Microsoft app portal, enabled keychain sharing on the capabilities tab of the application etc, not really sure why this won't work..
thanks for any help.
import UIKit
import MSAL
class ViewController: UIViewController, UITextFieldDelegate, URLSessionDelegate
// Update the below to your client ID you received in the portal. The below is for running the demo only
let kClientID = "a88969f1-61c7-4322-a9a0-9212bb96b782"
// These settings you don't need to edit unless you wish to attempt deeper scenarios with the app.
let kGraphURI = "https://graph.microsoft.com/v1.0/me/"
//let kScopes: [String] = ["https://graph.microsoft.com/user.read"]
let kAuthority = "https://login.microsoftonline.com/common"
var accessToken = String()
var applicationContext : MSALPublicClientApplication?
@IBOutlet weak var connectButton: UIButton!
@IBOutlet weak var signoutButton: UIButton!
@IBOutlet weak var loggingText: UITextView!
@IBAction func connectButtonTapped(_ sender: UIButton)
print("Connect button tapped")
if self.currentAccount() == nil
// 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()
else
self.acquireTokenSilently()
@IBAction func signoutButtonTapped(_ sender: UIButton)
print("Signout button tapped")
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
*/
try applicationContext.remove(account)
self.loggingText.text = ""
self.signoutButton.isEnabled = false
catch let error as NSError
self.loggingText.text = "Received error signing account out: (error)"
/**
Setup public client application in viewDidLoad
*/
override func viewDidLoad()
super.viewDidLoad()
do
/**
Initialize a MSALPublicClientApplication with a given clientID and authority
- clientId: The clientID of your application, you should get this from the app portal.
- authority: A URL indicating a directory that MSAL can use to obtain tokens. In Azure AD
it is of the form https://<instance/<tenant>, where <instance> is the
directory host (e.g. https://login.microsoftonline.com) and <tenant> is a
identifier within the directory itself (e.g. a domain associated to the
tenant, such as contoso.onmicrosoft.com, or the GUID representing the
TenantID property of the directory)
- error The error that occurred creating the application object, if any, if you're
not interested in the specific error pass in nil.
*/
guard let authorityURL = URL(string: kAuthority) else
self.loggingText.text = "Unable to create authority URL"
return
let authority = try MSALAuthority(url: authorityURL)
self.applicationContext = try MSALPublicClientApplication(clientId: kClientID, authority: authority)
catch let error
self.loggingText.text = "Unable to create Application Context (error)"
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
signoutButton.isEnabled = !self.accessToken.isEmpty
/**
This button will invoke the authorization flow.
*/
@IBAction func callGraphButton(_ sender: UIButton)
if self.currentAccount() == nil
// 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()
else
self.acquireTokenSilently()
func getContentWithToken()
// Specify the Graph API endpoint
let url = URL(string: kGraphURI)
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.loggingText.text = "Couldn't get graph result: (error)"
return
guard let result = try? JSONSerialization.jsonObject(with: data!, options: ) else
self.loggingText.text = "Couldn't deserialize result JSON"
return
self.loggingText.text = "Result from Graph: (result))"
.resume()
func acquireTokenInteractively()
guard let applicationContext = self.applicationContext else return
applicationContext.acquireToken(forScopes: ApplicationConstants.kScopes) (result, error) in
if let error = error
self.loggingText.text = "Could not acquire token: (error)"
return
guard let result = result else
self.loggingText.text = "Could not acquire token: No result returned"
return
self.accessToken = result.accessToken
self.loggingText.text = "Access token is (self.accessToken)"
self.signoutButton.isEnabled = true
self.getContentWithToken()
func acquireTokenSilently()
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.
*/
applicationContext.acquireTokenSilent(forScopes: ApplicationConstants.kScopes, account: self.currentAccount()!) (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
&& nsError.code == MSALErrorCode.interactionRequired.rawValue)
DispatchQueue.main.async
self.acquireTokenInteractively()
else
self.loggingText.text = "Could not acquire token silently: (error)"
return
guard let result = result else
self.loggingText.text = "Could not acquire token: No result returned"
return
self.accessToken = result.accessToken
self.loggingText.text = "Refreshed Access token is (self.accessToken)"
self.signoutButton.isEnabled = true
self.getContentWithToken()
func currentAccount() -> MSALAccount?
guard let applicationContext = self.applicationContext else return nil
// We retrieve our current account by getting the first account from cache
// In multi-account applications, account should be retrieved by home account identifier or username instead
do
let cachedAccounts = try applicationContext.allAccounts()
if !cachedAccounts.isEmpty
return cachedAccounts.first
catch let error as NSError
self.loggingText.text = "Didn't find any accounts in cache: (error)"
return nil
//
struct ApplicationConstants
static let ResourceId = "https://graph.microsoft.com"
static let kAuthority = "https://login.microsoftonline.com/common/oauth2/v2.0"
static let kGraphURI = "https://graph.microsoft.com/v1.0/me/"
static let kScopes = ["https://graph.microsoft.com/Mail.ReadWrite",
"https://graph.microsoft.com/Mail.Send",
"https://graph.microsoft.com/Files.ReadWrite",
"https://graph.microsoft.com/User.ReadBasic.All"]
static var kClientID = "6d5a8e6d-0281-4003-8feb-43a9ca39d4d2"
enum MSGraphError: Error
case nsErrorType(error: NSError)
ios xcode microsoft-graph keychain msal
add a comment |
I am trying to integrate with Microsoft Graph in my iOS application. I am developing in Swift on XCode. I followed this tutorial:
https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-ios#register-your-application
When I click connect, enter my login details, It keeps giving me the error message below. I have tried debugging and it goes into the acquireTokenInteractively() and the error is printed.
I have registered my application on the Microsoft app portal, enabled keychain sharing on the capabilities tab of the application etc, not really sure why this won't work..
thanks for any help.
import UIKit
import MSAL
class ViewController: UIViewController, UITextFieldDelegate, URLSessionDelegate
// Update the below to your client ID you received in the portal. The below is for running the demo only
let kClientID = "a88969f1-61c7-4322-a9a0-9212bb96b782"
// These settings you don't need to edit unless you wish to attempt deeper scenarios with the app.
let kGraphURI = "https://graph.microsoft.com/v1.0/me/"
//let kScopes: [String] = ["https://graph.microsoft.com/user.read"]
let kAuthority = "https://login.microsoftonline.com/common"
var accessToken = String()
var applicationContext : MSALPublicClientApplication?
@IBOutlet weak var connectButton: UIButton!
@IBOutlet weak var signoutButton: UIButton!
@IBOutlet weak var loggingText: UITextView!
@IBAction func connectButtonTapped(_ sender: UIButton)
print("Connect button tapped")
if self.currentAccount() == nil
// 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()
else
self.acquireTokenSilently()
@IBAction func signoutButtonTapped(_ sender: UIButton)
print("Signout button tapped")
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
*/
try applicationContext.remove(account)
self.loggingText.text = ""
self.signoutButton.isEnabled = false
catch let error as NSError
self.loggingText.text = "Received error signing account out: (error)"
/**
Setup public client application in viewDidLoad
*/
override func viewDidLoad()
super.viewDidLoad()
do
/**
Initialize a MSALPublicClientApplication with a given clientID and authority
- clientId: The clientID of your application, you should get this from the app portal.
- authority: A URL indicating a directory that MSAL can use to obtain tokens. In Azure AD
it is of the form https://<instance/<tenant>, where <instance> is the
directory host (e.g. https://login.microsoftonline.com) and <tenant> is a
identifier within the directory itself (e.g. a domain associated to the
tenant, such as contoso.onmicrosoft.com, or the GUID representing the
TenantID property of the directory)
- error The error that occurred creating the application object, if any, if you're
not interested in the specific error pass in nil.
*/
guard let authorityURL = URL(string: kAuthority) else
self.loggingText.text = "Unable to create authority URL"
return
let authority = try MSALAuthority(url: authorityURL)
self.applicationContext = try MSALPublicClientApplication(clientId: kClientID, authority: authority)
catch let error
self.loggingText.text = "Unable to create Application Context (error)"
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
signoutButton.isEnabled = !self.accessToken.isEmpty
/**
This button will invoke the authorization flow.
*/
@IBAction func callGraphButton(_ sender: UIButton)
if self.currentAccount() == nil
// 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()
else
self.acquireTokenSilently()
func getContentWithToken()
// Specify the Graph API endpoint
let url = URL(string: kGraphURI)
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.loggingText.text = "Couldn't get graph result: (error)"
return
guard let result = try? JSONSerialization.jsonObject(with: data!, options: ) else
self.loggingText.text = "Couldn't deserialize result JSON"
return
self.loggingText.text = "Result from Graph: (result))"
.resume()
func acquireTokenInteractively()
guard let applicationContext = self.applicationContext else return
applicationContext.acquireToken(forScopes: ApplicationConstants.kScopes) (result, error) in
if let error = error
self.loggingText.text = "Could not acquire token: (error)"
return
guard let result = result else
self.loggingText.text = "Could not acquire token: No result returned"
return
self.accessToken = result.accessToken
self.loggingText.text = "Access token is (self.accessToken)"
self.signoutButton.isEnabled = true
self.getContentWithToken()
func acquireTokenSilently()
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.
*/
applicationContext.acquireTokenSilent(forScopes: ApplicationConstants.kScopes, account: self.currentAccount()!) (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
&& nsError.code == MSALErrorCode.interactionRequired.rawValue)
DispatchQueue.main.async
self.acquireTokenInteractively()
else
self.loggingText.text = "Could not acquire token silently: (error)"
return
guard let result = result else
self.loggingText.text = "Could not acquire token: No result returned"
return
self.accessToken = result.accessToken
self.loggingText.text = "Refreshed Access token is (self.accessToken)"
self.signoutButton.isEnabled = true
self.getContentWithToken()
func currentAccount() -> MSALAccount?
guard let applicationContext = self.applicationContext else return nil
// We retrieve our current account by getting the first account from cache
// In multi-account applications, account should be retrieved by home account identifier or username instead
do
let cachedAccounts = try applicationContext.allAccounts()
if !cachedAccounts.isEmpty
return cachedAccounts.first
catch let error as NSError
self.loggingText.text = "Didn't find any accounts in cache: (error)"
return nil
//
struct ApplicationConstants
static let ResourceId = "https://graph.microsoft.com"
static let kAuthority = "https://login.microsoftonline.com/common/oauth2/v2.0"
static let kGraphURI = "https://graph.microsoft.com/v1.0/me/"
static let kScopes = ["https://graph.microsoft.com/Mail.ReadWrite",
"https://graph.microsoft.com/Mail.Send",
"https://graph.microsoft.com/Files.ReadWrite",
"https://graph.microsoft.com/User.ReadBasic.All"]
static var kClientID = "6d5a8e6d-0281-4003-8feb-43a9ca39d4d2"
enum MSGraphError: Error
case nsErrorType(error: NSError)
ios xcode microsoft-graph keychain msal
1
The error code indicates that you haven't correctly added the adalcache keychain sharing item
– Paulw11
Nov 14 '18 at 11:59
This problem is also referenced specifically here github.com/AzureAD/microsoft-authentication-library-for-objc/…
– Paulw11
Nov 14 '18 at 12:06
Any solutions for this?
– Liam
Nov 14 '18 at 12:48
1
As well as enabling keychain sharing, did you addcom.microsoft.adalcache
as a keychain identifier?
– Paulw11
Nov 14 '18 at 18:34
@Paulw11 that fixed it.. couldn't see that part of configuration on any of the steps in the documentation available! Thanks..
– Liam
Nov 14 '18 at 23:56
add a comment |
I am trying to integrate with Microsoft Graph in my iOS application. I am developing in Swift on XCode. I followed this tutorial:
https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-ios#register-your-application
When I click connect, enter my login details, It keeps giving me the error message below. I have tried debugging and it goes into the acquireTokenInteractively() and the error is printed.
I have registered my application on the Microsoft app portal, enabled keychain sharing on the capabilities tab of the application etc, not really sure why this won't work..
thanks for any help.
import UIKit
import MSAL
class ViewController: UIViewController, UITextFieldDelegate, URLSessionDelegate
// Update the below to your client ID you received in the portal. The below is for running the demo only
let kClientID = "a88969f1-61c7-4322-a9a0-9212bb96b782"
// These settings you don't need to edit unless you wish to attempt deeper scenarios with the app.
let kGraphURI = "https://graph.microsoft.com/v1.0/me/"
//let kScopes: [String] = ["https://graph.microsoft.com/user.read"]
let kAuthority = "https://login.microsoftonline.com/common"
var accessToken = String()
var applicationContext : MSALPublicClientApplication?
@IBOutlet weak var connectButton: UIButton!
@IBOutlet weak var signoutButton: UIButton!
@IBOutlet weak var loggingText: UITextView!
@IBAction func connectButtonTapped(_ sender: UIButton)
print("Connect button tapped")
if self.currentAccount() == nil
// 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()
else
self.acquireTokenSilently()
@IBAction func signoutButtonTapped(_ sender: UIButton)
print("Signout button tapped")
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
*/
try applicationContext.remove(account)
self.loggingText.text = ""
self.signoutButton.isEnabled = false
catch let error as NSError
self.loggingText.text = "Received error signing account out: (error)"
/**
Setup public client application in viewDidLoad
*/
override func viewDidLoad()
super.viewDidLoad()
do
/**
Initialize a MSALPublicClientApplication with a given clientID and authority
- clientId: The clientID of your application, you should get this from the app portal.
- authority: A URL indicating a directory that MSAL can use to obtain tokens. In Azure AD
it is of the form https://<instance/<tenant>, where <instance> is the
directory host (e.g. https://login.microsoftonline.com) and <tenant> is a
identifier within the directory itself (e.g. a domain associated to the
tenant, such as contoso.onmicrosoft.com, or the GUID representing the
TenantID property of the directory)
- error The error that occurred creating the application object, if any, if you're
not interested in the specific error pass in nil.
*/
guard let authorityURL = URL(string: kAuthority) else
self.loggingText.text = "Unable to create authority URL"
return
let authority = try MSALAuthority(url: authorityURL)
self.applicationContext = try MSALPublicClientApplication(clientId: kClientID, authority: authority)
catch let error
self.loggingText.text = "Unable to create Application Context (error)"
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
signoutButton.isEnabled = !self.accessToken.isEmpty
/**
This button will invoke the authorization flow.
*/
@IBAction func callGraphButton(_ sender: UIButton)
if self.currentAccount() == nil
// 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()
else
self.acquireTokenSilently()
func getContentWithToken()
// Specify the Graph API endpoint
let url = URL(string: kGraphURI)
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.loggingText.text = "Couldn't get graph result: (error)"
return
guard let result = try? JSONSerialization.jsonObject(with: data!, options: ) else
self.loggingText.text = "Couldn't deserialize result JSON"
return
self.loggingText.text = "Result from Graph: (result))"
.resume()
func acquireTokenInteractively()
guard let applicationContext = self.applicationContext else return
applicationContext.acquireToken(forScopes: ApplicationConstants.kScopes) (result, error) in
if let error = error
self.loggingText.text = "Could not acquire token: (error)"
return
guard let result = result else
self.loggingText.text = "Could not acquire token: No result returned"
return
self.accessToken = result.accessToken
self.loggingText.text = "Access token is (self.accessToken)"
self.signoutButton.isEnabled = true
self.getContentWithToken()
func acquireTokenSilently()
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.
*/
applicationContext.acquireTokenSilent(forScopes: ApplicationConstants.kScopes, account: self.currentAccount()!) (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
&& nsError.code == MSALErrorCode.interactionRequired.rawValue)
DispatchQueue.main.async
self.acquireTokenInteractively()
else
self.loggingText.text = "Could not acquire token silently: (error)"
return
guard let result = result else
self.loggingText.text = "Could not acquire token: No result returned"
return
self.accessToken = result.accessToken
self.loggingText.text = "Refreshed Access token is (self.accessToken)"
self.signoutButton.isEnabled = true
self.getContentWithToken()
func currentAccount() -> MSALAccount?
guard let applicationContext = self.applicationContext else return nil
// We retrieve our current account by getting the first account from cache
// In multi-account applications, account should be retrieved by home account identifier or username instead
do
let cachedAccounts = try applicationContext.allAccounts()
if !cachedAccounts.isEmpty
return cachedAccounts.first
catch let error as NSError
self.loggingText.text = "Didn't find any accounts in cache: (error)"
return nil
//
struct ApplicationConstants
static let ResourceId = "https://graph.microsoft.com"
static let kAuthority = "https://login.microsoftonline.com/common/oauth2/v2.0"
static let kGraphURI = "https://graph.microsoft.com/v1.0/me/"
static let kScopes = ["https://graph.microsoft.com/Mail.ReadWrite",
"https://graph.microsoft.com/Mail.Send",
"https://graph.microsoft.com/Files.ReadWrite",
"https://graph.microsoft.com/User.ReadBasic.All"]
static var kClientID = "6d5a8e6d-0281-4003-8feb-43a9ca39d4d2"
enum MSGraphError: Error
case nsErrorType(error: NSError)
ios xcode microsoft-graph keychain msal
I am trying to integrate with Microsoft Graph in my iOS application. I am developing in Swift on XCode. I followed this tutorial:
https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-ios#register-your-application
When I click connect, enter my login details, It keeps giving me the error message below. I have tried debugging and it goes into the acquireTokenInteractively() and the error is printed.
I have registered my application on the Microsoft app portal, enabled keychain sharing on the capabilities tab of the application etc, not really sure why this won't work..
thanks for any help.
import UIKit
import MSAL
class ViewController: UIViewController, UITextFieldDelegate, URLSessionDelegate
// Update the below to your client ID you received in the portal. The below is for running the demo only
let kClientID = "a88969f1-61c7-4322-a9a0-9212bb96b782"
// These settings you don't need to edit unless you wish to attempt deeper scenarios with the app.
let kGraphURI = "https://graph.microsoft.com/v1.0/me/"
//let kScopes: [String] = ["https://graph.microsoft.com/user.read"]
let kAuthority = "https://login.microsoftonline.com/common"
var accessToken = String()
var applicationContext : MSALPublicClientApplication?
@IBOutlet weak var connectButton: UIButton!
@IBOutlet weak var signoutButton: UIButton!
@IBOutlet weak var loggingText: UITextView!
@IBAction func connectButtonTapped(_ sender: UIButton)
print("Connect button tapped")
if self.currentAccount() == nil
// 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()
else
self.acquireTokenSilently()
@IBAction func signoutButtonTapped(_ sender: UIButton)
print("Signout button tapped")
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
*/
try applicationContext.remove(account)
self.loggingText.text = ""
self.signoutButton.isEnabled = false
catch let error as NSError
self.loggingText.text = "Received error signing account out: (error)"
/**
Setup public client application in viewDidLoad
*/
override func viewDidLoad()
super.viewDidLoad()
do
/**
Initialize a MSALPublicClientApplication with a given clientID and authority
- clientId: The clientID of your application, you should get this from the app portal.
- authority: A URL indicating a directory that MSAL can use to obtain tokens. In Azure AD
it is of the form https://<instance/<tenant>, where <instance> is the
directory host (e.g. https://login.microsoftonline.com) and <tenant> is a
identifier within the directory itself (e.g. a domain associated to the
tenant, such as contoso.onmicrosoft.com, or the GUID representing the
TenantID property of the directory)
- error The error that occurred creating the application object, if any, if you're
not interested in the specific error pass in nil.
*/
guard let authorityURL = URL(string: kAuthority) else
self.loggingText.text = "Unable to create authority URL"
return
let authority = try MSALAuthority(url: authorityURL)
self.applicationContext = try MSALPublicClientApplication(clientId: kClientID, authority: authority)
catch let error
self.loggingText.text = "Unable to create Application Context (error)"
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
signoutButton.isEnabled = !self.accessToken.isEmpty
/**
This button will invoke the authorization flow.
*/
@IBAction func callGraphButton(_ sender: UIButton)
if self.currentAccount() == nil
// 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()
else
self.acquireTokenSilently()
func getContentWithToken()
// Specify the Graph API endpoint
let url = URL(string: kGraphURI)
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.loggingText.text = "Couldn't get graph result: (error)"
return
guard let result = try? JSONSerialization.jsonObject(with: data!, options: ) else
self.loggingText.text = "Couldn't deserialize result JSON"
return
self.loggingText.text = "Result from Graph: (result))"
.resume()
func acquireTokenInteractively()
guard let applicationContext = self.applicationContext else return
applicationContext.acquireToken(forScopes: ApplicationConstants.kScopes) (result, error) in
if let error = error
self.loggingText.text = "Could not acquire token: (error)"
return
guard let result = result else
self.loggingText.text = "Could not acquire token: No result returned"
return
self.accessToken = result.accessToken
self.loggingText.text = "Access token is (self.accessToken)"
self.signoutButton.isEnabled = true
self.getContentWithToken()
func acquireTokenSilently()
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.
*/
applicationContext.acquireTokenSilent(forScopes: ApplicationConstants.kScopes, account: self.currentAccount()!) (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
&& nsError.code == MSALErrorCode.interactionRequired.rawValue)
DispatchQueue.main.async
self.acquireTokenInteractively()
else
self.loggingText.text = "Could not acquire token silently: (error)"
return
guard let result = result else
self.loggingText.text = "Could not acquire token: No result returned"
return
self.accessToken = result.accessToken
self.loggingText.text = "Refreshed Access token is (self.accessToken)"
self.signoutButton.isEnabled = true
self.getContentWithToken()
func currentAccount() -> MSALAccount?
guard let applicationContext = self.applicationContext else return nil
// We retrieve our current account by getting the first account from cache
// In multi-account applications, account should be retrieved by home account identifier or username instead
do
let cachedAccounts = try applicationContext.allAccounts()
if !cachedAccounts.isEmpty
return cachedAccounts.first
catch let error as NSError
self.loggingText.text = "Didn't find any accounts in cache: (error)"
return nil
//
struct ApplicationConstants
static let ResourceId = "https://graph.microsoft.com"
static let kAuthority = "https://login.microsoftonline.com/common/oauth2/v2.0"
static let kGraphURI = "https://graph.microsoft.com/v1.0/me/"
static let kScopes = ["https://graph.microsoft.com/Mail.ReadWrite",
"https://graph.microsoft.com/Mail.Send",
"https://graph.microsoft.com/Files.ReadWrite",
"https://graph.microsoft.com/User.ReadBasic.All"]
static var kClientID = "6d5a8e6d-0281-4003-8feb-43a9ca39d4d2"
enum MSGraphError: Error
case nsErrorType(error: NSError)
ios xcode microsoft-graph keychain msal
ios xcode microsoft-graph keychain msal
edited Nov 14 '18 at 11:12
Liam
asked Nov 14 '18 at 10:49
LiamLiam
120114
120114
1
The error code indicates that you haven't correctly added the adalcache keychain sharing item
– Paulw11
Nov 14 '18 at 11:59
This problem is also referenced specifically here github.com/AzureAD/microsoft-authentication-library-for-objc/…
– Paulw11
Nov 14 '18 at 12:06
Any solutions for this?
– Liam
Nov 14 '18 at 12:48
1
As well as enabling keychain sharing, did you addcom.microsoft.adalcache
as a keychain identifier?
– Paulw11
Nov 14 '18 at 18:34
@Paulw11 that fixed it.. couldn't see that part of configuration on any of the steps in the documentation available! Thanks..
– Liam
Nov 14 '18 at 23:56
add a comment |
1
The error code indicates that you haven't correctly added the adalcache keychain sharing item
– Paulw11
Nov 14 '18 at 11:59
This problem is also referenced specifically here github.com/AzureAD/microsoft-authentication-library-for-objc/…
– Paulw11
Nov 14 '18 at 12:06
Any solutions for this?
– Liam
Nov 14 '18 at 12:48
1
As well as enabling keychain sharing, did you addcom.microsoft.adalcache
as a keychain identifier?
– Paulw11
Nov 14 '18 at 18:34
@Paulw11 that fixed it.. couldn't see that part of configuration on any of the steps in the documentation available! Thanks..
– Liam
Nov 14 '18 at 23:56
1
1
The error code indicates that you haven't correctly added the adalcache keychain sharing item
– Paulw11
Nov 14 '18 at 11:59
The error code indicates that you haven't correctly added the adalcache keychain sharing item
– Paulw11
Nov 14 '18 at 11:59
This problem is also referenced specifically here github.com/AzureAD/microsoft-authentication-library-for-objc/…
– Paulw11
Nov 14 '18 at 12:06
This problem is also referenced specifically here github.com/AzureAD/microsoft-authentication-library-for-objc/…
– Paulw11
Nov 14 '18 at 12:06
Any solutions for this?
– Liam
Nov 14 '18 at 12:48
Any solutions for this?
– Liam
Nov 14 '18 at 12:48
1
1
As well as enabling keychain sharing, did you add
com.microsoft.adalcache
as a keychain identifier?– Paulw11
Nov 14 '18 at 18:34
As well as enabling keychain sharing, did you add
com.microsoft.adalcache
as a keychain identifier?– Paulw11
Nov 14 '18 at 18:34
@Paulw11 that fixed it.. couldn't see that part of configuration on any of the steps in the documentation available! Thanks..
– Liam
Nov 14 '18 at 23:56
@Paulw11 that fixed it.. couldn't see that part of configuration on any of the steps in the documentation available! Thanks..
– Liam
Nov 14 '18 at 23:56
add a comment |
1 Answer
1
active
oldest
votes
You need to ensure you have added the correct identifier to your keychain sharing group. The default value is com.microsoft.adalcache
.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53298417%2fmsal-failed-to-set-item-into-keychain-when-trying-to-authenticate-microsoft-gr%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You need to ensure you have added the correct identifier to your keychain sharing group. The default value is com.microsoft.adalcache
.
add a comment |
You need to ensure you have added the correct identifier to your keychain sharing group. The default value is com.microsoft.adalcache
.
add a comment |
You need to ensure you have added the correct identifier to your keychain sharing group. The default value is com.microsoft.adalcache
.
You need to ensure you have added the correct identifier to your keychain sharing group. The default value is com.microsoft.adalcache
.
answered Nov 15 '18 at 1:16
Paulw11Paulw11
68.7k1086103
68.7k1086103
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53298417%2fmsal-failed-to-set-item-into-keychain-when-trying-to-authenticate-microsoft-gr%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
The error code indicates that you haven't correctly added the adalcache keychain sharing item
– Paulw11
Nov 14 '18 at 11:59
This problem is also referenced specifically here github.com/AzureAD/microsoft-authentication-library-for-objc/…
– Paulw11
Nov 14 '18 at 12:06
Any solutions for this?
– Liam
Nov 14 '18 at 12:48
1
As well as enabling keychain sharing, did you add
com.microsoft.adalcache
as a keychain identifier?– Paulw11
Nov 14 '18 at 18:34
@Paulw11 that fixed it.. couldn't see that part of configuration on any of the steps in the documentation available! Thanks..
– Liam
Nov 14 '18 at 23:56