public override void OnException(ExceptionContext context)
        {
            if (ShouldUserReauthenticate(context.Exception))
            {
                var properties = new AuthenticationProperties();

                // Set the scopes to request, including the scopes that the MSAL token provider needs.
                var scopesToRequest = new List <string> {
                    OpenIdConnectScope.OpenIdProfile, OpenIdConnectScope.OfflineAccess
                };
                if (this.Scopes != null && this.Scopes.Any())
                {
                    // Use the MSAL token provider to replace scope placeholders with their actual values from configuration.
                    var msalTokenProvider = context.HttpContext.RequestServices.GetRequiredService <MsalTokenProvider>();
                    scopesToRequest.AddRange(msalTokenProvider.GetFullyQualifiedScopes(this.Scopes));
                }
                properties.SetParameter(OpenIdConnectParameterNames.Scope, scopesToRequest);

                // Try to avoid displaying the "pick an account" dialog to the user if we already know who they are.
                properties.SetParameter(OpenIdConnectParameterNames.LoginHint, context.HttpContext.User.GetLoginHint());
                properties.SetParameter(OpenIdConnectParameterNames.DomainHint, context.HttpContext.User.GetDomainHint());

                context.Result           = new ChallengeResult(properties);
                context.ExceptionHandled = true;
            }

            base.OnException(context);
        }
예제 #2
0
        /// <summary>
        /// Build Authentication properties needed for an incremental consent.
        /// </summary>
        /// <param name="scopes">Scopes to request</param>
        /// <returns>AuthenticationProperties</returns>
        private AuthenticationProperties BuildAuthenticationPropertiesForIncrementalConsent(string[] scopes, MsalUiRequiredException ex)
        {
            AuthenticationProperties properties = new AuthenticationProperties();

            // Set the scopes, including the scopes that ADAL.NET / MASL.NET need for the Token cache
            string[] additionalBuildInScopes = new string[] { "openid", "offline_access", "profile" };
            properties.SetParameter <ICollection <string> >(OpenIdConnectParameterNames.Scope, scopes.Union(additionalBuildInScopes).ToList());

            // Attempts to set the login_hint to avoid the logged-in user to be presented with an account selection dialog
            string loginHint = HttpContext.User.GetLoginHint();

            if (!string.IsNullOrWhiteSpace(loginHint))
            {
                properties.SetParameter <string>(OpenIdConnectParameterNames.LoginHint, loginHint);

                string domainHint = HttpContext.User.GetDomainHint();
                properties.SetParameter <string>(OpenIdConnectParameterNames.DomainHint, domainHint);
            }

            // Additional claims required (for instance MFA)
            if (!string.IsNullOrEmpty(ex.Claims))
            {
                properties.Items.Add("claims", ex.Claims);
            }

            return(properties);
        }
예제 #3
0
        /// <summary>
        /// Build Authentication properties needed for incremental consent.
        /// </summary>
        /// <param name="scopes">Scopes to request</param>
        /// <param name="ex">MsalUiRequiredException instance</param>
        /// <param name="context">current http context in the pipeline</param>
        /// <returns>AuthenticationProperties</returns>
        private AuthenticationProperties BuildAuthenticationPropertiesForIncrementalConsent(
            string[] scopes,
            MsalUiRequiredException ex,
            HttpContext context)
        {
            var properties = new AuthenticationProperties();

            // Set the scopes, including the scopes that ADAL.NET / MSAL.NET need for the token cache
            string[] additionalBuiltInScopes =
            { OidcConstants.ScopeOpenId,
              OidcConstants.ScopeOfflineAccess,
              OidcConstants.ScopeProfile };
            properties.SetParameter <ICollection <string> >(OpenIdConnectParameterNames.Scope,
                                                            scopes.Union(additionalBuiltInScopes).ToList());

            // Attempts to set the login_hint to avoid the logged-in user to be presented with an account selection dialog
            var loginHint = context.User.GetLoginHint();

            if (!string.IsNullOrWhiteSpace(loginHint))
            {
                properties.SetParameter(OpenIdConnectParameterNames.LoginHint, loginHint);

                var domainHint = context.User.GetDomainHint();
                properties.SetParameter(OpenIdConnectParameterNames.DomainHint, domainHint);
            }

            // Additional claims required (for instance MFA)
            if (!string.IsNullOrEmpty(ex.Claims))
            {
                properties.Items.Add(OidcConstants.AdditionalClaims, ex.Claims);
            }

            return(properties);
        }
