Skip to content

01binary/login

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

External OAuth login with popup

Audience

Developers implementing external authentication with Facebook, Twitter, Google, or another login provider, who wish to perform authentication in a popup window instead of the default (in the same window, redirecting to an external provider and then back to their site).

Overview

This ASP.NET 4 MVC 5 project documents some common pitfalls when implementing external logins in a popup. This differs from default project template that redirects the entire site to external login provider for authorization.

Summary

  • Provides instructions on how to make popups work with redirection on IE and Edge while running from localhost.
  • Minimally modifies the default ASP.NET template to have external logins open in popups. Look at popup.js and login.js to implement similar logic for your app.
  • Sets up Facebook authentication to use "popup" styling to avoid Facebook blocking the user with "window is too small" error.
  • Sets up Twitter authentication to use an updated certificate (valid 6/28/2016 to 9/19/2019). If this is now out of date, see existing StackOverflow topic linked in Startup.Auth.cs.
  • If you have used Fiddler, be sure to delete all DO_NOT_TRUST_FiddlerRoot certificates from your computer and user stores. This breaks Twitter authentication.
  • Lastly, this project sets up user secrets configuration to remind you not to check in your secrets.

Testing on localhost

Here are the explicit steps required to make your site running on localhost in IE/Edge be able to access its popups after they redirect back:

  • Go to Internet Options > Security
  • Select Trusted Sites icon (zone)
  • Change Security Level to exactly the same setting as the Security level for Internet zone (Medium-high by default).
  • Ensure Enable Protected Mode is likewise identical to Internet zone (checked by default).
  • Click Sites
  • Add http://localhost
  • Uncheck Require server verification
  • Close the Sites dialog
  • Click Apply on Internet Options dialog

This solution has been provided by Alex Altotsky: http://stackoverflow.com/a/30698397/3727395.

Opening external login in a popup window

The easiest way to implement this might be to modify the default ASP.NET form to open in a new window by specifying the target attribute for the HTML FORM tag. To control the size and chrome of the window that opens, the window with the right name can be pre-created in onclick of the form submit button with about:blank URL, which soon gets reused to show the POST result of the form.

See _externalloginslistpartial.cshtml for a complete example:

