Swift Xcode中的MSAL集成B2C AD在点击“授权”后无法获取错误

有一些类似的问题,但是没有一个能解决我的问题。

使用Xcode 11.1 MacOS Cataline 10.15

我克隆了此“ active-directory-b2c-ios-swift-native-msal”,并尝试运行以获取错误“无法获取令牌:Error Domain = MSALErrorDomain代码= -50000“(null)” UserInfo = {MSALErrorDescriptionKey =无法启动交互式会话,MSALInternalErrorCodeKey = -42008,MSALCorrelationIDKey = C9207A45-6A7D-416B-90E4-93E08F28A637}” 更改B2C详细信息后,同样的问题变得越来越严重。 请让我知道是什么问题,这是Xcode / OS / MSAL版本的问题还是Code的某些问题?

我尝试使用git repo中的默认配置提及“ active-directory-b2c-ios-swift-native-msal”,还尝试了以下更改,让kTenantName =“ dovervsg.onmicrosoft.com” //您的租户名称     let kClientID =“ xxxxxxxxxxxxxxxxxxxxxxx” //创建应用程序时来自门户的客户端ID     let kSignupOrSigninPolicy =“ B2C_1-policy” //您在门户中创建的注册和登录策略     let kEditProfilePolicy =“ b2c_1_edit_profile” //您在门户网站中创建的编辑策略     let kResetPasswordPolicy =“ B2C_1_reset_password” //您在门户网站中创建的重置密码策略     let kGraphURI =“ https://dev-vsg.dovertech.co.in” //这是您的后端API,已将其配置为接受应用程序的令牌     let kScopes:[String] = [“ https://dovervsg.onmicrosoft.com/User.Read”] //这是您配置了后端API所要查找的作用域。     //也尝试过使用这种范围格式,让kScopes:[String] = [“ https://dovervsg.onmicrosoft.com/api/User.Read”] // //这是您已经配置了后端API来查找的范围。

let kTenantName = "dovervsg.onmicrosoft.com" // Your tenant name
let kClientID = "xxxxxxxxxxxxxxxxxxxxxxx" // Your client ID from the portal when you created your application
let kSignupOrSigninPolicy = "B2C_1-policy" // Your signup and sign-in policy you created in the portal
let kEditProfilePolicy = "b2c_1_edit_profile" // Your edit policy you created in the portal
let kResetPasswordPolicy = "B2C_1_reset_password" // Your reset password policy you created in the portal
let kGraphURI = "https://dev-vsg.dovertech.co.in" // This is your backend API that you've configured to accept your app's tokens
let kScopes: [String] = ["https://dovervsg.onmicrosoft.com/User.Read"] // This is a scope that you've configured your backend API to look for.
// tried with this scope format as well,let kScopes: [String] = ["https://dovervsg.onmicrosoft.com/api/User.Read"] // This is a scope that you've configured your backend API to look for



// DO NOT CHANGE - This is the format of OIDC Token and Authorization endpoints for Azure AD B2C.
let kEndpoint = "https://login.microsoftonline.com/tfp/%@/%@"

var application: MSALPublicClientApplication!

var accessToken: String?

@IBOutlet weak var loggingText: UITextView!
@IBOutlet weak var signoutButton: UIButton!
@IBOutlet weak var callGraphApiButton: UIButton!
@IBOutlet weak var editProfileButton: UIButton!
@IBOutlet weak var refreshTokenButton: UIButton!

override func viewDidAppear(_ animated: Bool) {

    //super.viewDidLoad()

              do {
                  /**

                   Initialize a MSALPublicClientApplication with a MSALPublicClientApplicationconfig.
                   MSALPublicClientApplicationconfig can be initialized with client id,redirect uri and authority.
                   Redirect uri will be constucted automatically in the form of "msal<your-client-id-here>://auth" if not provided.
                   The scheme part,i.e. "msal<your-client-id-here>",needs to be registered in the info.plist of the project
                   */

                  let authority = try self.getauthority(forPolicy: self.kSignupOrSigninPolicy)

                  // Provide configuration for MSALPublicClientApplication
                  // MSAL will use default redirect uri when you provide nil
                  let pcaConfig = MSALPublicClientApplicationconfig(clientId: kClientID,redirecturi: nil,authority: authority)
                  self.application = try MSALPublicClientApplication(configuration: pcaConfig)
              } catch {
                  self.updateLoggingText(text: "Unable to create application \(error)")
              }
}

/**
 This button will invoke the authorization flow and send the policy specified to the B2C server.
 Here we are using the `kSignupOrSignInPolicy` to sign the user in to the app. We will store this 
 accessToken for subsequent calls.
 */




