I'm trying to get this up and running but I do not know where the issue is. My startup:
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentity<ApplicationUser, ApplicationRole>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI();
// .AddDefaultTokenProviders();
services.AddControllersWithViews();
//language
services.Configure<RequestLocalizationOptions>(options =>
{
options.DefaultRequestCulture = new RequestCulture("fr");
options.RequestCultureProviders = new List<IRequestCultureProvider>
{
new QueryStringRequestCultureProvider(),
new CookieRequestCultureProvider()
};
});
services.AddAuthentication(o =>
{
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddFacebook(facebookOptions =>
{
facebookOptions.AppId = "XXXXX";
facebookOptions.AppSecret = "XXXXX";
facebookOptions.SaveTokens = true;
});
services.AddControllersWithViews();
services.AddRazorPages();
services.AddAuthorization(options =>
{
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
}
My LoginController
[HttpGet]
[AllowAnonymous]
public async Task GetFacebook()
{
try
{
string scheme = "Facebook";
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")))
{
COMMON_FUNCTIONS.storeError(_context, "Not authenticated", MethodBase.GetCurrentMethod().ReflectedType.Name, auth.ToString());
// 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;
COMMON_FUNCTIONS.storeError(_context, "authenticated - mail", MethodBase.GetCurrentMethod().ReflectedType.Name, email);
// 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 = "APPSCHEME" + "://#" + string.Join(
"&",
qs.Where(kvp => !string.IsNullOrEmpty(kvp.Value) && kvp.Value != "-1")
.Select(kvp => $"{WebUtility.UrlEncode(kvp.Key)}={WebUtility.UrlEncode(kvp.Value)}"));
COMMON_FUNCTIONS.storeError(_context, "authenticated - url", MethodBase.GetCurrentMethod().ReflectedType.Name, url);
// Redirect to final url
Request.HttpContext.Response.Redirect(url);
}
}
catch (Exception ex)
{
COMMON_FUNCTIONS.storeError(_context, "Authenticate-ex", MethodBase.GetCurrentMethod().ReflectedType.Name, ex.ToString());
}
}
In my XAMARIN.FORMS:
private async void OnFacebookClicked(object sender, EventArgs e)
{
lblMessage.Text = "";
try
{
var authResult = await WebAuthenticator.AuthenticateAsync(new Uri(App.g_WebSite + "api/v1/Authenticate/GetFacebook"), new Uri("APPSCHEME://"));
var accessToken = authResult?.AccessToken;
}
catch (Exception ex) when (ex is TaskCanceledException || ex is OperationCanceledException)
{
lblMessage.Text = "User cancelled!";
}
catch (Exception ex)
{
string tt = ex.ToString();
lblMessage.Text = "Login failed!";
}
}
When I Click on the Loginbutton
, my function GetFacebook()
is called. In the server log I can see how the token is generated APPSCHEME://#access_token=xxxxxxxxxxxxxxxxxxxxxxxxx
before the Redirect call
Request.HttpContext.Response.Redirect(url);
But the page facebook page is not closing, the code in the XAMARIN.FORMS newer reaches
var accessToken = authResult?.AccessToken;
Update The code in my Android
[Activity(Label = "GSAQ_Mobile", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize )]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
//protected override void OnResume()
//{
// base.OnResume();
// Xamarin.Essentials.Platform.OnResume();
//}
}
[Activity(NoHistory = true, LaunchMode = LaunchMode.SingleTop)]
[IntentFilter(new[] { Android.Content.Intent.ActionView }, Categories = new[] { Android.Content.Intent.CategoryDefault, Android.Content.Intent.CategoryBrowsable },
DataScheme = "APPSCHEME")]
public class WebAuthenticationCallbackActivity : Xamarin.Essentials.WebAuthenticatorCallbackActivity
{
}
On my website, the facebooklogin
works fine.
Anyone an idea?
After lot's of testing I got it to work. I made several changes, but I do not know for certain which change did the trick:
In my opinion, point 4 did the trick, but the other points are sure a point of interest.