예제 #4
0
        protected override async Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            properties = properties ?? new AuthenticationProperties();

            if (Options.ValidateIssuer)
            {
                if (string.IsNullOrWhiteSpace(properties.GetParameter <string>(CookignConstants.Issuer)))
                {
                    properties.SetParameter(CookignConstants.Issuer, Options.CookingSettings.Issuer);
                }
            }
            if (Options.ValidateAudience)
            {
                if (string.IsNullOrWhiteSpace(properties.GetParameter <string>(CookignConstants.Audience)))
                {
                    properties.SetParameter(CookignConstants.Audience, Options.CookingSettings.Audience);
                }
            }
            if (Options.ValidateIpPublic)
            {
                if (properties.GetParameter <IPAddress>(CookignConstants.RemoteIp) == null)
                {
                    properties.SetParameter(CookignConstants.RemoteIp, Context.Connection.RemoteIpAddress);
                }
            }

            AuthenticationTicket ticket = new AuthenticationTicket(user, properties, Scheme.Name);

            string valueCookie = CreateProtector().Protect(ticket);

            CookieOptions options = new CookieOptions
            {
                HttpOnly = Options.HttpOnly,
                SameSite = Options.SameSiteMode,
                Secure   = Options.Secure,
                Expires  = DateTime.Now + Options.ExpireTimeSpan
            };


            Response.Cookies.Append(Options.CookieTokenName, valueCookie, options);

            if (Options.CreateCookieClaims)
            {
                options = new CookieOptions
                {
                    Expires = DateTime.Now + Options.ExpireTimeSpan
                };
                string claimsJson       = Newtonsoft.Json.JsonConvert.SerializeObject(from c in user.Claims select new { c.Type, c.Value });
                string cookieClaimValue = Convert.ToBase64String(Encoding.UTF8.GetBytes(claimsJson));
                Response.Cookies.Append(Options.CookieClaimsName, cookieClaimValue, options);
            }
        }
예제 #5
0
        /// <summary>
        /// Build authentication properties needed for incremental consent.
        /// </summary>
        /// <param name="scopes">Scopes to request.</param>
        /// <param name="ex"><see cref="MsalUiRequiredException"/> instance.</param>
        /// <param name="user">User.</param>
        /// <param name="userflow">Userflow being invoked for AAD B2C.</param>
        /// <returns>AuthenticationProperties.</returns>
        public static AuthenticationProperties BuildAuthenticationProperties(
            string[]?scopes,
            MsalUiRequiredException ex,
            ClaimsPrincipal user,
            string?userflow = null)
        {
            if (ex == null)
            {
                throw new ArgumentNullException(nameof(ex));
            }

            scopes ??= new string[0];
            var properties = new AuthenticationProperties();

            // Set the scopes, including the scopes that MSAL.NET needs for the token cache
            string[] additionalBuiltInScopes =
            {
                OidcConstants.ScopeOpenId,
                OidcConstants.ScopeOfflineAccess,
                OidcConstants.ScopeProfile,
            };

            HashSet <string> oidcParams = new HashSet <string>(scopes);

            oidcParams.UnionWith(additionalBuiltInScopes);
            properties.SetParameter(OpenIdConnectParameterNames.Scope, oidcParams.ToList());

            // Attempts to set the login_hint to avoid the logged-in user to be presented with an account selection dialog
            var loginHint = user.GetLoginHint();

            if (!string.IsNullOrWhiteSpace(loginHint))
            {
                properties.SetParameter(OpenIdConnectParameterNames.LoginHint, loginHint);

                var domainHint = user.GetDomainHint();
                properties.SetParameter(OpenIdConnectParameterNames.DomainHint, domainHint);
            }

            // Additional claims required (for instance MFA)
            if (!string.IsNullOrEmpty(ex.Claims))
            {
                properties.Items.Add(OidcConstants.AdditionalClaims, ex.Claims);
            }

            // Include current userflow for B2C
            if (!string.IsNullOrEmpty(userflow))
            {
                properties.Items.Add(OidcConstants.PolicyKey, userflow);
            }

            return(properties);
        }
