Search code examples
c#asp.net-corecookiesoauthasp.net-identity

Check claims (email) before creating a new cookie, without asp. core identity store using asp net core social login


I'm working on my hobby project where I'have implemented social login via Google.

now I want to prevent this so that only certain user can sign in into the app, As I found that there is no way to restrict this on google OAuth side, So I have added a table to store the email and role.

if the email address is not found in that table I want to prevent a user from signing.

            services
           .AddAuthentication(options =>
           {
               options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
           })
           .AddCookie()
           .AddGoogle(googleOption =>
           {

               googleOption.ClientId = Configuration["Authentication:Google:ClientID"]; ;
               googleOption.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
               googleOption.Events.OnRemoteFailure = (context) =>
               {
                   context.HandleResponse();
                   return context.Response.WriteAsync("<script>window.close();</script>");
               };
               googleOption.Events = new Microsoft.AspNetCore.Authentication.OAuth.OAuthEvents
               {
                   OnTicketReceived = async ctx =>
                   {
                       string emailAddress = ctx.Principal.
                                               FindFirstValue("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress");
                       var db = ctx.HttpContext.RequestServices.GetRequiredService<DbContext>();
                       var roles = await db.EmailRoles.Where(c => c.Email == emailAddress).ToListAsync();
                       if (roles.Count > 1)                           
                       {
                           var claims = new List<Claim>();
                           foreach (var item in roles)
                           {
                               claims.Add(new Claim(ClaimTypes.Role, item.Role));
                           }
                           var appIdentity = new ClaimsIdentity(claims);
                           ctx.Principal.AddIdentity(appIdentity);
                       }
                   }
               };
           });

Solution

  • I think you are looking for OnCreatingTicket. this will allow you to test the users as their logging in. In this example only gmail.com emails would be allowed to login anyone else would be kicked out

     services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            })
            .AddCookie()
            .AddGoogle("Google", options =>
            {
                options.ClientId = Configuration["Authentication:Google:ClientId"];
                options.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
                options.Events = new OAuthEvents
                {
                    OnCreatingTicket = context =>
                    {
                        string domain = context.User.Value<string>("domain");
                        if (domain != "gmail.com")
                            throw new GoogleAuthenticationException("You must sign in with a gmail.com email address");
    
                        return Task.CompletedTask;
                    }
                };
            });