Example #1
0
            public Task OnRedirectToIdentityProvider(RedirectContext context, TokenProviderConfiguration configuration)
            {
                _logger?.Message("Redirecting");
                var defaultPolicy = _azureOptions.DefaultPolicy;

                if (context.Properties.Items.TryGetValue(AzureAdB2COptions.PolicyAuthenticationProperty, out var policy) &&
                    !policy.Equals(defaultPolicy))
                {
                    context.ProtocolMessage.Scope         = OpenIdConnectScope.OpenIdProfile;
                    context.ProtocolMessage.ResponseType  = OpenIdConnectResponseType.IdToken;
                    context.ProtocolMessage.IssuerAddress = context.ProtocolMessage.IssuerAddress.ToLower()
                                                            .Replace($"/{defaultPolicy.ToLower()}/", $"/{policy.ToLower()}/");
                    context.Properties.Items.Remove(AzureAdB2COptions.PolicyAuthenticationProperty);
                }
                if (_upgradeHttp)
                {
                    if (context.ProtocolMessage.RedirectUri.StartsWith("http://"))
                    {
                        context.ProtocolMessage.RedirectUri = context.ProtocolMessage.RedirectUri.Replace("http://", "https://");
                    }
                }
                if (IsMfaRequired(context, configuration))
                {
                    context.ProtocolMessage.SetParameter("mfa_required", "true");
                }
                return(Task.CompletedTask);
            }
        public static IAppBuilder UseVeracityAuthentication(this IAppBuilder app, TokenProviderConfiguration configuration, Func <IOwinContext, bool> isMfaRequiredOptions = null)
        {
            _conditionalMfaFunc = isMfaRequiredOptions;
            _redirectUrl        = configuration.RedirectUrl;
            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                // Generate the metadata address using the tenant and policy information
                MetadataAddress = Authority(configuration),
                // These are standard OpenID Connect parameters, with values pulled from web.config
                ClientId              = ClientId(configuration),
                RedirectUri           = configuration.RedirectUrl,
                PostLogoutRedirectUri = configuration.RedirectUrl,
                ClientSecret          = configuration.ClientSecret,
                ResponseType          = "code id_token",
                // Specify the callbacks for each type of notifications
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    RedirectToIdentityProvider = notification => OnRedirectToIdentityProvider(notification, configuration),
                    AuthorizationCodeReceived  = notification => OnAuthorizationCodeReceived(notification, configuration),
                    AuthenticationFailed       = notification => OnAuthenticationFailed(notification, configuration),
                },

                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name"
                },
                // Specify the scope by appending all of the scopes requested into one string (seperated by a blank space)
                Scope = $"{OpenIdConnectScopes.OpenId} offline_access {configuration.Scope}"
            }
                );
            return(app);
        }
Example #3
0
            private static async Task <ValidationResult> ValidatePolicies(TokenProviderConfiguration configuration,
                                                                          IPolicyValidation policyValidator, string protocolMessageRedirectUri)
            {
                var policy = configuration.ServiceId != null
                    ? await policyValidator.ValidatePolicyWithServiceSpesificTerms(configuration.ServiceId, protocolMessageRedirectUri)
                    : await policyValidator.ValidatePolicy(protocolMessageRedirectUri);

                return(policy);
            }
        public static IServiceCollection AddVeracity(this IServiceCollection services, IConfiguration configuration, string key, out TokenProviderConfiguration tokenProviderConfiguration)
        {
            ConfigurationManagerHelper.SetManager(new NullConfig());

            var t = new TokenProviderConfiguration();

            configuration.Bind(key, t);
            tokenProviderConfiguration = t;
            return(services);
        }
        public static IConfidentialClientApplication ConfidentialClientApplication(this TokenProviderConfiguration configuration,
                                                                                   TokenCacheBase cache, Action <string> _debugLogger)
        {
            var context = ConfidentialClientApplicationBuilder.Create(ClientId(configuration))
                          .WithClientSecret(configuration.ClientSecret).WithB2CAuthority(Authority(configuration))//.WithAuthority(Authority(configuration),false)//.WithB2CAuthority(Authority(configuration))
                          .WithRedirectUri(configuration.RedirectUrl)
                          .WithLogging((level, message, pii) => { _debugLogger?.Invoke(message); })
                          .Build();

            cache.SetCacheInstance(context.UserTokenCache);
            return(context);
        }