@IBaction func authorizationButton(_ sender: UIButton) {
    do {
        /**

         authority is a URL indicating a directory that MSAL can use to obtain tokens. In Azure B2C
         it is of the form `https://<instance/tfp/<tenant>/<policy>`,where `<instance>` is the
         directory host (e.g. https://login.microsoftonline.com),`<tenant>` is a
         identifier within the directory itself (e.g. a domain associated to the
         tenant,such as contoso.onmicrosoft.com),and `<policy>` is the policy you wish to
         use for the current user flow.

         */

        let authority = try self.getauthority(forPolicy: self.kSignupOrSigninPolicy)

        /**
         Acquire a token for a new account using interactive authentication

         - scopes: Permissions you want included in the access token received
         in the result in the completionBlock. Not all scopes are
         gauranteed to be included in the access token returned.
         - completionBlock: The completion block that will be called when the authentication
         flow completes,or encounters an error.
         */

        let webViewParameters = MSALWebviewParameters(parentViewController: self)
        let parameters = MSALInteractiveTokenParameters(scopes: kScopes,webviewParameters: webViewParameters)
        parameters.promptType = .selectaccount
        print( parameters.promptType = .selectaccount)
        parameters.authority = authority
         debugPrint(  parameters.authority = authority)
        application.acquireToken(with: parameters) { (result,error) in

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

            self.accessToken = result.accessToken
            self.updateLoggingText(text: "access token is \(self.accessToken ?? "Empty")")
            self.signoutButton.isEnabled = true
            self.callGraphApiButton.isEnabled = true
            self.editProfileButton.isEnabled = true
            self.refreshTokenButton.isEnabled = true
        }
    } catch {
        self.updateLoggingText(text: "Unable to create authority \(error)")
    }
}

@IBaction func editProfile(_ sender: UIButton) {
    do {

        /**

         authority is a URL indicating a directory that MSAL can use to obtain tokens. In Azure B2C
         it is of the form `https://<instance/tfp/<tenant>/<policy>`,and `<policy>` is the policy you wish to
         use for the current user flow.

         */

        let authority = try self.getauthority(forPolicy: self.kEditProfilePolicy)

        /**
         Acquire a token for a new account using interactive authentication

         - scopes: Permissions you want included in the access token received
         in the result in the completionBlock. Not all scopes are
         gauranteed to be included in the access token returned.
         - completionBlock: The completion block that will be called when the authentication
         flow completes,or encounters an error.
         */

        let thisaccount = try self.getaccountByPolicy(withaccounts: application.allaccounts(),policy: kEditProfilePolicy)
        let webViewParameters = MSALWebviewParameters(parentViewController: self)
        let parameters = MSALInteractiveTokenParameters(scopes: kScopes,webviewParameters: webViewParameters)
        parameters.authority = authority
        parameters.account = thisaccount

        application.acquireToken(with: parameters) { (result,error) in
            if let error = error {
                self.updateLoggingText(text: "Could not edit profile: \(error)")
            } else {
                self.updateLoggingText(text: "Successfully edited profile")
            }
        }
    } catch {
        self.updateLoggingText(text: "Unable to construct parameters before calling acquire token \(error)")
    }
}

@IBaction func refreshToken(_ sender: UIButton) {

    do {
        /**

         authority is a URL indicating a directory that MSAL can use to obtain tokens. In Azure B2C
         it is of the form `https://<instance/tfp/<tenant>/<policy>`,and `<policy>` is the policy you wish to
         use for the current user flow.

         */

        let authority = try self.getauthority(forPolicy: self.kSignupOrSigninPolicy)

        /**

         Acquire a token for an existing account silently

         - scopes: Permissions you want included in the access token received
         in the result in the completionBlock. Not all scopes are
         gauranteed 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.
         */

        guard let thisaccount = try self.getaccountByPolicy(withaccounts: application.allaccounts(),policy: kSignupOrSigninPolicy) else {
            self.updateLoggingText(text: "There is no account available!")
            return
        }

        let parameters = MSALSilentTokenParameters(scopes: kScopes,account:thisaccount)
        parameters.authority = authority
        self.application.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) {

                        // Notice we supply the account here. This ensures we acquire token for the same account
                        // as we originally authenticated.

                        let webviewParameters = MSALWebviewParameters(parentViewController: self)
                        let parameters = MSALInteractiveTokenParameters(scopes: self.kScopes,webviewParameters: webviewParameters)
                        parameters.account = thisaccount

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

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

                            self.accessToken = result.accessToken
                            self.updateLoggingText(text: "access token is \(self.accessToken ?? "empty")")
                        }
                        return
                    }
                }

                self.updateLoggingText(text: "Could not acquire token: \(error)")
                return
            }

            guard let result = result else {

                self.updateLoggingText(text: "Could not acquire token: No result returned")
                return
            }

            self.accessToken = result.accessToken
            self.updateLoggingText(text: "Refreshing token silently")
            self.updateLoggingText(text: "Refreshed access token is \(self.accessToken ?? "empty")")
        }
    } catch {
        self.updateLoggingText(text: "Unable to construct parameters before calling acquire token \(error)")
    }
}

