title: How to grant access to users externally authenticated and not registered in my WebApp using asp.net core 2.2?
body: <blockquote>
    <p><strong>Summary</strong></p>
  </blockquote>
  
  <p>This is my first try with OAuth2 and External Login Mechanisms.</p>
  
  <p>I'm creating a WebApp that will expose API features through a user-friendly UI.</p>
  
  <p>In order to make API calls, I need to receive an access token from QBO that grants access to resources.</p>
  
  <p>So, my WebApp has an external login option which I use to authenticate against QBO, and then authorize my app.</p>
  
  <p>Everything works fine until...</p>
  
  <p><a href="https://i.stack.imgur.com/HXzOO.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/HXzOO.png" alt="Error loading external login information."></a></p>
  
  <blockquote>
    <p><strong>Services Configuration</strong></p>
  </blockquote>
  
  <p>Based on a tutorial for GitHub authentication, I came up with this.</p>
  
  <pre><code>        services.AddAuthentication(o =&gt; {
              o.DefaultAuthenticateScheme = IdentityConstants.ExternalScheme;
              o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
              o.DefaultChallengeScheme = IdentityConstants.ExternalScheme;
          })
              .AddOAuth("qbo", "qbo", o =&gt; {
                  o.CallbackPath = new PathString("/signin-qbo");
                  o.ClientId = Configuration["ecm.qbo.client-id"];
                  o.ClientSecret = Configuration["ecm.qbo.client-secret"];
                  o.SaveTokens = true;
                  o.Scope.Add("openid");
                  o.Scope.Add("profile");
                  o.Scope.Add("email");
                  o.Scope.Add("com.intuit.quickbooks.accounting");
  
                  o.AuthorizationEndpoint = Configuration["ecm.qbo.authorization-endpoint"];
                  o.TokenEndpoint = Configuration["ecm.qbo.token-endpoint"];
                  o.UserInformationEndpoint = Configuration["ecm.qbo.user-info-endpoint"];
  
                  o.Events.OnCreatingTicket = async context =&gt; {
                      var companyId = context.Request.Query["realmid"].FirstOrDefault() ?? throw new ArgumentNullException("realmId");
                      var accessToken = context.AccessToken;
                      var refreshToken = context.RefreshToken;
  
                      Configuration["ecm.qbo.access-token"] = accessToken;
                      Configuration["ecm.qbo.refresh-token"] = refreshToken;
                      Configuration["ecm.qbo.realm-id"] = companyId;
  
                      context.Backchannel.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
                      context.Backchannel.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                      var response = await context.Backchannel.GetStringAsync(context.Options.UserInformationEndpoint);
  
                      var result = JsonConvert.DeserializeObject&lt;Dictionary&lt;string, string&gt;&gt;(response);
  
                      var user = (ClaimsIdentity)context.Principal.Identity;
                      user.AddClaims(new Claim[] {
                          new Claim("access_token", accessToken),
                          new Claim("refresh_token", refreshToken),
                          new Claim(ClaimTypes.GivenName, result["givenName"]),
                          new Claim(ClaimTypes.Surname, result["familyName"]),
                          new Claim(ClaimTypes.Email, result["email"]),
                          new Claim(ClaimTypes.Name, result["givenName"]+" "+result["familyName"])
                      });
                  };
              });
  </code></pre>
  
  <p>This works. I can add my claims based on user information, the context.Principal.Identity indicates that it's authenticated.</p>
  
  <p>For some reasons, it seems to try and redirect to `/Identity/Account/Login?returnUrl=%2F. Why is that?</p>
  
  <blockquote>
    <p><strong>Login page redirection</strong></p>
  </blockquote>
  
  <p>Here, I don't get why I get the redirection and this confuses me a lot. So, I added the AccountController just to try and shut it up.</p>
  
  <pre><code>namespace ecm.backoffice.Controllers {
      [Authorize]
      [Route("[controller]/[action]")]
      public class AccountController : Controller {
          [AllowAnonymous]
          [HttpGet]
          public IActionResult Login(string returnUrl = "/") {
              return Challenge(new AuthenticationProperties { RedirectUri = returnUrl });
          }
  
          [Authorize]
          [HttpGet]
          public async Task&lt;IActionResult&gt; Logout(string returnUrl = "/") {
              await Request.HttpContext.SignOutAsync("qbo");
              return Redirect(returnUrl);
         }
      }
  }
  </code></pre>
  
  <p>And this creates more confusion than it solves, actually. I'm lost here...</p>
  
  <blockquote>
    <p><strong>Apply Migrations</strong></p>
  </blockquote>
  
  <p>This Individual User Authentication WebApp seems to use Identity which looks like it creates a lot of behind the scene mechanisms. I first tried to register to my app, and had to "Apply Migrations", which I totally get, since the data model wasn't initialized.</p>
  
  <p>So, I clicked the Apply Migrations button. I though I was okay with this...</p>
  
  <blockquote>
    <p><strong>Entity Framework Core</strong></p>
  </blockquote>
  
  <p>I am aware that the app is using Entity Framework Core for its persistence mechanism, hence the registration process, etc. And to configure it, I needed to add these lines to the services configs.</p>
  
  <pre><code>        services.AddDbContext&lt;ApplicationDbContext&gt;(options =&gt;
              options.UseSqlServer(
                  Configuration.GetConnectionString("DefaultConnection")));
          services.AddDefaultIdentity&lt;IdentityUser&gt;()
              .AddDefaultUI(UIFramework.Bootstrap4)
              .AddEntityFrameworkStores&lt;ApplicationDbContext&gt;();
  </code></pre>
  
  <p>It looks like it just won't work at all.</p>
  
  <blockquote>
    <p><strong>Thoughts</strong></p>
  </blockquote>
  
  <p>At this point, I think that the message says it Entity Framework just can't load the user information from its underlying data store. I totally understand that, and I don't want to register this user. I just want to take for granted that if QBO authenticated the user, it's fine by me and I grant open bar access to the WebApp features, even if the user ain't registered.</p>
  
  <p>How to tell that to my WebApp?</p>
  
  <blockquote>
    <p><strong>Related Q/A I read prior to ask</strong></p>
  </blockquote>
  
  <p><a href="https://stackoverflow.com/questions/53925609/prevent-redirect-to-account-login-in-asp-net-core-2-2">Prevent redirect to /Account/Login in asp.net core 2.2</a>
  <a href="https://stackoverflow.com/questions/51883634/asp-net-core-2-1-web-api-identity-and-external-login-provider">ASP.NET Core (2.1) Web API: Identity and external login provider</a>
  <a href="https://stackoverflow.com/questions/54354247/asp-net-core-2-2-redirects-to-login-after-successful-sign-in">asp.net core 2.2 redirects to login after successful sign in</a>
  <a href="http://asp.net%20core%202.2%20redirects%20to%20login%20after%20successful%20sign%20in" rel="nofollow noreferrer">External Login Authentication in Asp.net core 2.1</a></p>
  
  <p>And many more...</p>