Example #6
0
            internal void Configure(string name, OpenIdConnectOptions options, TokenProviderConfiguration configuration)
            {
                options.ClientId         = _azureOptions.ClientId;
                options.Authority        = $"{_azureOptions.Instance}/{_azureOptions.Domain}/{_azureOptions.SignUpSignInPolicyId}/v2.0";
                options.UseTokenLifetime = true;
                options.CallbackPath     = _azureOptions.CallbackPath;

                options.TokenValidationParameters = new TokenValidationParameters {
                    NameClaimType = "name"
                };
                var handler = options.Events.OnAuthorizationCodeReceived;

                options.Events = new OpenIdConnectEvents
                {
                    OnRedirectToIdentityProvider = context => OnRedirectToIdentityProvider(context, configuration),
                    OnRemoteFailure             = OnRemoteFailure,
                    OnAuthorizationCodeReceived = context => OnAuthorizationCodeReceived(context, configuration, handler)
                };
            }
        private static Task OnRedirectToIdentityProvider(
            RedirectToIdentityProviderNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification, TokenProviderConfiguration configuration)
        {
            var policy = notification.OwinContext.Get <string>("Policy");

            if (!string.IsNullOrEmpty(policy) && !policy.Equals(DefaultPolicy(configuration)))
            {
                notification.ProtocolMessage.Scope         = OpenIdConnectScopes.OpenId;
                notification.ProtocolMessage.ResponseType  = OpenIdConnectResponseTypes.IdToken;
                notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.ToLower().Replace(DefaultPolicy(configuration).ToLower(), policy.ToLower());
            }
            if (IsMfaRequired(notification, configuration))
            {
                notification.ProtocolMessage.SetParameter("mfa_required", "true");
            }
            return(Task.FromResult(0));
        }
 public static object AppUrl(TokenProviderConfiguration configuration) => configuration.RedirectUrl.EndsWith("/") ? configuration.RedirectUrl.Remove(configuration.RedirectUrl.Length - 1, 1) : configuration.RedirectUrl;
 public static object TenantId(TokenProviderConfiguration configuration) => configuration.TenantId;
 public static string DefaultPolicy(TokenProviderConfiguration configuration) => configuration.Policy;
 private static bool IsMfaRequired(AuthorizationCodeReceivedNotification context, TokenProviderConfiguration configuration)
 {
     return(configuration.RequireMfa || (_conditionalMfaFunc?.Invoke(context.OwinContext) ?? false));
 }
 public static string Authority(TokenProviderConfiguration configuration) => $"{configuration.Instance}{(configuration.Instance.EndsWith("/")?"":"/")}tfp/{TenantId(configuration)}/{configuration.Policy}/v2.0/.well-known/openid-configuration";
        private static async Task ExchangeAuthCodeWithToken(AuthorizationCodeReceivedNotification notification, TokenProviderConfiguration configuration)
        {
            HttpContext.Current.User = new ClaimsPrincipal(notification.AuthenticationTicket.Identity);
            var c       = HttpContext.Current;
            var cache   = CacheFactoryFunc().Invoke();
            var context = configuration.ConfidentialClientApplication(cache, _debugLogger);
            var user    = await context.AcquireTokenByAuthorizationCode(new[] { configuration.Scope }, notification.Code)
                          .ExecuteAsync();

            HttpContext.Current = c;
        }
Example #14
0
 private TokenProvider(TokenProviderConfiguration configuration)
 {
     _configuration = configuration;
 }
Example #15
0
 private TokenProvider(IServiceProvider appApplicationServices, TokenProviderConfiguration configuration)
 {
     _configuration = configuration;
 }
