Ios MSAL库在没有响应的情况下登录

Ios MSAL库在没有响应的情况下登录,ios,swift,xcode,outlook,msal,Ios,Swift,Xcode,Outlook,Msal,我正在尝试一个能够为Outlook日历显示所有事件并创建新事件的应用程序。我正在使用MSAL库获取身份验证代码。问题是,尽管当我触摸“输入”或“取消”按钮时出现登录屏幕,但我没有注意到任何反应。这是我的代码: class OutlookManagerController: BaseViewController { let oClientKey = "a07745a5-3b90-4385-a2b2-8223dbf68688" let authScopes = ["openid+ht

我正在尝试一个能够为Outlook日历显示所有事件并创建新事件的应用程序。我正在使用MSAL库获取身份验证代码。问题是,尽管当我触摸“输入”或“取消”按钮时出现登录屏幕,但我没有注意到任何反应。这是我的代码:

class OutlookManagerController: BaseViewController {
    let oClientKey = "a07745a5-3b90-4385-a2b2-8223dbf68688"
    let authScopes = ["openid+https://outlook.office.com/contacts.read+offline_access"]

    func getAcessToken(){
        if let application = try? MSALPublicClientApplication.init(clientId: oClientKey) {
            application.acquireToken(forScopes: authScopes) { (result, error) in
                if result != nil {
                    let userToken = result!.accessToken!
                    print(userToken)

                } else {
                    print(error!.localizedDescription)
                }
            }
        }
        else {
            print("Unable to create application.")
        }
    }
}

似乎您没有监听MSAL在调用
AcquireToken()
时启动的
SFSafariViewController
的身份验证代码返回。MSAL使用
SFSafariViewController
进行登录,以实现更好的安全性,并提供跨应用程序的单点登录。您只需要设置一个重定向URI,该URI能够回调您的应用程序并为您的租户使用正确的颁发者

这就是你遇到的问题。登录成功,但Azure无法找到返回到您的应用程序的路径

首先,一些基础工作

系统网络视图 大多数现代OAuth2库现在使用系统Webview来登录用户。系统web视图是一个浏览器组件,应用程序可以启动该组件,该组件看起来是应用程序的一部分,但实际上是一个运行操作系统web浏览器的独立进程。对于iOS来说,这是最新版本,而在Android上则是如此

在中为用户唱歌的系统Webview的好处很多,包括:

  • 更好的安全性。应用程序无法访问在系统Webview中键入的凭据,因为它是一个独立的浏览器进程

    今天,许多应用程序使用用户名和密码表单或嵌入式webview来获取凭据。这允许应用程序监听并获取这些凭据。许多公司已经开始禁止具有此类登录的应用程序。系统网络视图可确保您的应用程序不会出现此问题

  • 单点登录。一旦用户使用系统Webview登录,浏览器中将放置一个cookie,该帐户可用于任何应用程序,从而防止用户需要单独登录每个应用程序

    随着越来越多的消费者和企业利用手机短信和其他因素作为附加步骤,不得不重复这一步骤以及使用您的密码对客户来说变得非常烦人。系统Web视图可消除此问题

  • 更好的控制。用户可以选择提供应用程序的帐户,或者在系统Webview中添加一个全新的帐户(如果支持)
你已经看到谷歌和微软通过我们最新的SDK和更新我们的身份服务向这个系统Webview过渡,这是为了给客户提供这些保护和功能。OpenID项目的AppAuth也提供了这种支持。OpenID项目的代码由谷歌和微软的工程师提供

系统Webview需要返回到您的应用程序 阅读上述内容时,您可能会想到以下几点:

如果某个应用程序现在调用系统Webview进行登录,但对其没有控制权,如何从系统Webview获取所需的令牌?

答案是,您必须利用每个操作系统回调应用程序的机制,然后使用OAuth2协议中的
重定向URI
,使用该机制将响应返回给该应用程序。这几乎与web浏览器中的工作原理完全相同。您将从网站重定向到身份提供商进行登录,然后身份提供商使用
redirectURI
将用户返回到网站,并在响应中的某处添加令牌

对于iOS,这是通过自定义URL方案完成的。URL方案的格式为
CFBundleURLScheme:\\CFBundleURLSchemes
,定义为:

  • CFBundleURLName 包含URL方案的抽象名称的字符串。为确保唯一性,建议您指定标识符的反向DNS样式,例如com.acme.myscheme。 您指定的字符串也用作应用程序的InfoPlist.strings文件中的密钥。密钥的值是人类可读的方案名称
  • CbundleurlSchemes 包含URL方案名称的字符串数组,例如http、mailto、tel和sms
要注册应用程序的URL类型,请在应用程序的
Info.plist
文件中包含
CFBundleURLTypes
键。
CFBundleURLTypes
键包含一个字典数组,每个字典定义了应用程序支持的URL方案

如何让系统网络视图返回应用程序 因此,结合这两件事,您需要做的事情相当简单:

  • 找出你的应用程序的URL方案(例如
    appauth://abc123
  • 告诉Azure AD您的新URL方案是什么,将其添加为应用程序的另一个
    重定向URI
  • 配置应用程序以侦听此URL方案并启动应用程序
  • 配置应用程序本身,以便在此URL方案启动您的应用程序后获取令牌(app Auth,以及我们自己的MSAL库,为您执行此操作!)
  • 1.确定应用程序的URL方案 您可以从Apple的应用程序间通信文档中了解如何创建URL方案,但我们建议您使用
    appauth://
    (例如
    appauth://ab032846-efee-481f-b6bc-493aae92c432

    2.告诉Azure AD你的新URL方案是什么 你需要将此URL方案作为重定向URI添加到你的应用程序中。这很容易。只需访问并选择你的应用程序。在
    本机应用程序下向下滚动到自定义应用程序URI,然后添加新的重定向URI

    3.配置应用程序以侦听此URL方案 根据Ap将以下内容添加到您的
    info.plist
    文件中
    func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
        MSALPublicClientApplication.handleMSALResponse(url)
        return true
    }
    
      <key>CFBundleURLTypes</key>
        <array>
            <dict>
                <key>CFBundleTypeRole</key>
                <string>Editor</string>
                <key>CFBundleURLName</key>
                <string>ab032846-efee-481f-b6bc-493aae92c432</string>
                <key>CFBundleURLSchemes</key>
                <array>
                    <string>app-auth</string>
                </array>
            </dict>
        </array>
    
    func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
    
        print("Received callback!")
    
        MSALPublicClientApplication.handleMSALResponse(url)
    
    
        return true
    }