Reputation: 51
On my API server I use Xamarin.Essentials: Web Authenticator to login via social account (google, fb, apple). It works fine for Google and Facebook logins, but not Apple. Nginx when logging in via Google returns something like this:
- [15/Mar/2022:07:10:57 +0000] "GET /api/mobileauth/Google HTTP/2.0" 302 0 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1"
- [15/Mar/2022:07:10:58 +0000] "GET /signin-google?state=CfD..(e.t.c)
I can handle it, and it works fine, but when I try to log in, Apple returns error 500 like this:
- [15/Mar/2022:07:14:11 +0000] "GET /api/mobileauth/Apple HTTP/2.0" 302 0 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1"
- [15/Mar/2022:07:14:34 +0000] "POST /signin-apple HTTP/2.0" 500 0 "https://appleid.apple.com/" "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1"
Maybe someone had a similar problem and knows why is this happening? The server goes through Cloudflare which has full SSL. Anyone have any ideas? my startup:
services.AddAuthentication(o =>
{
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddFacebook(fb =>
{
fb.AppId = "my AppId";
fb.AppSecret = "my AppSecret ";
fb.SaveTokens = true;
})
.AddGoogle(g =>
{
g.ClientId = "my ClientId ";
g.ClientSecret = "my ClientSecret ";
g.SaveTokens = true;
})
.AddApple(a =>
{
a.ClientId = "my ClientId";
a.KeyId = "my KeyId ";
a.TeamId = "my TeamId ";
a.UsePrivateKey(keyId
=> WebHostEnvironment.ContentRootFileProvider.GetFileInfo($"AuthKey_my_KeyId.p8"));
a.SaveTokens = true;
});
my controller:
[HttpGet("{scheme}")]
public async Task Get([FromRoute] string scheme)
{
try
{
var auth = await Request.HttpContext.AuthenticateAsync(scheme);
if (!auth.Succeeded
|| auth?.Principal == null
|| !auth.Principal.Identities.Any(id => id.IsAuthenticated)
|| string.IsNullOrEmpty(auth.Properties.GetTokenValue("access_token")))
{
// Not authenticated, challenge
await Request.HttpContext.ChallengeAsync(scheme);
}
else
{
var claims = auth.Principal.Identities.FirstOrDefault()?.Claims;
var email = string.Empty;
email = claims?.FirstOrDefault(c => c.Type == System.Security.Claims.ClaimTypes.Email)?.Value;
// Get parameters to send back to the callback
var qs = new Dictionary<string, string>
{
{ "access_token", auth.Properties.GetTokenValue("access_token") },
{ "refresh_token", auth.Properties.GetTokenValue("refresh_token") ?? string.Empty },
{ "expires", (auth.Properties.ExpiresUtc?.ToUnixTimeSeconds() ?? -1).ToString() },
{ "email", email }
};
// Build the result url
var url = callbackScheme + "://#" + string.Join(
"&",
qs.Where(kvp => !string.IsNullOrEmpty(kvp.Value) && kvp.Value != "-1")
.Select(kvp => $"{WebUtility.UrlEncode(kvp.Key)}={WebUtility.UrlEncode(kvp.Value)}"));
// Redirect to final url
Request.HttpContext.Response.Redirect(url);
}
}
catch(Exception ex)
{
_logger.Error("Exception!" + ex + " Model:" + scheme);
}
}
Upvotes: 1
Views: 298
Reputation: 1241
First, configure your app to use Apple Sign In. https://learn.microsoft.com/en-us/xamarin/ios/platform/ios13/sign-in
For iOS 13 and higher, use the AppleSignInAuthenticator.AuthenticateAsync() method. This will call the native Apple Sign in API’s under the hood so users get the best experience possible on these devices. Write your shared code to use the right API at runtime like this:
var scheme = "..."; // Apple, Microsoft, Google, Facebook, etc.
WebAuthenticatorResult r = null;
if (scheme.Equals("Apple")
&& DeviceInfo.Platform == DevicePlatform.iOS
&& DeviceInfo.Version.Major >= 13)
{
// Use Native Apple Sign In API's
r = await AppleSignInAuthenticator.AuthenticateAsync();
}
else
{
// Web Authentication flow
var authUrl = new Uri(authenticationUrl + scheme);
var callbackUrl = new Uri("xamarinessentials://");
r = await WebAuthenticator.AuthenticateAsync(authUrl, callbackUrl);
}
var accessToken = r?.AccessToken;
Upvotes: 0