ASWebAuthenticationSessionの動きを調べてみた

##調べたかったことと結果のまとめ

* ASWebAuthenticationSession はURLスキーマの指定が必要だが、アプリのinfo.plistへの設定は必要か
 * 不要だった。
* 他のアプリのURLスキーマを踏んだら、他のアプリに飛んでしまうか
    * 飛んだ。
* 他のアプリと同じURLスキーマを指定した時、他のアプリに奪われてしまう可能性があるか
    * 大丈夫そう。（多分）

つまり、Webサイト側のRedirect先を間違えなければ、スキーマ自体は他のアプリとかぶっていても大丈夫そう。
むしろ、そうじゃなかったら、危なくて使えない。

### 動画

```callbackURLScheme: "exampleauth"``` にして、``` <a href="exampleauth://auth?token=1234">ログイン</a>```をタップすると、もちろんログインが成功し、URLが取れる。

![astest.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135431/574cc820-4b50-5dc3-bff9-3602c95e4bc9.gif)


そして、```<a href="photos-redirect:">写真を開く</a>```をタップすると、写真アプリに飛んでしまう。

![astest3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135431/a93a96e1-57b5-18e9-ba69-8dc8a4e2c1e2.gif)


```callbackURLScheme: "photos-redirect"``` にして、```<a href="photos-redirect:">写真を開く</a>```をタップすると、ログインが成功し、URLが取れる。（写真アプリに飛ばない）

![astest2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135431/1d0dee19-7dd6-0dba-f85c-cccd8f3551ca.gif)


## サンプルコード

### アプリ
[Appleのサンプルコード](https://developer.apple.com/documentation/authenticationservices/authenticating_a_user_through_a_web_service) や [SwiftUIでASWebAuthenticationSession](https://qiita.com/devdazy/items/baf2c6e5442e1023e041)を参照。

```swift
import SwiftUI
import AuthenticationServices

// https://qiita.com/devdazy/items/baf2c6e5442e1023e041
class AuthPresentationContextProver: NSObject, ASWebAuthenticationPresentationContextProviding {
    private weak var viewController: UIViewController!

    init(viewController: UIViewController) {
        self.viewController = viewController
        super.init()
    }

    func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
        return viewController?.view.window! ?? ASPresentationAnchor()
    }
}

struct ContentView: View {
    @State var text = "ASWebAuthenticaionSession Test"
    @State var session: ASWebAuthenticationSession?
    @State var presentationContextProvider: AuthPresentationContextProver?
    	
    var body: some View {
        VStack {
            Text(text)
            Button(action: authenticate) {
                Text("Login")
            }
            .padding(2.0)
        }
        
    }
    
    func authenticate(){
        text = "button clicked!"
        // Use the URL and callback scheme specified by the authorization provider.
        guard let authURL = URL(string: "https://xn--s7y86k.jp/aslogintestpage2.html") else { return }
        
        let scheme = "exampleauth"
        //let scheme = "photos-redirect"

        // Initialize the session.
         self.session = ASWebAuthenticationSession(url: authURL, callbackURLScheme: scheme)
        { callbackURL, error in
            // Handle the callback.
            if (error != nil) {self.text = error.debugDescription + callbackURL!.absoluteString}
            if (callbackURL != nil){ self.text = callbackURL!.absoluteString}
        }
        let presentationContextProvider = AuthPresentationContextProver(viewController: UIHostingController(rootView: self))
        self.session?.presentationContextProvider = presentationContextProvider
        self.presentationContextProvider = presentationContextProvider
        self.session?.start()
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
```

### Webサイト

```html
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>ログインページのテスト</title>
</head>

<body>

    <h1>ログインページのテスト</h1>

    <DIV class="container">
        <p>ログインしましょう。</p>
        <a href="exampleauth://auth?token=1234">ログイン</a></br></br>
        <a href="line://">LINEを開く</a></br></br>
        <a href="photos-redirect:">写真を開く</a>
    </DIV>

</body>

</html>
```