What I need to implement that Face ID authentication will work on Xamarin.forms project?
You have to do this natively on your iOS project, and then expose it to your Forms project using a DependencyService or some kind of ioc.
You must add to your info.plist the NSFaceIDUsageDescription key, otherwise the app will crash when asking for authentication.
Here is a snippet that authenticates a user locally:
var context = new LAContext();
LAContextReplyHandler replyHandler;
NSError AuthError;
if (context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, out AuthError))
{
replyHandler = new LAContextReplyHandler((success, error) =>
{
// Handle authentication success or error
});
// Authenticate and ask for permission if needed.
context.EvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, "Authenticate", replyHandler);
}
Related
My code is entering an infinite loop, hitting azure login page (hosted by Microsoft), then redirecting back to my app, then back to ms host login page etc etc etc.
In my code I have a breakpoint in the OnAuthorizationCodeReceived event...
public void ConfigureAzureAd(IServiceCollection services)
{
//set authentication to use Azure AD
services.AddAuthentication(auth =>
{
auth.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
auth.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
auth.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(opts =>
{
Configuration.GetSection("OpenIdConnect").Bind(opts);
opts.Events = new OpenIdConnectEvents
{
OnAuthorizationCodeReceived = async ctx =>
{
HttpRequest request = ctx.HttpContext.Request;
//We need to also specify the redirect URL used
string currentUri = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path);
//Credentials for app itself
var credential = new ClientCredential(ctx.Options.ClientId, ctx.Options.ClientSecret);
//Construct token cache
ITokenCacheFactory cacheFactory = ctx.HttpContext.RequestServices.GetRequiredService<ITokenCacheFactory>();
TokenCache cache = cacheFactory.CreateForUser(ctx.Principal);
var authContext = new AuthenticationContext(ctx.Options.Authority, cache);
//Get token for Microsoft Graph API using the authorization code
string resource = "https://graph.microsoft.com";
AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(
ctx.ProtocolMessage.Code, new Uri(currentUri), credential, resource);
//Tell the OIDC middleware we got the tokens, it doesn't need to do anything
ctx.HandleCodeRedemption(result.AccessToken, result.IdToken);
//ctx.HandleCodeRedemption();
}
};
});
}
and I can inspect the data in result, and it all looks ok (though not sure what failure would look like), it appears the login is working but my app is unable to recognize that the login has happened, or it's not saving, and keeps retrying
I've also asked someone else to try logging in with a user not in my Active Directory, and it fails appropriately, it really looks like Active Directory is happy, but my app just keeps redirecting.
I'm using .Net Core 2.2 (my first core project)
I'm using Active Directory Free
Update in response to #Marilee Turscak - MSFT
If i do not have the correct Reply Url setup in portal.azure.com and pass in it via C# then azure throws an error, so I've definitely got a reply URL in there and it matches correctly
Config looks like this:
"OpenIdConnect": {
"ClientId": "<guid in here>", // Application ID
"ClientSecret": "<secrect from portal.azure.com>",
"Authority": "https://login.microsoftonline.com/emailwithout#symbol.onmicrosoft.com/",
"PostLogoutRedirectUri": "http://www.<projectname_in_here>.local",
"CallbackPath": "/signin-oidc",
"ResponseType": "code id_token"
}
You need to set a Reply URL both in your code and in your application registration in Azure AD. You should set your Reply URL to wherever you want the user to be redirected (generally your main published homepage url - like https://myapp.azurewebsites.net).
For reference, you can see the examples in the Github samples.
https://azure.microsoft.com/en-us/resources/samples/active-directory-dotnet-webapp-openidconnect/
Answering my own question...
I think my issue was somehow related to feature folders. I was implementing custom routing to enable feature folders, but the Azure AD code sets it's own custom route to "/signin-oidc". I came to this conclusion by using Visual Studio to create a new project with Azure Active Directory wizard, got the test project signing-in, but when I ported my old code to the new test project, I got exactly the same error, but in the new "Visual Studio Wizard" there was very little configuration, AND it interfaced with my Azure AD and registered the app and added all the required configuration, so i knew it would before adding the feature folders, and produced exactly the same error behavior after feature folders, so conclude it was something to do with the feature folders custom routing.
Url to the code I found to help implement feature folders if anyone is interested: https://github.com/ardalis/OrganizingAspNetCore/tree/master/CoreFeatureFolders
I have one project (Project A) which is a .NET CORE API project using Openiddict with an endpoint of /connect/token to issue JWT tokens using Identity to handle the security etc. This project works great as is.
I have another project (Project B), which is just a very simple project with some HTML that makes requests to the API to get an access token, and get data from the API. This project also works great.
Now the part I cannot wrap my brain around, how do I use Facebook login between these two totally separate projects? I know how to use it if everything is under one roof, and it's really easy, but this scenario has me totally confused since everything is separated. So for starters, who handles the 'ExternalLogin', 'ExternalLoginCallBack' logic (from .NET web template using individual accounts), the API? The HTML project? When connecting with Facebook, what redirect uri should I use (API/HTML project)? Then who should have the below code in their 'Startup.cs' file?
app.UseFacebookAuthentication(new FacebookOptions
{
AppId = "xxxxxxx",
AppSecret = "xxxxxxxxx",
Scope = { "email", "user_friends" },
Fields = { "name", "email" },
SaveTokens = true,
});
And finally if this helps here is how I have Project A currently setup:
STARTUP.CS (API)
public void ConfigureServices function: (API)
// add entity framework using the config connection string
services.AddEntityFrameworkSqlServer()
.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
// add identity
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// add OpenIddict
services.AddOpenIddict<ApplicationUser, ApplicationRole, ApplicationDbContext>()
.DisableHttpsRequirement()
.EnableTokenEndpoint("/connect/token")
.AllowPasswordFlow()
.AllowRefreshTokenFlow()
.UseJsonWebTokens()
.AddEphemeralSigningKey();
services.AddCors();
public void Configure function: (API)
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
RequireHttpsMetadata = false,
Audience = "http://localhost:54418/",
Authority = "http://localhost:54418/"
});
Authorization Controller (API)
public class AuthorizationController : Controller
{
private OpenIddictUserManager<ApplicationUser> _userManager;
public AuthorizationController(OpenIddictUserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
[HttpPost("~/connect/token")]
[Produces("application/json")]
public async Task<IActionResult> Exchange()
{
var request = HttpContext.GetOpenIdConnectRequest();
if (request.IsPasswordGrantType())
{
var user = await _userManager.FindByNameAsync(request.Username);
if (user == null)
{
return BadRequest(new OpenIdConnectResponse
{
ErrorDescription = "The username or password provided is incorrect"
});
}
var identity = await _userManager.CreateIdentityAsync(user, request.GetScopes());
// Add a custom claim that will be persisted
// in both the access and the identity tokens.
if (user.Avatar != null)
{
identity.AddClaim("user_avatar", user.Avatar,
OpenIdConnectConstants.Destinations.AccessToken,
OpenIdConnectConstants.Destinations.IdentityToken);
}
if (user.InSiteUserName != null)
{
identity.AddClaim("insite_username", user.InSiteUserName,
OpenIdConnectConstants.Destinations.AccessToken,
OpenIdConnectConstants.Destinations.IdentityToken);
}
identity.AddClaim("hasLoggedIn", user.HasLoggedIn.ToString(),
OpenIdConnectConstants.Destinations.AccessToken,
OpenIdConnectConstants.Destinations.IdentityToken);
// Create a new authentication ticket holding the user identity.
var ticket = new AuthenticationTicket(
new ClaimsPrincipal(identity),
new AuthenticationProperties(),
OpenIdConnectServerDefaults.AuthenticationScheme);
ticket.SetResources(request.GetResources());
ticket.SetScopes(request.GetScopes());
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
}
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.UnsupportedGrantType,
ErrorDescription = "The specified grant type is not supported."
});
}
}
}
I don't know if it's including anything from Project B since it's pretty basic/bare and relies on the API for everything.
I know this is a loaded and complicated question, and I'm sure I'm not presenting it as fluidly as possible so I apologize in advance for that, like I said before, I'm confused. Thank you!
Now the part I cannot wrap my brain around, how do I use Facebook login between these two totally separate projects? I know how to use it if everything is under one roof, and it's really easy, but this scenario has me totally confused since everything is separated. So for starters, who handles the 'ExternalLogin', 'ExternalLoginCallBack' logic (from .NET web template using individual accounts), the API? The HTML project?
In the recommended case (i.e when using an interactive flow like the authorization code flow or the implicit flow), the authorization server project itself is responsible of handling the external authentication dance, using the social providers you've configured in your ASP.NET Core pipeline.
In theory, the final client application (i.e the JS app) doesn't even know that you've decided to use external authentication at the authorization server level, since it's not directly linked to Facebook or Google.
In this case, the redirect_uri configured in the Facebook options must correspond to an endpoint owned by the authorization server application (in your case, it's provided by the Facebook authentication middleware).
If you don't like this approach, there's also a different flow named "assertion grant", that basically reverses how things are handled: the final client app (the JS app in your case) is directly linked to Facebook - so the redirect_uri must correspond to the JS app - and uses OpenIddict's token endpoint to "exchange" Facebook tokens with tokens issued by your own server, that can be used with your own APIs.
For more information about this flow, please read Exchanging a google idToken for local openId token c#.
I creating a website which has register link multiple auth providers and custom token as well. I also using AngularFire2 to communicate between Angular2 and Firebase but seem it doesn't have method similar with Firebase, e.g:
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
ref.authWithCustomToken(AUTH_TOKEN, function(error, authData) {
Anyone can show up to me how can deal with issue?
To authenticate using a custom token, you can call AngularFire2's login method with the following configuration options:
angularFire.auth.login(AUTH_TOKEN, {
provider: AuthProviders.Custom,
method: AuthMethods.CustomToken
});
Internally, this will call Firebase's signInWithCustomToken method.
I've got an ServiceStack service running with custom authentication, this runs fine from the browser and through a Windows console program.
I'm now trying to get a simple Xamarin Android program to authenticate but whatever I try it crashes with an Exception without any further explanation. The code I am using stops at the line with 'var authResponse', I'm using the 4.0.44 ServiceStack packages and the lastest stable Xamarin from inside VS2015.
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
// servicestack
var client = new JsonServiceClient("http://10.0.2.2:8080");
var authResponse = client.Get<AuthenticateResponse>( new Authenticate
{
UserName = "Willem",
Password = "secret",
RememberMe = true
});
Any pointers to what/where I should look?
tia
If this is a self-hosted Service you would need to register the HttpListener AppHost to accept requests from different hosts by listening on a host wildcard, e.g:
appHost.Start("http://*:8080/");
I'm completely newbie at authentication proccess with OAuth (I'm trying to make use of OAuth 2, exactly), and the example I am following to authenticate by using Facebook SDK latest release says that this code snippet should work for C# .NET environments (http://blog.prabir.me/post/Facebook-CSharp-SDK-Writing-your-first-Facebook-Application.aspx):
webBrowser.Navigate(loginUrl);
private void webBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
FacebookOAuthResult result;
if (FacebookOAuthResult.TryParse(e.Url, out result))
{
if (result.IsSuccess)
{
var accesstoken = result.AccessToken;
}
else
{
var errorDescription = result.ErrorDescription;
var errorReason = result.ErrorReason;
}
}
}
Since I am programming a browser SL app, the WebBrowser control displays nothing, so I am not either able to catch the response, how could I do something equivalent to that in my app? Or how could I manage to complete the authentication proccess if there is no equivalent way? Thanks!
A suggestion: Why don't you try to parse the WebResponse when you receive it as opposed to listening for the event?
I use Facebook OAuth in my web app. It is nothing but a series of URL posts with the correct parameters.
Take a look at this post: Login using Facebook Problem after logging out (All the details are in the answer and comments)
Here are the brief steps:
Call the Facebook OAuth Dialog URL with your AppId, redirect url, and permissions. Request_type should be "code"
When the user logs in and authorizes you application, they will be redirected to the redirect url with a "code" querystring parameter.
Take the value of the code parameter and make another call to Facebook to get the token.
Use this token to make calls on the user's behalf.