@IBaction func callApi(_ sender: UIButton) {
    guard let accessToken = self.accessToken else {
        self.updateLoggingText(text: "Operation failed because could not find an access token!")
        return
    }

    let sessionconfig = URLSessionconfiguration.default
    sessionconfig.timeoutIntervalForRequest = 30
    let url = URL(string: self.kGraphURI)
    var request = URLRequest(url: url!)
    request.setvalue("Bearer \(accessToken)",forHTTPHeaderField: "Authorization")
    let urlSession = URLSession(configuration: sessionconfig,delegate: self,delegateQueue: OperationQueue.main)

    self.updateLoggingText(text: "Calling the API....")

    urlSession.dataTask(with: request) { data,response,error in
        guard let validData = data else {
            self.updateLoggingText(text: "Could not call API: \(error ?? "No error informarion" as! Error)")
            return
        }

        let result = try? JSONSerialization.jsonObject(with: validData,options: [])

        guard let validResult = result as? [String: Any] else {
            self.updateLoggingText(text: "Nothing returned from API")
            return
        }

        self.updateLoggingText(text: "API response: \(validResult.debugDescription)")
        }.resume()
}

@IBaction func signoutButton(_ sender: UIButton) {
    do {
        /**
         Removes all tokens from the cache for this application for the provided account

         - account:    The account to remove from the cache
         */

        let thisaccount = try self.getaccountByPolicy(withaccounts: application.allaccounts(),policy: kSignupOrSigninPolicy)

        if let accountToRemove = thisaccount {
            try application.remove(accountToRemove)
        } else {
            self.updateLoggingText(text: "There is no account to signing out!")
        }

        self.signoutButton.isEnabled = false
        self.callGraphApiButton.isEnabled = false
        self.editProfileButton.isEnabled = false
        self.refreshTokenButton.isEnabled = false

        self.updateLoggingText(text: "Signed out")

    } catch  {
        self.updateLoggingText(text: "Received error signing out: \(error)")
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

override func viewWillAppear(_ animated: Bool) {

    if self.accessToken == nil {
        signoutButton.isEnabled = false
        callGraphApiButton.isEnabled = false
        editProfileButton.isEnabled = false
        refreshTokenButton.isEnabled = false
    }
}

func getaccountByPolicy (withaccounts accounts: [MSALaccount],policy: String) throws -> MSALaccount? {

    for account in accounts {
        // This is a single account sample,so we only check the suffic part of the object id,// where object id is in the form of <object id>-<policy>.
        // For multi-account apps,the whole object id needs to be checked.
        if let homeaccountId = account.homeaccountId,let objectId = homeaccountId.objectId {
            if objectId.hasSuffix(policy.lowercased()) {
                return account
            }
        }
    }
    return nil
}

/**

 The way B2C knows what actions to perform for the user of the app is through the use of `Authority URL`.
 It is of the form `https://<instance/tfp/<tenant>/<policy>`,where `<instance>` is the
 directory host (e.g. https://login.microsoftonline.com),`<tenant>` is a
 identifier within the directory itself (e.g. a domain associated to the
 tenant,and `<policy>` is the policy you wish to
 use for the current user flow.
 */
func getauthority(forPolicy policy: String) throws -> MSALB2CAuthority {
    guard let authorityURL = URL(string: String(format: self.kEndpoint,self.kTenantName,policy)) else {
        throw NSError(domain: "SomeDomain",code: 1,userInfo: ["errorDescription": "Unable to create authority URL!"])
    }
    return try MSALB2CAuthority(url: authorityURL)
}

func updateLoggingText(text: String) {
    DispatchQueue.main.async{
        self.loggingText.text = text
    }
}

}

运行后出现以上错误

longsheng923123 回答:Swift Xcode中的MSAL集成B2C AD在点击“授权”后无法获取错误

sample已更新,现在应该可以正常工作。现在,它已更新为处理*.b2clogin.com,现在将sui_si并编辑配置文件添加到已知的权限列表中。


let siginPolicyAuthority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)
            let editProfileAuthority = try self.getAuthority(forPolicy: self.kEditProfilePolicy)

            // Provide configuration for MSALPublicClientApplication
            // MSAL will use default redirect uri when you provide nil
            let pcaConfig = MSALPublicClientApplicationConfig(clientId: kClientID,redirectUri: nil,authority: siginPolicyAuthority)
            pcaConfig.knownAuthorities = [siginPolicyAuthority,editProfileAuthority]
            self.application = try MSALPublicClientApplication(configuration: pcaConfig)

 func getAuthority(forPolicy policy: String) throws -> MSALB2CAuthority {
        guard let authorityURL = URL(string: String(format: self.kEndpoint,self.kAuthorityHostName,self.kTenantName,policy)) else {
            throw NSError(domain: "SomeDomain",code: 1,userInfo: ["errorDescription": "Unable to create authority URL!"])
        }
        return try MSALB2CAuthority(url: authorityURL)
    }

本文链接:https://www.f2er.com/3124815.html

大家都在问