How signin-google in asp.net core authentication is linked to the google handler? - authentication

I went into the source code but I can't see where it's wired to the handler.
In the GoogleExtensions.cs file, I see the
=> builder.AddOAuth<GoogleOptions, GoogleHandler>(authenticationScheme,
displayName, configureOptions);
But I don't understand how the route "/signin-google" calls the handler.

How signin-google in asp.net core authentication is linked to the google handler?
The question can be divided into two small questions .
How user is redirected to the url of /signin-google
How GoogleHandler process the request on /signin-google
How user is redirected to signin-google
Initially, when user clicks the Google button to login with Google Authentication, the browser will post a request to the following url:
https://your-server/Identity/Account/ExternalLogin?returnUrl=%2F
Your server simply redirects the user to Google.com and asks Google to authenticate the current user :
https://accounts.google.com/o/oauth2/v2/auth?
response_type=code
&client_id=xxx
&scope=openid%20profile%20email
&redirect_uri=https%3A%2F%2Fyour-server%2Fsignin-google
&state=xxx
When Google has authenticated the user successfully, it will redirect the user to your website with a parameter of code according to redirect_uri above.
https://your-server/signin-google?
state=xxx
&code=yyy
&scope=zzz
&authuser=0
&session_state=abc
&prompt=none
Note the path here equals /signin-google. That's the first key point.
How GoogleHandler process the signin-google
Before we talk about how GoogleHandler goes , we should take a look at how AuthenticationMiddleware and AuthenticationHandler work:
When there's an incoming request, the AuthenticationMiddleware (which is registered by UseAuthentication() in your Configure() method of Startup.cs), will inspect every request and try to authenticate user.
Since you've configured authentication services to use google authentication , the AuthenticationMiddleware will invoke the GoogleHandler.HandleRequestAsync() method
If needed, the GoogleHandler.HandleRequestAsync() then handle remote authentication with OAuth2.0 protocol , and get the user's identity.
Here the GoogleHandler inherits from RemoteAuthenticationHandler<TOptions> , and its HandleRequestAsync() method will be used by AuthenticationMiddleware to determine if need to handle the request. . When it returns true, that means the current request has been already processed by the authentication handler and there's no further process will be executed.
So how does the HandleRequestAsync() determine whether the request should be processed by itself ?
The HandleRequestAsync() method just checks the current path against the Options.CallbackPath . See source code below :
public abstract class RemoteAuthenticationHandler<TOptions> : AuthenticationHandler<TOptions>, IAuthenticationRequestHandler
where TOptions : RemoteAuthenticationOptions, new()
{
// ...
public virtual Task<bool> ShouldHandleRequestAsync()
=> Task.FromResult(Options.CallbackPath == Request.Path);
public virtual async Task<bool> HandleRequestAsync()
{
if (!await ShouldHandleRequestAsync())
{
return false;
}
// ... handle remote authentication , such as exchange code from google
}
}
Closing
The whole workflow will be :
The user clicks on button to login with Google
Google authenticates the user and redirects him to /signin-google
Since the path== signin-google, the middleware will use HandleRequestAsync() to proecess current request, and exchange code with google.
... do some other things

Related

Redirect after successful ADB2C login

I'm using Azure ADB2C authentication in my ASP.NET Core web app.
Based on the claims received after the user logging in, I'd like to redirect the user to another page.
I thought I might be able to redirect the user on the OnTokenValidated event of OpenIdConnectEvents. But frankly, I'm not sure if this is redirecting the client, or redirecting the auth flow. Bottom line, it doesn't redirect the user.
public async Task OnTokenValidated(TokenValidatedContext context)
{
// ... clipped code ...
context.HttpContext.Response.Redirect("~/somewhere");
}
My event handler works otherwise--just doesn't redirect.
What is the final event received after a user successfully logs in with ADB2C?
And how, specifically, can I redirect a user?
Thanks

Forgot password in .Net Core 5.0

my login and register methods are working well and i use the Claim when the user try to login or logout.
i saw many example of that ForgotMyPassword page but all of it using
private readonly UserManager<IdentityUser> _userManager; which is based on Microsoft.AspNetCore.Identity; . Can i do ForgotMyPassword action without using UserManager
?? im asking that Claim based authentication and authorization is what i need in my project.
can i use them both,if i can how can i do that ?
it would be so great if someone explain its clearly,regards
When users register, their information will be added to the database. You can pass the registered email of the user to the ForgotMyPassword action. Then send a verification code to the mailbox or send a link to make user redirect to another page to reset the password. Make the user finish changing the password.
You can both use authentication and authorization, they are responsible for different businesses. Authentication has cookie, jwt and other authentication service. cookie authentication is the built-in component. Identity has integrated it. You should have learn about it.
The another service is authorization. Authorization service only works after authentication is successful. It has many authorization methods, about claim-based authorization, when one user access the authorized action, it will go through the middleware app.UseAuthorization(). This middleware will check whether there is a claim corresponding to the action policy's claim. Because you have configured it in startup.
services.AddAuthorization(options=>
{
options.AddPolicy("Policy1",policy=>
{
policy.RequireClaim("claim1",new string[] {"value1","value2" });
});
});
On the authorized action.
[Authorize(Policy = "Policy1")]
public IActionResult get()
{
return Ok();
}
In this scenario, the user should have the claim Claim("claim1","value1") or Claim("claim1","value2").

