{"id":300,"date":"2020-03-05T02:41:26","date_gmt":"2020-03-04T17:41:26","guid":{"rendered":"http:\/\/milennium9.godohosting.com\/wordpress\/?p=300"},"modified":"2020-03-05T19:24:38","modified_gmt":"2020-03-05T10:24:38","slug":"unity-apple-login%ea%b3%bc-firebase-%ec%9d%b8%ec%a6%9d","status":"publish","type":"post","link":"http:\/\/milennium9.godohosting.com\/wordpress\/?p=300","title":{"rendered":"[Unity] Apple Login\uacfc Firebase \uc778\uc99d"},"content":{"rendered":"\n<p>Apple\uc774 \uc775\uba85 \ub85c\uadf8\uc778 \uae30\ub2a5\ub9cc \uc0ac\uc6a9\ud560\uac8c \uc544\ub2c8\ub77c\uba74 Apple Login\uc744 \uc758\ubb34\ud654 \ud558\uc600\uae30 \ub54c\ubb38\uc5d0 Apple Login\uc744 \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uc73c\uba74 \ub9ac\uc81d\uc744 \ub2f9\ud558\uac8c \ub429\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uadf8\ub798\uc11c Apple Login\uc744 \ud504\ub85c\uc81d\ud2b8\uc5d0 \ucd94\uac00\ud558\ub294 \uacfc\uc815\uc744 \uac04\ub7b5\ud558\uac8c \ub0a8\uae41\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uc6b0\uc120 Unity\uc5d0\uc11c \uc560\ud50c \ub85c\uadf8\uc778\uc744 \uc9c0\uc6d0\ud558\ub294 \ud50c\ub7ec\uadf8\uc778\uc774 \ub450 \uac00\uc9c0\uac00 \uc788\uc2b5\ub2c8\ub2e4.<br>\uccab\ubc88\uc9f8\ub294 Unity Technology\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 SignInWithApple \uc785\ub2c8\ub2e4. <br><a href=\"https:\/\/assetstore.unity.com\/packages\/tools\/sign-in-with-apple-154202\">https:\/\/assetstore.unity.com\/packages\/tools\/sign-in-with-apple-154202<\/a> <br><br>\ub450\ubc88\uc9f8\ub294 GitHub\uc5d0 \uc62c\ub77c\uc640 \uc788\ub294 AppleAuth \uc785\ub2c8\ub2e4.<br><a href=\"https:\/\/github.com\/lupidan\/apple-signin-unity\">https:\/\/github.com\/lupidan\/apple-signin-unity<\/a> <\/p>\n\n\n\n<p>\ub2f9\uc5f0\ud788 \ucc98\uc74c\uc5d0\ub294 Unity\uc5d0\uc11c \uc81c\uacf5\ud574 \uc8fc\ub294 \ud50c\ub7ec\uadf8\uc778\uc744 \uc0ac\uc6a9\ud558\uc5ec \uad6c\ud604\uc744 \uc9c4\ud589\ud558\uc600\uace0 Apple Login\uc774 \ubb38\uc81c\uc5c6\uc774 \ub3d9\uc791\ud558\ub294 \uac83\uc744 \ud655\uc778\ud558\uc600\uc73c\ub098 Firebase \uc778\uc99d \ub2e8\uacc4\uc5d0\uc11c \ubcbd\uc5d0 \ubd80\ub52a\ud614\uc2b5\ub2c8\ub2e4.<br>Firebase \uc778\uc99d \ub2e8\uacc4\uc5d0\uc11c Apple Login\uc758 \uac80\uc99d\uc744 \uc704\ud574 nonce\ub97c \uc694\uad6c\ud558\ub294\ub370, SignInWithApple\uc740 Nonce\uc744 \uc5bb\uc5b4\uc624\ub294 API\uac00 \uc81c\uacf5\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4.<br>(\ud604\uc7ac \uc2dc\uc810\uc5d0 \uc81c\uac00 \ubc1c\uacac\ud558\uc9c0 \ubabb\ud588\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4.)<br>\uadf8\ub798\uc11c \ub208\ubb3c\uc744 \uba38\uae08\uace0 \ucf54\ub4dc\ub97c \ub0a0\ub9b0 \ub4a4 AppleAuth\ub97c \ud1b5\ud574 \uad6c\ud604\uc744 \uc9c4\ud589\ud588\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">AppleAuth \uc124\uce58<\/h2>\n\n\n\n<p>GitHub\uc758 \uc124\uba85\ub300\ub85c \uc9c4\ud589\ud558\uba74 \ub429\ub2c8\ub2e4.<br>\uc800\ub294 2018.4 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0 Packages\/manifest.json \ud30c\uc77c\uc744 \uc5f4\uc5b4 \uc544\ub798\uc758 \ud328\ud0a4\uc9c0\ub97c \ucd94\uac00\ud574 \uc90d\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\"dependencies\": {\n    \"com.lupidan.apple-signin-unity\": \"https:\/\/github.com\/lupidan\/apple-signin-unity.git#v1.1.0\",\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">AppleAuthorizer \uad6c\ud604<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>using AppleAuth;\n\npublic class AppleAuthorizer {\n    \/\/ \ucde8\ud5a5 \uc0c1 \uc2f1\uae00\ud134\uc744 \uc0ac\uc6a9\ud569\ub2c8\ub2e4.\n    public static AppleAuthorizer instance {get; private set;}\n\n    public static string IdToken {get; private set;}\n    public static string AuthCode {get; private set;}\n    public static string RawNonce {get; private set;}\n    public static string Nonce {get; private set;}\n\n    private IAppleAuthManager appleAuthManager;\n    public bool IsLoginSuccess = false;\n    public bool IsLoginDone = false;\n\n    private void Awake() {\n        if( _instance == null &amp;&amp; _instance != this) {\n            Destroy(gameObject);\n            return;\n        }\n        _instance = this;\n        DontDestroyOnLoad(gameObject);\n    }\n    private void Start() {\n        if(AppleAuthManager.IsCurrentPlatformSupported) {\n            var deserializer = new PayloadDeserializer();\n            appleAuthManager = new AppleAuthManager(deserializer);\n        }\n    }\n    private void Update() {\n        appleAuthManager?.Update();\n    }\n\n    \/\/ Nonce\ub294 SHA256\uc73c\ub85c \ub9cc\ub4e4\uc5b4\uc11c \uc804\ub2ec\ud574\uc57c\ud568\n    private static string GenerateNonce(string _rawNonce) {\n        SHA256 sha = new SHA256Managed();\n        var sh = new StringBuilder();\n        \/\/ Encoding\uc740 \ubc18\ub4dc\uc2dc ASCII\uc5ec\uc57c \ud568\n        byte[] hash = sha.ComputeHash(Encoding.ASCII.GetBytes(_rawNonce));\n        \/\/ ToString\uc5d0\uc11c \"x2\"\ub85c \uc18c\ubb38\uc790 \ubcc0\ud658\ud574\uc57c \ud568. \ub300\ubb38\uc790\uba74 \uc2e4\ud328\ud568. \u3160\u3160\n        foreach (var b in hash) sb.Append(b.ToString(\"x2\"));\n        return sb.ToString();\n    }\n    \/\/ \ub0b4\ubd80\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\ub294 \uc778\ud130\ud398\uc774\uc2a4 \ud1b5\uc77c\uc744 \uc704\ud574 Coroutine\uc73c\ub85c \uad6c\ud604\n    \/\/ \uae30\uc874 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc544\ub2c8\uc5c8\ub2e4\uba74 Async\ub97c \uc0ac\uc6a9\ud588\uc744 \ub4ef\n    public IEnumerator LoginProcess() {\n        IsLoginSuccess = false;\n        IsLoginDone = false;\n\n        \/\/ Nonce \ucd08\uae30\ud654\n        \/\/ Nonce\ub294 Apple\ub85c\uadf8\uc778 \uc2dc \uc811\uc18d \uc138\uc158\ub9c8\ub2e4 \uc0c8\ub85c \uc0dd\uc131\n        RawNonce = System.Guid.NewGuid().ToString();\n        Nonce = GenerateNonce(RawNonce);\n\n        \/\/ QuickLogin\uc744 \uba3c\uc800 \uc218\ud589\n        \/\/ \uc774\uc804 \ub85c\uadf8\uc778 \uae30\ub85d\uc774 \uc5c6\ub2e4\uba74 \uc2e4\ud328 \ucc98\ub9ac\ub428\n        var quickLoginArgs = new AppleAuthQuickLoginArgs(Nonce);\n        var isQuickLoginDone = false;\n        appleAuthManager.QuickLogin(\n            quickLoginArgs,\n            credential => {\n                try {\n                    var appleIdCredential = credential as IAppleIDCredential;\n                    AuthCode = Encoding.UTF8.GetString(appleIdCredential.AuthorizationCode);\n                    IdToken = Encoding.UTF8.GetString(appleIdCredential.IdentityToken);\n                    IsLoginSuccess = true;\n                }\n                catch(System.Exception e) {\n                    Debug.LogException(e);\n                    IsLoginSuccess = false;\n                }\n                isQuickLoginDone = true;\n            },\n            error => {\n                IsLoginSuccess = false;\n                isQuickLoginDone = true;\n            });\n        yield return new WaitUntil(() => isQuickLoginDone);\n        \/\/ QuickLogin\uc774 \uc131\uacf5\ud588\ub2e4\ub294 \uac83\uc740 \uc774\uc804 \ub85c\uadf8\uc778 \uc815\ubcf4\uac00 \uc788\uc5c8\ub2e4\ub294 \uc758\ubbf8\n        \/\/ \uc77c\ubc18 Login \uacfc\uc815\uc744 \uc9c4\ud589\ud560 \ud544\uc694\uac00 \uc5c6\uc5b4\uc9d0.\n        if(IsLoginSuccess) {\n            IsLoginDone = true;\n            yield break;\n        }\n\n        var loginArgs = new AppleAuthLoginArgs(LoginOptions.IncludeEmail, Nonce);\n        appleAuthManager.LoginWithAppleId(\n            loginArgs,\n            credential => {\n                try {\n                    var appleIdCredential = credential as IAppleIDCredential;\n                    AuthCode = Encoding.UTF8.GetString(appleIdCredential.AuthorizationCode);\n                    IdToken = Encoding.UTF8.GetString(appleIdCredential.IdentityToken);\n                    IsLoginSuccess = true;\n                }\n                catch(System.Exception e) {\n                    Debug.LogException(e);\n                    IsLoginSuccess = false;\n                }\n                IsLoginDone = true;\n            },\n            error => {\n                IsLoginSuccess = false;\n                IsLoginDone = true;\n            });\n        yield return new WaitUntil(() => IsLoginDone);\n    }\n}<\/code><\/pre>\n\n\n\n<p>\uc704\uc758 \ucf54\ub4dc\ub294 \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uc778\uc99d \ucf54\ub4dc\uc758 \uc77c\ubd80\ub97c \ub5bc\uc5b4\ub0b8 \uac83\uc774\ub77c \ucef4\ud30c\uc77c \uc624\ub958\uac00 \ub0a0 \uc218 \uc788\uc73c\ub098 \uae30\ubcf8\uc801\uc778 \ub85c\uc9c1\uc740 \ub3d9\uc77c\ud558\uae30 \ub54c\ubb38\uc5d0 \uc0ac\uc6a9 \uac00\ub2a5\ud560 \uac83\uc774\ub77c\uace0 \uc0dd\uac01\ub429\ub2c8\ub2e4.<br>QuickLogin\uc5d0 \ub300\ud55c \ucc98\ub9ac\ub294 \uae30\uc874 \ub85c\uadf8\uc778 \uc815\ubcf4\uac00 \uc788\ub294\uc9c0 \uc5ec\ubd80\ub97c \ubcc4\ub3c4\ub85c \ud30c\uc545\ud574\uc57c\ud560\uc9c0 \uadf8\ub0e5 QuickLogin\uc744 \uc2e4\ud328\ucc98\ub9ac\ud558\uba74 \ub420\uc9c0 \ud14c\uc2a4\ud2b8\uac00 \ud544\uc694\ud55c \uc0c1\ud0dc.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Firebase\uc5d0\uc11c AppleLogin \uc0ac\uc6a9<\/h2>\n\n\n\n<p>Firebase \ucabd \ucf54\ub4dc\ub294 \uc7a1\ucf54\ub4dc\uac00 \ub9ce\uc544\uc11c Apple Login\uc5d0 \uc0ac\uc6a9\ub418\ub294 \ubd80\ubd84\ub9cc \ucd94\ub838\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Firebase\ub294 Google\uc774\ub098 Apple GameCenter\uc640 \ub2ec\ub9ac AppleLoginProvider\ub97c \uc81c\uacf5\ud558\uc9c0 \uc54a\uace0 \uc788\ub2e4. \uadf8\ub798\uc11c OAuthProvider\ub97c \uc0ac\uc6a9\ud574\uc57c\ud55c\ub2e4.\n\/\/ RawNonce\ub294 SHA256\uc73c\ub85c \ubcc0\ud658\ud558\uae30 \uc804 \ubb38\uc790\uc5f4\uc744 \uc758\ubbf8\ud55c\ub2e4.\nvar credential = Firebase.Auth.OAuthProvider.GetCredential(\"apple.com\", AppleAuthorizer.IdToken, AppleAuthorizer.RawNonce, AppleAuthorizer.AuthCode);\n\nvar task = auth.SignInWithCredentialAsync(credential);\nyield return new WaitUntil(() => task.IsCompleted || task.IsFaulted || task.IsCanceled);\n\nFirebaseUser user = task.Result;<\/code><\/pre>\n\n\n\n<p>\uc8fc\uc758\ud560 \uac83\uc740 AppleLogin \uacfc\uc815\uc5d0\uc11c\ub294 SHA256\uc73c\ub85c \ub9cc\ub4e4\uc5b4\uc9c4 Nonce\ub97c \uc804\ub2ec\ud574\uc57c\ud558\uace0 Firebase \uc778\uc99d \uc2dc\uc5d0\ub294 SHA256\uc73c\ub85c \ubcc0\ud658\ud558\uae30 \uc804\uc758 \ubb38\uc790\uc5f4\uc744 \uc804\ub2ec\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">XCode \uc124\uc815<\/h2>\n\n\n\n<p>AppleLogin\uc744 \uc704\ud55c XCode \uc124\uc815\uc740 Unity Blog\uc5d0\uc11c \uc601\uc0c1\uc73c\ub85c \uce5c\uc808\ud558\uac8c \uc124\uba85\ud558\uace0 \uc788\uc73c\ub2c8 \ud574\ub2f9 \ub0b4\uc6a9\uc744 \ucc38\uace0\ud558\uba74 \ub41c\ub2e4.<br><a href=\"https:\/\/blogs.unity3d.com\/kr\/2019\/09\/19\/support-for-apple-sign-in\/\">https:\/\/blogs.unity3d.com\/kr\/2019\/09\/19\/support-for-apple-sign-in\/<\/a> <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Reference<\/h2>\n\n\n\n<p><a href=\"https:\/\/firebase.google.com\/docs\/auth\/ios\/apple?authuser=0\">https:\/\/firebase.google.com\/docs\/auth\/ios\/apple?authuser=0<\/a><br><a href=\"https:\/\/github.com\/lupidan\/apple-signin-unity\">https:\/\/github.com\/lupidan\/apple-signin-unity<\/a> <br><a href=\"https:\/\/firebase.google.com\/docs\/auth\/unity\/apple\">https:\/\/firebase.google.com\/docs\/auth\/unity\/apple<\/a> <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\uae30\ud0c0 \uc0bd\uc9c8<\/h2>\n\n\n\n<p>UIApplicationExitsOnSuspend\uac00 plist\uc5d0 \ud3ec\ud568\ub418\uc5b4 \uc788\uc73c\uba74 ipa \uc5c5\ub85c\ub4dc \uc911 \uc5d0\ub7ec\ub0a8.<br>plist \uc5f4\uc5b4\uc11c \uc0ad\uc81c\ud574 \uc918\uc57c\ud568.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Apple\uc774 \uc775\uba85 \ub85c\uadf8\uc778 \uae30\ub2a5\ub9cc \uc0ac\uc6a9\ud560\uac8c \uc544\ub2c8\ub77c\uba74 Apple Login\uc744 \uc758\ubb34\ud654 \ud558\uc600\uae30 \ub54c\ubb38\uc5d0 Apple Login\uc744 \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uc73c\uba74 \ub9ac\uc81d\uc744 \ub2f9\ud558\uac8c \ub429\ub2c8\ub2e4. \uadf8\ub798\uc11c Apple Login\uc744 \ud504\ub85c\uc81d\ud2b8\uc5d0 \ucd94\uac00\ud558\ub294 \uacfc\uc815\uc744 \uac04\ub7b5\ud558\uac8c \ub0a8\uae41\ub2c8\ub2e4. \uc6b0\uc120 Unity\uc5d0\uc11c \uc560\ud50c \ub85c\uadf8\uc778\uc744 \uc9c0\uc6d0\ud558\ub294 \ud50c\ub7ec\uadf8\uc778\uc774 \ub450 \uac00\uc9c0\uac00 \uc788\uc2b5\ub2c8\ub2e4.\uccab\ubc88\uc9f8\ub294 Unity Technology\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 SignInWithApple \uc785\ub2c8\ub2e4. https:\/\/assetstore.unity.com\/packages\/tools\/sign-in-with-apple-154202 \ub450\ubc88\uc9f8\ub294 GitHub\uc5d0 \uc62c\ub77c\uc640 \uc788\ub294 AppleAuth \uc785\ub2c8\ub2e4.https:\/\/github.com\/lupidan\/apple-signin-unity \ub2f9\uc5f0\ud788 \ucc98\uc74c\uc5d0\ub294 Unity\uc5d0\uc11c \uc81c\uacf5\ud574 \uc8fc\ub294 \ud50c\ub7ec\uadf8\uc778\uc744 \uc0ac\uc6a9\ud558\uc5ec \uad6c\ud604\uc744 &hellip; <a href=\"http:\/\/milennium9.godohosting.com\/wordpress\/?p=300\" class=\"more-link\"><span class=\"screen-reader-text\">[Unity] Apple Login\uacfc Firebase \uc778\uc99d<\/span> \ub354\ubcf4\uae30 <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_newsletter_tier_id":0},"categories":[1],"tags":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p5PypW-4Q","_links":{"self":[{"href":"http:\/\/milennium9.godohosting.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/300"}],"collection":[{"href":"http:\/\/milennium9.godohosting.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/milennium9.godohosting.com\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/milennium9.godohosting.com\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/milennium9.godohosting.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=300"}],"version-history":[{"count":9,"href":"http:\/\/milennium9.godohosting.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/300\/revisions"}],"predecessor-version":[{"id":310,"href":"http:\/\/milennium9.godohosting.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/300\/revisions\/310"}],"wp:attachment":[{"href":"http:\/\/milennium9.godohosting.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=300"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/milennium9.godohosting.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=300"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/milennium9.godohosting.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=300"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}