Untitled

 avatar
unknown
plain_text
2 years ago
14 kB
3
Indexable
using System;
using System.Configuration;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Helpers;
using Abp.Extensions;
using Abp.Owin;
using Hangfire;
using IdentityModel;
using IdentityModel.Client;
using Microsoft.AspNet.Identity;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.Facebook;
using Microsoft.Owin.Security.Google;
using Microsoft.Owin.Security.Notifications;
using Microsoft.Owin.Security.OpenIdConnect;
using Microsoft.Owin.Security.Twitter;
using Nascence.BodynitsPortal.Web;
using Nascence.BodynitsPortal.WebApi.Controllers;
using NLog;
using Owin;

[assembly: OwinStartup(typeof(Startup))]

namespace Nascence.BodynitsPortal.Web
{
    public class Startup
    {
        private static Logger _logger = LogManager.GetCurrentClassLogger();

        public void Configuration(IAppBuilder app)
        {
            app.UseAbp();

            app.UseOAuthBearerAuthentication(AccountController.OAuthBearerOptions);
            app.UseKentorOwinCookieSaver();
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login")
            });

            //app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

            //if (IsTrue("ExternalAuth.Facebook.IsEnabled"))
            //{
            //    app.UseFacebookAuthentication(CreateFacebookAuthOptions());                
            //}

            //if (IsTrue("ExternalAuth.Twitter.IsEnabled"))
            //{
            //    app.UseTwitterAuthentication(CreateTwitterAuthOptions());                
            //}

            //if (IsTrue("ExternalAuth.Google.IsEnabled"))
            //{
            //    app.UseGoogleAuthentication(CreateGoogleAuthOptions());                
            //}

            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

            if (IsTrue("ExternalAuth.OpenId.IsEnabled"))
            {
                app.UseOpenIdConnectAuthentication(CreateOpenIdOptions());
            }

            app.MapSignalR();