Example #16
0
 public static string Authority(TokenProviderConfiguration configuration) => $"https://login.microsoftonline.com/tfp/{configuration.TenantId}/{configuration.Policy}/v2.0/.well-known/openid-configuration";
Example #17
0
 private static bool IsMfaRequired(AuthorizationCodeReceivedContext context, TokenProviderConfiguration configuration)
 {
     return(configuration.RequireMfa || (_conditionalMfaFunc?.Invoke(context.HttpContext, context.Properties) ?? false));
 }
 public TokenProvider(TokenProviderConfiguration tokenProviderConfiguration)
 {
     this.tokenProviderConfiguration = tokenProviderConfiguration;
 }
        /*
         * Catch any failures received by the authentication middleware and handle appropriately
         */
        private static Task OnAuthenticationFailed(
            AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification, TokenProviderConfiguration configuration)
        {
            _errorLogger?.Invoke(notification.Exception, "external error");
            notification.HandleResponse();

            // Handle the error code that Azure AD B2C throws when trying to reset a password from the login page
            // because password reset is not supported by a "sign-up or sign-in policy"
            if (notification.ProtocolMessage.ErrorDescription != null && notification.ProtocolMessage.ErrorDescription.Contains("AADB2C90118"))
            {
                // If the user clicked the reset password link, redirect to the reset password route
                notification.Response.Redirect("/Account/ResetPassword");
            }
            else if (notification.Exception.Message == "access_denied")
            {
                notification.Response.Redirect("/");
            }
            else
            {
                notification.Response.Redirect(string.Format(configuration.ErrorPage ?? "/error?message={0}", notification.Exception?.Message));
            }

            return(Task.FromResult(0));
        }
Example #20
0
 internal void Configure(OpenIdConnectOptions options, TokenProviderConfiguration configuration)
 {
     _logger?.Message("Configuring");
     Configure(Options.DefaultName, options, configuration);
 }
        /*
         * Callback function when an authorization code is received
         */
        private static async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification, TokenProviderConfiguration configuration)
        {
            var ct = HttpContext.Current;

            try
            {
                if (IsMfaRequired(notification, configuration) && !notification.AuthenticationTicket.Identity.Claims.Any(c => c.Type == "mfa_required" && c.Value == "true"))
                {
                    throw new UnauthorizedAccessException("MFA required");
                }
                await ExchangeAuthCodeWithToken(notification, configuration);

                try
                {
                    await ValidatePolicies(notification);

                    notification.OwinContext.Authentication.SignIn(notification.AuthenticationTicket.Identity);
                    notification.Response.Redirect(notification.RedirectUri);
                    notification.HandleResponse();
                    HttpContext.Current = ct;
                }
                catch (AggregateException aex)
                {
                    _exceptionLogger?.Invoke(aex);
                    if (aex.InnerException != null)
                    {
                        _exceptionLogger?.Invoke(aex.InnerException);
                    }
                    HttpContext.Current = ct;
                    if (aex.InnerException is ServerException serverException)
                    {
                        HandlePolicyViolation(notification, serverException);
                    }
                }
                catch (ServerException ex)
                {
                    _exceptionLogger?.Invoke(ex);
                    HttpContext.Current = ct;
                    HandlePolicyViolation(notification, ex);
                }
            }
            catch (Exception ex)
            {
                HttpContext.Current = ct;
                _exceptionLogger?.Invoke(ex);
                throw;
            }
        }
 public static string Authority(TokenProviderConfiguration configuration) => $"{ConfigurationManagerHelper.GetValueOnKey("Instance", "https://login.veracity.com/")}{TenantId(configuration)}/{configuration.Policy}/v2.0/.well-known/openid-configuration";
 private static bool IsMfaRequired(RedirectToIdentityProviderNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context, TokenProviderConfiguration configuration)
 {
     return(configuration.RequireMfa || (_conditionalMfaFunc?.Invoke(context.OwinContext) ?? false));
 }
 public static string ClientId(TokenProviderConfiguration configuration) => configuration.ClientId;