using (Html.BeginForm("ExternalLogin", "Account", FormMethod.Post, new { target = "login" })) {
<button type="submit" onclick="openPopup('login', externalLoginComplete)" class="btn btn-default" id="@p.AuthenticationType" name="provider" value="@p.AuthenticationType" title="Log in using your @p.Caption account">@p.AuthenticationType</button>

The window called 'login' is pre-loaded with chrome options and size, then used as a target for the ExternalLogin form.

To handle closing this window, we define a function that watches the result of the window.open call for closure or a result window variable being set.

  • If the window is closed unexpectedly, the watching function notifies the application of login failure.
  • If external login fails because user forgot password or clicked cancel, the watching function notifies the application of login failure.
  • If external login succeeds but user clicked cancel at the prompt to register with your application, the watching function notifies the application of login failure.
  • If external login succeeds and the user was already registered or submitted your registration form, the watching function notifies the application of success and provides the registered user name.

See popup.js for a complete example:

function watchPopup(popup, onClose) {
    if (popup) {
        if (watchPopup.watchTimer) {
            try {
                if (popup.closed) {
                    cancelPopup(popup, watchPopup.closeHandler)
                }

                if (popup.result) {
                    closePopup(popup, watchPopup.closeHandler);
                }
            }
            catch (e) {}
        } else {
            watchPopup.closeHandler = onClose;
            watchPopup.watchTimer = setInterval(
                watchPopup, 200, popup);
        }
    } else if (watchPopup.watchTimer) {
        clearInterval(watchPopup.watchTimer);
        watchPopup.watchTimer = null;
    }
}

Note that the try/catch block above handles JavaScript exception 0x800706b5 which is thrown when attempting to acess the popup window reference from the application while the popup displays a URI in another domain. This is a transient error that stops being thrown as soon as the popup is re-directed back to your domain (or localhost when testing).

Enabling popup styling for Facebook authentication

If you navigate to Facebook OAuth endpoint in a small popup window, it will display a full-screen Bootstrap-like error dialog telling you that the area isn't big enough to display the form. This error does seem to be transient, but even if you don't get it, the contents will be scrunched together and look unprofessional.

The solution has been provided by nlaq here: http://stackoverflow.com/a/27286681. It involves specifying a query string parameter to change the style into something more suitable for a popup.

See Startup.Auth.cs for a complete example:

public class PopupFacebookProvider : FacebookAuthenticationProvider
{
    public override void ApplyRedirect(FacebookApplyRedirectContext context)
    {
        context.Response.Redirect(context.RedirectUri + "&display=popup");
    }
}
app.UseFacebookAuthentication(new FacebookAuthenticationOptions
{
    AppId = ... ,
    AppSecret = ... ,

    Provider = new PopupFacebookProvider()
});

Specifying updated SSL certificate identifier for Twitter authentication

As of the time of this writing, posting to Twitter OAuth endpoint with default settings (fresh project unmodified from the template) will throw an exception:

The remote certificate is invalid according to the validation procedure

The two common causes are:

  • ASP.NET project uses a NuGet library with an outdated Twitter certificate (see below).
  • Fiddler was recently used to watch a Fiddler auth session, and replaced Twitter certificate with its own (see next section):

The solution for specifying an updated Twitter certificate has been provided by multiple contributors here: http://stackoverflow.com/questions/25011890/owin-twitter-login-the-remote-certificate-is-invalid-according-to-the-validati. See Startup.Auth.cs for a complete example on updating a certificate used to authenticate with Twitter:

app.UseTwitterAuthentication(new TwitterAuthenticationOptions
{
    ConsumerKey = ... ,
    ConsumerSecret = ... ,

    BackchannelCertificateValidator = new CertificateSubjectKeyIdentifierValidator(new[]
    {
        "A5EF0B11CEC04103A34A659048B21CE0572D7D47", // VeriSign Class 3 Secure Server CA - G2
        "0D445C165344C1827E1D20AB25F40163D8BE79A5", // VeriSign Class 3 Secure Server CA - G3
        "7FD365A7C2DDECBBF03009F34339FA02AF333133", // VeriSign Class 3 Public Primary Certification Authority - G5
        "39A55D933676616E73A761DFA16A7E59CDE66FAD", // Symantec Class 3 Secure Server CA - G4
        "5168FF90AF0207753CCCD9656462A212B859723B", // DigiCert SHA2 High Assurance Server C?A 
        "B13EC36903F8BF4701D498261A0802EF63642BC3"  // DigiCert High Assurance EV Root CA
    })
});

Cleaning Fiddler certificates

If Fiddler was recently used to debug traffic while authenticating with Twitter, the Twitter certificate will be replaced with a mock certificate created by Fiddler and installed in the user certificate store. This will cause Twitter to fail authentication on subsequent attempts because it uses certificate pinning. To solve this issue, clear the mock Twitter certificate from the personal user store (if you can, it's recommended that you clean all Fiddler certificates).

  • Click Start on a Windows PC where you are using Internet Explorer or Edge to work on your site
  • Start typing "cert" to get search results
  • Click on Manage user certificates result
  • Click on Personal folder on the left. If the list on the right has a Twitter certificate mocked by Fiddler (containing DO_NOT_TRUST in its name), delete it.
  • If this doesn't help, go through all folders and delete all certificates that have DO_NOT_TRUST in their name.
  • If this doesn't help, search for "cert" again on the Start menu and this time click on Manage computer certificates.
  • Go through all folders and delete all certificates that have DO_NOT_TRUST in their name.
  • You might be able to find a script that cleans all Fiddler certs from both stores.
  • Note that other browsers (such as Firefox) may have their own certificate stores. In that case you may have to find instructions to clear their respective stores.

Configuring user secrets

This demo assumes familiarity with basic steps for registering your application with an external login provider and getting application identifier and secret. Note that in this demo, I am using an external secrets file one level above the repository folder. Create a file called Secrets.config there according to these instructions: http://www.asp.net/identity/overview/features-api/best-practices-for-deploying-passwords-and-other-sensitive-data-to-aspnet-and-azure. Alternatively, replace logic that gets secrets from configuration with literal strings for quick testing.

About

This ASP.NET 4 MVC 5 project documents some common pitfalls when implementing external logins in a popup.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published