            //Enable it to use HangFire dashboard (uncomment only if it's enabled in BodynitsPortalWebModule)
            //app.UseHangfireDashboard();
        }

        private static OpenIdConnectAuthenticationOptions CreateOpenIdOptions()
        {
            AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;

            var options = new OpenIdConnectAuthenticationOptions
            {
                Authority = AppHelper.IdentityHelper.OpenIdAuthority,
                ClientId = AppHelper.IdentityHelper.OpenIdClientId,
                PostLogoutRedirectUri = AppHelper.IdentityHelper.OpenIdPostLogoutRedirectUri,
                RedirectUri = AppHelper.IdentityHelper.OpenIdRedirectUri,
                RequireHttpsMetadata = false,
                SignInAsAuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                UseTokenLifetime = false,
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    RedirectToIdentityProvider = (n) =>
                    {
                        // if signing out, add the id_token_hint
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                        }
                        else if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
                        {
                            var tenancyName = "DEF";
                            if (tenancyName != null)
                            {
                                //n.ProtocolMessage.Parameters.Add("tenancy_name", tenancyName.Last());
                                n.ProtocolMessage.Parameters.Add("tenancy_name", tenancyName);
                                HttpCookie tenancyNameCookie = new HttpCookie("tenancyNameCookie");
                                //tenancyNameCookie["tenancy_name"] = tenancyName.Last();
                                tenancyNameCookie["tenancy_name"] = tenancyName;
                                var response = HttpContext.Current.Response;
                                response.Cookies.Add(tenancyNameCookie);
                            }

                            // set PKCE parameters
                            var codeVerifier = CryptoRandom.CreateUniqueId(32);

                            string codeChallenge;
                            using (var sha256 = SHA256.Create())
                            {
                                var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
                                codeChallenge = Base64Url.Encode(challengeBytes);
                            }

                            n.ProtocolMessage.SetParameter("code_challenge", codeChallenge);
                            n.ProtocolMessage.SetParameter("code_challenge_method", "S256");

                            // remember code_verifier (adapted from OWIN nonce cookie)
                            RememberCodeVerifier(n, codeVerifier);
                        }

                        return Task.FromResult(0);
                    },
                    AuthenticationFailed = (n) =>
                    {
                        try
                        {
                            _logger.Info("Authentication Failed");
                            _logger.Info(n.Exception);
                            _logger.Info(n.Response?.StatusCode);
                            _logger.Info(n.Response?.ReasonPhrase);
                            n.HandleResponse();
                            n.Response.Redirect("/Application/Index");
                            return Task.FromResult(0);
                        }
                        catch (Exception ex)
                        {
                            throw ex;
                        };
                    },
                    AuthorizationCodeReceived = async n =>
                    {

                        var client = new HttpClient();

                        // get code_verifier
                        var codeVerifier = RetrieveCodeVerifier(n);

                        // attach code_verifier
                        n.TokenEndpointRequest.SetParameter("code_verifier", codeVerifier);

                        var tokenResponse = await client.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest()
                        {
                            Address = AppHelper.IdentityHelper.OpenIdTokenEndpoint,
                            ClientId = AppHelper.IdentityHelper.OpenIdClientId,
                            ClientSecret = AppHelper.IdentityHelper.OpenIdClientSecret,
                            Code = n.Code,
                            RedirectUri = n.RedirectUri,
                            CodeVerifier = codeVerifier,
                        });

                        if (tokenResponse.IsError)
                        {
                            throw new Exception(tokenResponse.Error);
                        }

                        var userInfoResponse = await client.GetUserInfoAsync(new UserInfoRequest()
                        {
                            Address = AppHelper.IdentityHelper.OpenIdUserInfoEndpoint,
                            Token = tokenResponse.AccessToken,
                        });

                        // create new identity
                        var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                        id.AddClaims(userInfoResponse.Claims);

                        id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
                        id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
                        id.AddClaim(new Claim("iss", n.AuthenticationTicket.Identity.FindFirst("iss").Value));
                        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));
                        id.AddClaim(new Claim(ClaimTypes.NameIdentifier, userInfoResponse.Claims.FirstOrDefault(x => x.Type == "preferred_username").Value));

                        n.AuthenticationTicket = new AuthenticationTicket(
                        new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, ClaimTypes.NameIdentifier, "role"),
                            n.AuthenticationTicket.Properties);

                    }
                    
                }
            };

            var clientSecret = ConfigurationManager.AppSettings["ExternalAuth.OpenId.ClientSecret"];
            if (!clientSecret.IsNullOrEmpty())
            {
                options.ClientSecret = clientSecret;
            }

            return options;
        }

        private static void RememberCodeVerifier(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> n, string codeVerifier)
        {
            var properties = new AuthenticationProperties();
            properties.Dictionary.Add("cv", codeVerifier);
            n.Options.CookieManager.AppendResponseCookie(
                n.OwinContext,
                GetCodeVerifierKey(n.ProtocolMessage.State),
                Convert.ToBase64String(Encoding.UTF8.GetBytes(n.Options.StateDataFormat.Protect(properties))),
                new CookieOptions
                {
                    SameSite = SameSiteMode.None,
                    HttpOnly = true,
                    Secure = n.Request.IsSecure,
                    Expires = DateTime.UtcNow + n.Options.ProtocolValidator.NonceLifetime
                });
        }

        private static string RetrieveCodeVerifier(AuthorizationCodeReceivedNotification n)
        {
            string key = GetCodeVerifierKey(n.ProtocolMessage.State);

            string codeVerifierCookie = n.Options.CookieManager.GetRequestCookie(n.OwinContext, key);
            if (codeVerifierCookie != null)
            {
                var cookieOptions = new CookieOptions
                {
                    SameSite = SameSiteMode.None,
                    HttpOnly = true,
                    Secure = n.Request.IsSecure
                };

                n.Options.CookieManager.DeleteCookie(n.OwinContext, "cv", cookieOptions);
            }

            var cookieProperties = n.Options.StateDataFormat.Unprotect(Encoding.UTF8.GetString(Convert.FromBase64String(codeVerifierCookie)));
            cookieProperties.Dictionary.TryGetValue("cv", out var codeVerifier);

            return codeVerifier;
        }

        private static string GetCodeVerifierKey(string state)
        {
            using (var hash = SHA256.Create())
            {
                return OpenIdConnectAuthenticationDefaults.CookiePrefix + "cv." + Convert.ToBase64String(hash.ComputeHash(Encoding.UTF8.GetBytes(state)));
            }
        }

        private static FacebookAuthenticationOptions CreateFacebookAuthOptions()
        {
            var options = new FacebookAuthenticationOptions
            {
                AppId = ConfigurationManager.AppSettings["ExternalAuth.Facebook.AppId"],
                AppSecret = ConfigurationManager.AppSettings["ExternalAuth.Facebook.AppSecret"]
            };

            options.Scope.Add("email");
            options.Scope.Add("public_profile");

            return options;
        }

        private static TwitterAuthenticationOptions CreateTwitterAuthOptions()
        {
            return new TwitterAuthenticationOptions
            {
                ConsumerKey = ConfigurationManager.AppSettings["ExternalAuth.Twitter.ConsumerKey"],
                ConsumerSecret = ConfigurationManager.AppSettings["ExternalAuth.Twitter.ConsumerSecret"]
            };
        }

        private static GoogleOAuth2AuthenticationOptions CreateGoogleAuthOptions()
        {
            return new GoogleOAuth2AuthenticationOptions
            {
                ClientId = ConfigurationManager.AppSettings["ExternalAuth.Google.ClientId"],
                ClientSecret = ConfigurationManager.AppSettings["ExternalAuth.Google.ClientSecret"]
            };
        }

        private static bool IsTrue(string appSettingName)
        {
            return string.Equals(
                ConfigurationManager.AppSettings[appSettingName],
                "true",
                StringComparison.InvariantCultureIgnoreCase);
        }
    }
}
Editor is loading...