예제 #6
0
        public async Task ChallengeWillIncludeScopeAsOverwrittenWithBaseAuthenticationProperties()
        {
            using var host = await CreateHost(
                      app => app.UseAuthentication(),
                      services =>
            {
                services.AddAuthentication().AddFacebook(o =>
                {
                    o.AppId     = "Test App Id";
                    o.AppSecret = "Test App Secret";
                    o.Scope.Clear();
                    o.Scope.Add("foo");
                    o.Scope.Add("bar");
                });
            },
                      async context =>
            {
                var properties = new AuthenticationProperties();
                properties.SetParameter(OAuthChallengeProperties.ScopeKey, new string[] { "baz", "qux" });
                await context.ChallengeAsync(FacebookDefaults.AuthenticationScheme, properties);
                return(true);
            });

            using var server = host.GetTestServer();
            var transaction = await server.SendAsync("http://example.com/challenge");

            var res = transaction.Response;

            Assert.Equal(HttpStatusCode.Redirect, res.StatusCode);
            Assert.Contains("scope=baz,qux", res.Headers.Location.Query);
        }
        public async Task <IActionResult> HrdRedirect([FromForm] string mail)
        {
            var p = new AuthenticationProperties()
            {
                RedirectUri = "/"
            };

            if (await IsLikelyAad(mail))
            {
                p.SetParameter <string>("login_hint", mail);
                p.SetParameter <string>("domain_hint", "aad");
                return(Challenge(p, OpenIdConnectDefaults.AuthenticationScheme));
            }
            p.SetParameter <string>("login_hint", mail);
            return(Challenge(p, OpenIdConnectDefaults.AuthenticationScheme));
        }
        private AuthenticateResult Fail(CaberMutualAuthenticationFailureReason failure)
        {
            var properties = new AuthenticationProperties();

            properties.SetParameter(FailureReasonEntry, failure);
            return(AuthenticateResult.Fail(new CaberMutualAuthenticationFailureReasonFormatter().Format(failure), properties));
        }
예제 #9
0
    public async Task RedirectToAuthorizeEndpoint_HasScopeAsOverwrittenWithBaseAuthenticationProperties()
    {
        using var host = await CreateHost(
                  s => s.AddAuthentication ().AddOAuth(
                      "Weblie",
                      opt =>
        {
            ConfigureDefaults(opt);
            opt.Scope.Clear();
            opt.Scope.Add("foo");
            opt.Scope.Add("bar");
        }),
                  async ctx =>
        {
            var properties = new AuthenticationProperties();
            properties.SetParameter(OAuthChallengeProperties.ScopeKey, new string[] { "baz", "qux" });
            await ctx.ChallengeAsync("Weblie", properties);
            return(true);
        });

        using var server = host.GetTestServer();
        var transaction = await server.SendAsync("https://www.example.com/challenge");

        var res = transaction.Response;

        Assert.Equal(HttpStatusCode.Redirect, res.StatusCode);
        Assert.Contains("scope=baz%20qux", res.Headers.Location.Query);
    }