Example #25
0
            private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext arg, TokenProviderConfiguration configuration, Func <AuthorizationCodeReceivedContext, Task> handler)
            {
                _logger?.Message("Auth code received...");
                var timer = Stopwatch.StartNew();

                try
                {
                    arg.HttpContext.User = arg.Principal;
                    if (IsMfaRequired(arg, configuration) && !arg.Principal.Claims.Any(c => c.Type == "mfa_required" && c.Value == "true"))
                    {
                        throw new UnauthorizedAccessException("MFA required");
                    }
                    var cache   = arg.HttpContext.RequestServices.GetService <TokenCacheBase>();
                    var context = configuration.ConfidentialClientApplication(cache, s => { _logger?.Message(s); });
                    var user    = await context.AcquireTokenByAuthorizationCode(new[] { configuration.Scope }, arg.ProtocolMessage.Code).ExecuteAsync();

                    _logger?.Message($"exchanging code with access token took: {timer.ElapsedMilliseconds}ms");
                    var policyValidator = arg.HttpContext.RequestServices.GetService <IPolicyValidation>();
                    try
                    {
                        if (policyValidator != null)
                        {
                            var timer2 = Stopwatch.StartNew();
                            var policy = await ValidatePolicies(configuration, policyValidator, arg.ProtocolMessage.RedirectUri ?? configuration.PolicyRedirectUrl ?? configuration.RedirectUrl);

                            timer2.Stop();
                            _logger?.Message($"Policy check took {timer2.ElapsedMilliseconds}ms. ");
                            if (policy.AllPoliciesValid)
                            {
                                _logger?.Message("Policies validated!");
                                AdditionalAuthCodeHandling?.Invoke(arg);
                            }
                            else
                            {
                                _logger?.Message("Not all policies is valid, redirecting to Veracity");
                                arg.Response.Redirect(policy.RedirectUrl); //Getting the redirect url from the error message.
                                arg.HandleResponse();
                            }
                        }
                        else
                        {
                            AdditionalAuthCodeHandling?.Invoke(arg);
                        }
                    }
                    catch (AggregateException aex)
                    {
                        var e = aex.InnerException as ServerException;
                        if (e != null)
                        {
                            HandleServerException(arg, e);
                        }
                    }
                    catch (ServerException ex)
                    {
                        HandleServerException(arg, ex);
                    }
                }
                catch (Exception ex)
                {
                    ex.Log();
                }
                timer.Stop();
                _logger?.Message($"Total on code received  took {timer.ElapsedMilliseconds}ms. ");
                await handler(arg);
            }
Example #26
0
        public static AuthenticationBuilder AddAzureAdB2C(this AuthenticationBuilder builder, Action <AzureAdB2COptions> configureOptions, TokenProviderConfiguration configuration)
        {
            _builder = builder;
            builder.Services.Configure(configureOptions);

            builder.Services.AddSingleton <IConfigureOptions <OpenIdConnectOptions>, ConfigureAzureOptions>()
            .AddScoped <ITokenHandler, TokenProvider>()
            .AddSingleton <TokenProviderConfiguration, TokenProviderConfiguration>()
            .AddHttpContextAccessor()
            .AddSingleton <ILogger, LogWrapper>()
            .AddSingleton <ILogging, LogWrapper>()
            .AddScoped(s => s.GetService <IHttpContextAccessor>().HttpContext.User)

            .AddScoped <TokenCacheBase>(s => new DistributedTokenCache(s.GetService <IHttpContextAccessor>().HttpContext.User, s.GetService <IDistributedCache>(), s.GetService <ILogger>(), s.GetService <IDataProtector>()));
            builder.AddOpenIdConnect(opts =>
            {
                _upgradeHttp = configuration.UpgradeHttp;
                opts.Scope.Add(configuration.Scope);
                opts.Scope.Add("openid");
                opts.Scope.Add("offline_access");
                opts.ClientSecret         = configuration.ClientSecret;
                opts.AuthenticationMethod = OpenIdConnectRedirectBehavior.FormPost;
                opts.ResponseType         = "code id_token";
            });

            return(builder);
        }