Redirect unauthorized requests to Azure AD for login

I've got a WebAPI instance running in Azure that is secured with Azure AD. A mobile app connects to this API using bearer tokens, works great. When I try calling the API from the browser, though, it returns a 401 because I'm not logged in. That's true because I'm not presented with a login screen.
My API doesn't have any UI so what I'd want it to do is to forward the user to Azure AD login and return to the API endpoint they were calling after authentication.
If I go to the Azure portal, there's a setting that says "Action to take when the request is not authorized". If I set that one to "Log in with Azure Active Directory", it behaves the way I want it to. But... I have some endpoints which need to be accessed anonymously, and this setting catches all requests, not caring about any [AllowAnonymous] attributes.
So any request to an endpoint labeled Authorize that is not authorized yet should be forwarded to Azure AD login, all others should be allowed.
Add a DelegatingHandler to your web api project and register it in WebApiConfig.cs:
config.MessageHandlers.Add(new UnAuthorizedDelegatehandler());
public class UnAuthorizedDelegatehandler: DelegatingHandler
There you can check for 401 status codes and do the redirect to whatever and also apply a redirect url as querystring parameter.
HttpResponseMessage rm = await base.SendAsync(request, cancellationToken);
if (rm.StatusCode == HttpStatusCode.Unauthorized)
{
// configure the redirect here
return rm;
}

How to create identity in MVC app with JWT

I'll try to be explicit.
I have a Front End app (MVC), it can communicate with a Facade Web Api (Resource) and get token from an authentication server.
My problem is I can't create an identity in MVC app. This is mu Startup class.
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
});
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
}
When I try to go to a method controller decorated with [Authorize], I get 401 error instead to be redirected to Login page.
Please, I would appreciate any help, advice or example.
Regards,
Typically, unless your app is doing postback's you do not need to enable the cookie authentication with login path. That is for the oauth password login flow (grant_type) where you are internally authorizing your users against your identity database. If you're redirecting to an external authorization api (like facebook) then you don't need to set a login path in your application since the first authorization endpoint that gets hit is your external callback (after you send them to facebook, they will send them back to your external endpoint). The redirect you are getting is because cookie authentication is registered as active authentication mode so it redirects 401's to the login path you set (overriding other OWIN middleware).
If you want to house your authorization server in house, have a look at the link below, it will at the least get you setup with JWT support -
http://bitoftech.net/2014/10/27/json-web-token-asp-net-web-api-2-jwt-owin-authorization-server/

loopback protected routes/ensure login

How do I ensure that a user is logged in before I render a view using loopback?
I can loggin in the front end using my angular app. But I wanted to block anonymous users from viewing the page.
I thought it would be a header, something like headers.authorization_token, but it does not seem to be there.
I am looking for something like connect-ensurelogin for passport, without having to use passport.
This is the $interceptor that solves your problem.
This code detects 401 responses (user not logged in or the access token is expired) from Loopback REST server and redirect the user to the login page:
// Inside app config block
$httpProvider.interceptors.push(function($q, $location) {
return {
responseError: function(rejection) {
if (rejection.status == 401) {
$location.nextAfterLogin = $location.path();
$location.path('/login');
}
return $q.reject(rejection);
}
};
});
And this code will redirect to the requested page once the user is logged in
// In the Login controller
User.login($scope.credentials, function() {
var next = $location.nextAfterLogin || '/';
$location.nextAfterLogin = null;
$location.path(next);
});
Here is one possible approach that has worked for me (details may vary):
Design each of the Pages in your Single Page Angular App to make at one of your REST API calls when the Angular Route is resolved.
Secure all of your REST API Routes using the AccessToken/User/Role/ACL scheme that LoopBack provides.
When no valid Access Token is detected on the REST Server side, pass back a 401 Unauthorized Error.
On the Client Side Data Access, when you detect a 401 on your REST Call, redirect to your Logic Route.
For the smoothest User Experience, whenever you redirect to Login, store the Route the User wanted to access globally
(localStore, $RootScope, etc.) and redirect back there when the User
Logs in and gets a valid Access Token.
Here is the LoopBack Access Control sample: https://github.com/strongloop/loopback-example-access-control