예제 #10
0
        public async Task <IActionResult> Login(string returnUrl)
        {
            if (string.IsNullOrEmpty(returnUrl))
            {
                returnUrl = "~/";
            }

            if (Url.IsLocalUrl(returnUrl) == false && _interaction.IsValidReturnUrl(returnUrl) == false)
            {
                _logger.LogError($"User supplied invalid return url: {returnUrl}. Possibly a misconfiguration or malicious attempt for an attack.");
                return(this.RedirectToErrorPage());
            }

            var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

            var shouldUseMfa = context.Client.Properties.Where(p => p.Key == Insolvency.Interfaces.Constants.ShouldUseMfaKey).FirstOrDefault().Value;

            var props = new AuthenticationProperties
            {
                RedirectUri = Url.Action(nameof(Callback)),
                Items       =
                {
                    { "returnUrl", returnUrl                              },
                    { "scheme",    Constants.ScpAuthenticationSchemeAlias }
                }
            };

            if (!string.IsNullOrEmpty(shouldUseMfa))
            {
                props.SetParameter <bool>(Insolvency.Interfaces.Constants.ShouldUseMfaKey, bool.Parse(shouldUseMfa));
            }

            return(Challenge(props, Constants.ScpAuthenticationSchemeAlias));
        }
        private static TestServer CreateServer(Action <MicrosoftAccountOptions> configureOptions)
        {
            var builder = new WebHostBuilder()
                          .Configure(app =>
            {
                app.UseAuthentication();
                app.Use(async(context, next) =>
                {
                    var req = context.Request;
                    var res = context.Response;
                    if (req.Path == new PathString("/challenge"))
                    {
                        await context.ChallengeAsync("Microsoft", new AuthenticationProperties()
                        {
                            RedirectUri = "/me"
                        });
                    }
                    else if (req.Path == new PathString("/challengeWithOtherScope"))
                    {
                        var properties = new OAuthChallengeProperties();
                        properties.SetScope("baz", "qux");
                        await context.ChallengeAsync("Microsoft", properties);
                    }
                    else if (req.Path == new PathString("/challengeWithOtherScopeWithBaseAuthenticationProperties"))
                    {
                        var properties = new AuthenticationProperties();
                        properties.SetParameter(OAuthChallengeProperties.ScopeKey, new string[] { "baz", "qux" });
                        await context.ChallengeAsync("Microsoft", properties);
                    }
                    else if (req.Path == new PathString("/me"))
                    {
                        await res.DescribeAsync(context.User);
                    }
                    else if (req.Path == new PathString("/signIn"))
                    {
                        await Assert.ThrowsAsync <InvalidOperationException>(() => context.SignInAsync("Microsoft", new ClaimsPrincipal()));
                    }
                    else if (req.Path == new PathString("/signOut"))
                    {
                        await Assert.ThrowsAsync <InvalidOperationException>(() => context.SignOutAsync("Microsoft"));
                    }
                    else if (req.Path == new PathString("/forbid"))
                    {
                        await Assert.ThrowsAsync <InvalidOperationException>(() => context.ForbidAsync("Microsoft"));
                    }
                    else
                    {
                        await next();
                    }
                });
            })
                          .ConfigureServices(services =>
            {
                services.AddAuthentication(TestExtensions.CookieAuthenticationScheme)
                .AddCookie(TestExtensions.CookieAuthenticationScheme, o => { })
                .AddMicrosoftAccount(configureOptions);
            });

            return(new TestServer(builder));
        }
        public void GetSetParameter_String()
        {
            var props = new AuthenticationProperties();

            Assert.Null(props.GetParameter <string>("foo"));
            Assert.Equal(0, props.Parameters.Count);

            props.SetParameter <string>("foo", "foo bar");
            Assert.Equal("foo bar", props.GetParameter <string>("foo"));
            Assert.Equal("foo bar", props.Parameters["foo"]);
            Assert.Equal(1, props.Parameters.Count);

            props.SetParameter <string>("foo", null);
            Assert.Null(props.GetParameter <string>("foo"));
            Assert.Null(props.Parameters["foo"]);
            Assert.Equal(1, props.Parameters.Count);
        }
        public void GetSetParameter_Int()
        {
            var props = new AuthenticationProperties();

            Assert.Null(props.GetParameter <int?>("foo"));
            Assert.Equal(0, props.Parameters.Count);

            props.SetParameter <int?>("foo", 123);
            Assert.Equal(123, props.GetParameter <int?>("foo"));
            Assert.Equal(123, props.Parameters["foo"]);
            Assert.Equal(1, props.Parameters.Count);

            props.SetParameter <int?>("foo", null);
            Assert.Null(props.GetParameter <int?>("foo"));
            Assert.Null(props.Parameters["foo"]);
            Assert.Equal(1, props.Parameters.Count);
        }
        public void GetSetParameter_Collection()
        {
            var props = new AuthenticationProperties();

            Assert.Null(props.GetParameter <int?>("foo"));
            Assert.Equal(0, props.Parameters.Count);

            var list = new string[] { "a", "b", "c" };

            props.SetParameter <ICollection <string> >("foo", list);
            Assert.Equal(new string[] { "a", "b", "c" }, props.GetParameter <ICollection <string> >("foo"));
            Assert.Same(list, props.Parameters["foo"]);
            Assert.Equal(1, props.Parameters.Count);

            props.SetParameter <ICollection <string> >("foo", null);
            Assert.Null(props.GetParameter <ICollection <string> >("foo"));
            Assert.Null(props.Parameters["foo"]);
            Assert.Equal(1, props.Parameters.Count);
        }
