1
votes

I'm wondering if it's possible for an ASP.NET 4.7 WebForm application to use the OAUTH authentication using the Authorization Code Flow with Proof Key for Code Exchange (PKCE) in order to not expose the token on the client side.

This is the code currently used in the Startup.Auth.cs class:

using System;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Owin.Security.OpenIdConnect;
using Microsoft.Owin.Security.Notifications;
using Owin;
using System.Threading.Tasks;
using System.Web;

public partial class Startup 
{
    string clientId = System.Configuration.ConfigurationManager.AppSettings["ClientId"];
    string redirectUri = System.Configuration.ConfigurationManager.AppSettings["RedirectUri"];
    static string tenant = System.Configuration.ConfigurationManager.AppSettings["Tenant"];
    string authority = String.Format(System.Globalization.CultureInfo.InvariantCulture, System.Configuration.ConfigurationManager.AppSettings["Authority"], tenant);


    public void ConfigureAuth(IAppBuilder app)
    {
        var provider = new CookieAuthenticationProvider();
        provider.OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, User>(
                            validateInterval: TimeSpan.FromMinutes(60),
                            regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager));



        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
        //Workaround for Katana bug #197
        app.UseKentorOwinCookieSaver();
        //******************************
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
            SlidingExpiration = true,
            ExpireTimeSpan = TimeSpan.FromMinutes(60),
            LoginPath = new PathString("/Account/Login"),
            CookieSecure = CookieSecureOption.Always,
            Provider = provider
        });
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);


        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
        app.UseCookieAuthentication(new CookieAuthenticationOptions());
        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
            // Sets the ClientId, authority, RedirectUri as obtained from web.config
            ClientId = clientId,
                Authority = authority,
                RedirectUri = redirectUri,
                AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive,
            PostLogoutRedirectUri = redirectUri,
                Scope = OpenIdConnectScope.OpenIdProfile,
            ResponseType = OpenIdConnectResponseType.IdToken,
            TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuer = false
                },
            Notifications = new OpenIdConnectAuthenticationNotifications
                {

                AuthenticationFailed = OnAuthenticationFailed,
                    AuthorizationCodeReceived = (context) =>
                    {
                        return Task.FromResult(0);
                    },
                    SecurityTokenValidated = (context) =>
                    {
                        return Task.FromResult(0);
                    },
                    SecurityTokenReceived = (context) =>
                    {
                        return Task.FromResult(0);
                    }
                }
            }
        );
    }
    ...
}

Is there a way to do it, or maybe it's not necessary because "Authorization Code" flow improve the security only in Single Page Applications?

Ref: https://auth0.com/docs/authorization/which-oauth-2-0-flow-should-i-use

1

1 Answers

1
votes

Should work fine - the flow is determined by the response_type field:

  • Implicit flow would use 'token' or 'token id_token' - it does not look like you are using that. It is recommended to avoid including token, since that returns tokens in URLs and they could leak

  • Use code flow via 'code' - though I believe the MS libraries may require you to use the hybrid flow of 'code id_token'. Both are secure designs.

PKCE is needed for single page apps, since they cannot store a client secret. For your server side app it is less important since the secret is not revealed to the browser. I don't think those MS server side libraries support PKCE.