首页 > 解决方案 > 在 .net 后端使用苹果 JS 登录验证 AuthToken

问题描述

我正在尝试在我们的 Web 应用程序上实现 Sign in with apple,它适用于 AppleTV 和 IOS,但相同的流程似乎不适用于来自 Apple JS 的令牌,我得到INVALID_CLIENT.

似乎它需要一些额外的步骤,所以我添加了 KID 等,现在我被困住了INVALID_GRANT(根据我的理解,这更好,至少客户还可以)。

Js侧面看,我做了以下事情:(流程似乎是正确的,有适当的回应AppleIDSignInOnSuccess

AppleID.auth.init({  
                 clientId: 'com.#########.weblogin',//service Id created   
                  scope: 'name email',  
                  state: state,  
                  redirectURI: location.href,  
                  usePopup: true //or false defaults to false  
              }); 



document.addEventListener('AppleIDSignInOnSuccess', (data) => {  
            //handle successful response  
            var deviceKey = document.cookie.replace(/(?:(?:^|.*;\s*)deviceKey\s*\=\s*([^;]*).*$)|^.*$/, "$1");  
            requestLogin({  
                AppleToken: data.detail.authorization.id_token,  
                AppleAuthorizationCode: btoa(data.detail.authorization.code),//our api requires base64urlsafe strings to be symetric with native apps
                FirstName: data.detail.user?.firstName,  
                LastName: data.detail.user?.LastName,  
                DeviceKey:  deviceKey  
            });  
        });

需要注意的是,虽然与文档 [state] 不同,不会返回,但在弹出的情况下可能没有必要,但这可能表明出现问题。

现在我用我的.NET后端处理 AuthorizationCode。

Hclient.DefaultRequestHeaders.Add("User-Agent", "Microsoft ASP.NET Core OpenIdConnect handler");  

var datas = new Dictionary<string, string="">()  
                        {  
                            { "client_id" , request.DeviceKey.StartsWith("WEB_") ? "com.########.weblogin" : "com.########.app" }, //use the serviceId and not the main appId for web  
                            { "code" , request.AppleAuthorizationCode.FromBase64UrlSafe().FromUtf8Bytes() },  
                            { "grant_type" , "authorization_code" },  
                            { "redirect_uri", "https://login.#######.com/signin-apple" },  
                            {"client_secret",request.DeviceKey.StartsWith("WEB_") ? TokenGenerator2.CreateNewToken() : TokenGenerator.CreateNewToken() }//generate the client_secret differently for web  
                        };  
var formdata = new FormUrlEncodedContent(datas);  

using (HttpResponseMessage res = Hclient.PostAsync("https://appleid.apple.com/auth/token",formdata ).Result)

这是响应“INVALID_GRANT”的调用。这就是我生成 jwt 令牌 client_secret 的方式。

public static class TokenGenerator2  
        {  
            public static string CreateNewToken()  
            {  
                const string iss = "7#######G"; // team ID  
                const string aud = "https://appleid.apple.com";  
                const string sub = "com.#######.weblogin"; // service Id  
                const string keyId =  "G######W";//key Idassociated with the p8 file  

                const string privateKey = "MIGT####...#####"; // contents of AuthKey_[keyId].p8 file  



                var d = DateTime.UtcNow.AddDays(-5);//I was worried the date time was the issue so I took a laaaaarge one ...  


                var cngKey = CngKey.Import(  
                  Convert.FromBase64String(privateKey),  
                  CngKeyBlobFormat.Pkcs8PrivateBlob);  


                var handler = new JwtSecurityTokenHandler();  


                var securityKey = new ECDsaSecurityKey(new ECDsaCng(cngKey) { KeySize = 256 , HashAlgorithm = CngAlgorithm.ECDsaP256});  


                securityKey.KeyId = keyId;  
                var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.EcdsaSha256);  


                return  handler.CreateEncodedJwt(iss, aud, new ClaimsIdentity(new List { new Claim("sub", sub) }),d, expires: d.AddMonths(3),d, signingCredentials: signingCredentials);  

            }  

        }  

作为参考,这是我为本机应用程序创建它的方式(有效的流程)

  public static class TokenGenerator  
        {  
            public static string CreateNewToken()  
            {  
                const string iss = "7#######G"; // your account's team ID found in the dev portal  
                const string aud = "https://appleid.apple.com";  
                const string sub = "com.######.app";   
                const string privateKey = "MIGTAg###...####"; // contents of .p8 file  


                var cngKey = CngKey.Import(  
                  Convert.FromBase64String(privateKey),  
                  CngKeyBlobFormat.Pkcs8PrivateBlob);  
                var d = DateTime.UtcNow.AddDays(-5);  


                var handler = new JwtSecurityTokenHandler();  
                var token = handler.CreateJwtSecurityToken(  
                    issuer: iss,  
                    audience: aud,  
                    subject: new ClaimsIdentity(new List { new Claim("sub", sub) }),  
                    expires: d.AddMonths(3), // expiry can be a maximum of 6 months  
                    issuedAt: d,  
                    notBefore: d,  
                    signingCredentials: new SigningCredentials(  
                      new ECDsaSecurityKey(new ECDsaCng(cngKey)), SecurityAlgorithms.EcdsaSha256));  


                return handler.WriteToken(token);  
            }  


        }  

标签: .net.net-coreoauth-2.0cngapple-sign-in

解决方案


推荐阅读