예제 #15
0
        public IActionResult Google(string redirectTo = null)
        {
            var properties = new AuthenticationProperties
            {
                RedirectUri = string.IsNullOrEmpty(redirectTo) ? "/home" : redirectTo
            };

            if (Request.Cookies.TryGetValue(".Sub", out var subject) && !string.IsNullOrWhiteSpace(subject))
            {
                properties.SetParameter("login_hint", subject);
            }

            return(Challenge(properties, "Google"));
        }
예제 #16
0
        protected async override Task HandleChallengeAsync(AuthenticationProperties properties)
        {
            var res = await GetRequestTokenAsync();

            if (res.IsSuccess && res.RequestToken != null)
            {
                properties.SetParameter("RequestToken", res.RequestToken.code);
                var cookieOptions = Options.CorrelationCookie.Build(Context, DateTime.Now);
                Response.Cookies.Append("RequestToken", res.RequestToken.code, cookieOptions);
                if (properties.RedirectUri != null)
                {
                    Response.Cookies.Append("RedirectUri", properties.RedirectUri, cookieOptions);
                }
                await base.HandleChallengeAsync(properties);
            }
        }
예제 #17
0
        public async Task OnGetAsync()
        {
            var redirectUri = HttpContext.Request.Query["returnUrl"];

            if (string.IsNullOrWhiteSpace(redirectUri))
            {
                redirectUri = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}";
            }

            var authProperties = new AuthenticationProperties
            {
                RedirectUri = redirectUri
            };

            authProperties.SetParameter("login_hint", "signup");

            await HttpContext.ChallengeAsync("Auth0", authProperties);
        }
        public async Task Challenge_HasOverwrittenPromptParamFromBaseAuthenticationProperties()
        {
            var settings = new TestSettings(opt =>
            {
                opt.ClientId  = "Test Id";
                opt.Authority = TestServerBuilder.DefaultAuthority;
                opt.Prompt    = "consent";
            });
            var properties = new AuthenticationProperties();

            properties.SetParameter(OpenIdConnectChallengeProperties.PromptKey, "login");

            var server      = settings.CreateTestServer(properties);
            var transaction = await server.SendAsync(TestServerBuilder.TestHost + TestServerBuilder.ChallengeWithProperties);

            var res = transaction.Response;

            Assert.Equal(HttpStatusCode.Redirect, res.StatusCode);
            settings.ValidateChallengeRedirect(res.Headers.Location);
            Assert.Contains("prompt=login", res.Headers.Location.Query);
        }
        public async Task Challenge_HasOverwrittenMaxAgeParaFromBaseAuthenticationPropertiesm()
        {
            var settings = new TestSettings(opt =>
            {
                opt.ClientId  = "Test Id";
                opt.Authority = TestServerBuilder.DefaultAuthority;
                opt.MaxAge    = TimeSpan.FromSeconds(500);
            });
            var properties = new AuthenticationProperties();

            properties.SetParameter(OpenIdConnectChallengeProperties.MaxAgeKey, TimeSpan.FromSeconds(1234));

            var server      = settings.CreateTestServer(properties);
            var transaction = await server.SendAsync(TestServerBuilder.TestHost + TestServerBuilder.ChallengeWithProperties);

            var res = transaction.Response;

            Assert.Equal(HttpStatusCode.Redirect, res.StatusCode);
            settings.ValidateChallengeRedirect(res.Headers.Location);
            Assert.Contains("max_age=1234", res.Headers.Location.Query);
        }
        public async Task Challenge_HasOverwrittenScopeParamFromBaseAuthenticationProperties()
        {
            var settings = new TestSettings(opt =>
            {
                opt.ClientId  = "Test Id";
                opt.Authority = TestServerBuilder.DefaultAuthority;
                opt.Scope.Clear();
                opt.Scope.Add("foo");
                opt.Scope.Add("bar");
            });
            var properties = new AuthenticationProperties();

            properties.SetParameter(OpenIdConnectChallengeProperties.ScopeKey, new string[] { "baz", "qux" });

            var server      = settings.CreateTestServer(properties);
            var transaction = await server.SendAsync(TestServerBuilder.TestHost + TestServerBuilder.ChallengeWithProperties);

            var res = transaction.Response;

            Assert.Equal(HttpStatusCode.Redirect, res.StatusCode);
            settings.ValidateChallengeRedirect(res.Headers.Location);
            Assert.Contains("scope=baz%20qux", res.Headers.Location.Query);
        }
예제 #21
0
        public async Task <IActionResult> Login(UsersViewModel model)
        {
            ViewData["returnUrl"] = model.ReturnUrl;
            Users user = await _usersService.GetByStr(model.UserName, model.Password);

            if (user != null)
            {
                Dictionary <string, string> dis = new Dictionary <string, string>();
                dis.Add("NameUser", "Remark");
                dis.Add("Remark", "Remark");
                AuthenticationProperties props = new AuthenticationProperties(dis)
                {
                    IsPersistent = true,
                    ExpiresUtc   = DateTimeOffset.UtcNow.Add(TimeSpan.FromDays(1))
                };
                props.SetParameter <Users>("user", user);
                var claims = new List <Claim>()
                {
                    new Claim("NameUser", user.UserName),
                    new Claim("Remark", user.Remark)
                }.ToArray();

                await HttpContext.SignInAsync(user.UserName.ToString(), user.UserName, props);

                if (model.ReturnUrl != null)
                {
                    return(Redirect(model.ReturnUrl));
                }

                return(Redirect("/api/values"));
            }
            else
            {
                return(View());
            }
        }
예제 #22
0
    private static async Task <IHost> CreateHost(Action <MicrosoftAccountOptions> configureOptions)
    {
        var host = new HostBuilder()
                   .ConfigureWebHost(builder =>
                                     builder.UseTestServer()
                                     .Configure(app =>
        {
            app.UseAuthentication();
            app.Use(async(context, next) =>
            {
                var req = context.Request;
                var res = context.Response;
                if (req.Path == new PathString("/challenge"))
                {
                    await context.ChallengeAsync("Microsoft", new MicrosoftChallengeProperties
                    {
                        Prompt     = "select_account",
                        LoginHint  = "username",
                        DomainHint = "consumers",
#pragma warning disable CS0618 // Type or member is obsolete
                        ResponseMode = "query",
#pragma warning restore CS0618 // Type or member is obsolete
                        RedirectUri = "/me"
                    });
                }
                else if (req.Path == new PathString("/challengeWithOtherScope"))
                {
                    var properties = new OAuthChallengeProperties();
                    properties.SetScope("baz", "qux");
                    await context.ChallengeAsync("Microsoft", properties);
                }
                else if (req.Path == new PathString("/challengeWithOtherScopeWithBaseAuthenticationProperties"))
                {
                    var properties = new AuthenticationProperties();
                    properties.SetParameter(OAuthChallengeProperties.ScopeKey, new string[] { "baz", "qux" });
                    await context.ChallengeAsync("Microsoft", properties);
                }
                else if (req.Path == new PathString("/me"))
                {
                    await res.DescribeAsync(context.User);
                }
                else if (req.Path == new PathString("/signIn"))
                {
                    await Assert.ThrowsAsync <InvalidOperationException>(() => context.SignInAsync("Microsoft", new ClaimsPrincipal()));
                }
                else if (req.Path == new PathString("/signOut"))
                {
                    await Assert.ThrowsAsync <InvalidOperationException>(() => context.SignOutAsync("Microsoft"));
                }
                else if (req.Path == new PathString("/forbid"))
                {
                    await Assert.ThrowsAsync <InvalidOperationException>(() => context.ForbidAsync("Microsoft"));
                }
                else
                {
                    await next(context);
                }
            });
        })
                                     .ConfigureServices(services =>
        {
            services.AddAuthentication(TestExtensions.CookieAuthenticationScheme)
            .AddCookie(TestExtensions.CookieAuthenticationScheme, o => { })
            .AddMicrosoftAccount(configureOptions);
        }))
                   .Build();
        await host.StartAsync();

        return(host);
    }