Example #1
0
        public async Task when_setting_disabled_logout_should_not_revoke_refreshtoken()
        {
            BffHost.BffOptions.RevokeRefreshTokenOnLogout = false;
            await BffHost.InitializeAsync();

            await BffHost.BffLoginAsync("alice", "sid");

            {
                var store  = IdentityServerHost.Resolve <IPersistedGrantStore>();
                var grants = await store.GetAllAsync(new PersistedGrantFilter
                {
                    SubjectId = "alice"
                });

                var rt = grants.Single(x => x.Type == "refresh_token");
                rt.Should().NotBeNull();
            }

            await BffHost.BffLogoutAsync("sid");

            {
                var store  = IdentityServerHost.Resolve <IPersistedGrantStore>();
                var grants = await store.GetAllAsync(new PersistedGrantFilter
                {
                    SubjectId = "alice"
                });

                var rt = grants.Single(x => x.Type == "refresh_token");
                rt.Should().NotBeNull();
            }
        }
Example #2
0
        public async Task user_endpoint_when_sliding_flag_is_passed_cookie_should_not_slide()
        {
            await BffHost.BffLoginAsync("alice");

            var sessions = await _sessionStore.GetUserSessionsAsync(new UserSessionsFilter { SubjectId = "alice" });

            sessions.Count().Should().Be(1);

            var session = sessions.Single();

            var ticketStore = BffHost.Resolve <IServerTicketStore>();
            var firstTicket = await ticketStore.RetrieveAsync(session.Key);

            firstTicket.Should().NotBeNull();

            _clock.UtcNow = _clock.UtcNow.AddMinutes(8);
            (await BffHost.GetIsUserLoggedInAsync("slide=false")).Should().BeTrue();

            var secondTicket = await ticketStore.RetrieveAsync(session.Key);

            secondTicket.Should().NotBeNull();

            (secondTicket.Properties.IssuedUtc == firstTicket.Properties.IssuedUtc).Should().BeTrue();
            (secondTicket.Properties.ExpiresUtc == firstTicket.Properties.ExpiresUtc).Should().BeTrue();
        }
Example #3
0
        public async Task logout_endpoint_for_anonymous_user_without_sid_should_succeed()
        {
            var response = await BffHost.BrowserClient.GetAsync(BffHost.Url("/bff/logout"));

            response.StatusCode.Should().Be(302); // endsession
            response.Headers.Location.ToString().ToLowerInvariant().Should().StartWith(IdentityServerHost.Url("/connect/endsession"));
        }
Example #4
0
        public async Task calls_to_remote_endpoint_should_require_csrf()
        {
            var req      = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/api_user_or_client/test"));
            var response = await BffHost.BrowserClient.SendAsync(req);

            response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
        }
Example #5
0
        public async Task custom_header_should_be_forwarded_and_xforwarded_headers_should_be_created()
        {
            BffHost.BffOptions.AddXForwardedHeaders = true;
            BffHost.BffOptions.ForwardedHeaders.Add("x-custom");

            await BffHost.InitializeAsync();

            var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/api_anon_only/test"));

            req.Headers.Add("x-csrf", "1");
            req.Headers.Add("x-custom", "custom");
            var response = await BffHost.BrowserClient.SendAsync(req);

            response.IsSuccessStatusCode.Should().BeTrue();
            var json = await response.Content.ReadAsStringAsync();

            var apiResult = JsonSerializer.Deserialize <ApiResponse>(json);

            apiResult.RequestHeaders.Count.Should().Be(4);

            apiResult.RequestHeaders["X-Forwarded-Host"].Single().Should().Be("app");
            apiResult.RequestHeaders["X-Forwarded-Proto"].Single().Should().Be("https");
            apiResult.RequestHeaders["Host"].Single().Should().Be("api");
            apiResult.RequestHeaders["x-custom"].Single().Should().Be("custom");
        }
        public async Task when_BackchannelLogoutAllUserSessions_is_true_backchannel_logout_should_logout_all_sessions()
        {
            BffHost.BffOptions.BackchannelLogoutAllUserSessions = true;

            await BffHost.BffLoginAsync("alice", "sid1");

            BffHost.BrowserClient.RemoveCookie("bff");
            await BffHost.BffLoginAsync("alice", "sid2");

            {
                var store    = BffHost.Resolve <IUserSessionStore>();
                var sessions = await store.GetUserSessionsAsync(new UserSessionsFilter { SubjectId = "alice" });

                sessions.Count().Should().Be(2);
            }

            await IdentityServerHost.RevokeSessionCookieAsync();

            {
                var store    = BffHost.Resolve <IUserSessionStore>();
                var sessions = await store.GetUserSessionsAsync(new UserSessionsFilter { SubjectId = "alice" });

                sessions.Should().BeEmpty();
            }
        }
Example #7
0
        public async Task calls_to_local_endpoint_without_antiforgery_should_not_require_csrf()
        {
            var req      = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/local_anon_no_csrf"));
            var response = await BffHost.BrowserClient.SendAsync(req);

            response.StatusCode.Should().Be(HttpStatusCode.OK);
        }
Example #8
0
        public async Task backchannel_logout_endpoint_should_revoke_refreshtoken()
        {
            await BffHost.BffLoginAsync("alice", "sid123");

            {
                var store  = IdentityServerHost.Resolve <IPersistedGrantStore>();
                var grants = await store.GetAllAsync(new PersistedGrantFilter
                {
                    SubjectId = "alice"
                });

                var rt = grants.Single(x => x.Type == "refresh_token");
                rt.Should().NotBeNull();
            }

            await IdentityServerHost.RevokeSessionCookieAsync();

            {
                var store  = IdentityServerHost.Resolve <IPersistedGrantStore>();
                var grants = await store.GetAllAsync(new PersistedGrantFilter
                {
                    SubjectId = "alice"
                });

                var rt = grants.Should().BeEmpty();
            }
        }
Example #9
0
        public async Task logout_endpoint_should_signout()
        {
            await BffHost.BffLoginAsync("alice", "sid123");

            await BffHost.BffLogoutAsync("sid123");

            (await BffHost.GetIsUserLoggedInAsync()).Should().BeFalse();
        }
Example #10
0
        public ApiUseForwardedHeaders()
        {
            ApiHost = new ApiHost(IdentityServerHost, "scope1", useForwardedHeaders: true);
            ApiHost.InitializeAsync().Wait();

            BffHost = new BffHost(IdentityServerHost, ApiHost, "spa", useForwardedHeaders: false);
            BffHost.InitializeAsync().Wait();
        }
        public async Task backchannel_logout_endpoint_should_signout()
        {
            await BffHost.BffLoginAsync("alice", "sid123");

            await IdentityServerHost.RevokeSessionCookieAsync();

            (await BffHost.GetIsUserLoggedInAsync()).Should().BeFalse();
        }
Example #12
0
        public void calls_to_bff_not_in_endpoint_routing_should_fail()
        {
            var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/invalid_endpoint/test"));

            Func <Task> f = () => BffHost.BrowserClient.SendAsync(req);

            f.Should().Throw <Exception>();
        }
Example #13
0
        public void calls_to_endpoint_without_bff_metadata_should_fail()
        {
            var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/not_bff_endpoint"));

            Func <Task> f = () => BffHost.BrowserClient.SendAsync(req);

            f.Should().Throw <Exception>();
        }
Example #14
0
        public async Task logout_endpoint_should_reject_non_local_returnUrl()
        {
            await BffHost.BffLoginAsync("alice", "sid123");

            Func <Task> f = () => BffHost.BrowserClient.GetAsync(BffHost.Url("/bff/logout") + "?sid=sid123&returnUrl=https://foo");

            f.Should().Throw <Exception>().And.Message.Should().Contain("returnUrl");
        }
Example #15
0
 public ServerSideTicketStoreTests()
 {
     BffHost.OnConfigureServices += services =>
     {
         services.AddSingleton <IUserSessionStore>(_sessionStore);
     };
     BffHost.InitializeAsync().Wait();
 }
Example #16
0
        public async Task logout_endpoint_should_redirect_to_external_signout_and_return_to_root()
        {
            await BffHost.BffLoginAsync("alice", "sid123");

            await BffHost.BffLogoutAsync("sid123");

            BffHost.BrowserClient.CurrentUri.ToString().ToLowerInvariant().Should().Be(BffHost.Url("/"));
            (await BffHost.GetIsUserLoggedInAsync()).Should().BeFalse();
        }
Example #17
0
        public async Task unauthenticated_calls_to_authorized_local_endpoint_should_fail()
        {
            var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/local_authz"));

            req.Headers.Add("x-csrf", "1");
            var response = await BffHost.BrowserClient.SendAsync(req);

            response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
        }
Example #18
0
        public async Task unauthenticated_api_call_should_return_401()
        {
            var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/always_fail_authz"));

            req.Headers.Add("x-csrf", "1");
            var response = await BffHost.BrowserClient.SendAsync(req);

            response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
        }
Example #19
0
        public async Task calls_to_local_endpoint_should_require_csrf()
        {
            await BffHost.BffLoginAsync("alice");

            var req      = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/local_anon"));
            var response = await BffHost.BrowserClient.SendAsync(req);

            response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
        }
Example #20
0
        public async Task login_endpoint_with_existing_session_should_challenge()
        {
            await BffHost.BffLoginAsync("alice");

            var response = await BffHost.BrowserClient.GetAsync(BffHost.Url("/bff/login"));

            response.StatusCode.Should().Be(HttpStatusCode.Redirect);
            response.Headers.Location.ToString().Should().StartWith(IdentityServerHost.Url("/connect/authorize"));
        }
Example #21
0
        public async Task user_endpoint_for_unauthenticated_user_should_fail()
        {
            var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/bff/user"));

            req.Headers.Add("x-csrf", "1");
            var response = await BffHost.BrowserClient.SendAsync(req);

            response.StatusCode.Should().Be(401);
        }
Example #22
0
        public async Task user_endpoint_for_authenticated_user_without_csrf_header_should_fail()
        {
            await BffHost.IssueSessionCookieAsync(new Claim("sub", "alice"), new Claim("foo", "foo1"), new Claim("foo", "foo2"));

            var req      = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/bff/user"));
            var response = await BffHost.BrowserClient.SendAsync(req);

            response.StatusCode.Should().Be(401);
        }
Example #23
0
        public async Task user_endpoint_when_uservalidate_renews_and_sliding_flag_is_passed_cookie_should_not_slide()
        {
            var shouldRenew = false;

            #if NET6_0_OR_GREATER
            BffHost.OnConfigureServices += services =>
            {
                services.Configure <CookieAuthenticationOptions>("cookie", options =>
                {
                    options.Events.OnCheckSlidingExpiration = ctx =>
                    {
                        ctx.ShouldRenew = shouldRenew;
                        return(Task.CompletedTask);
                    };
                });
            };
            #else
            BffHost.OnConfigureServices += services =>
            {
                services.Configure <CookieAuthenticationOptions>("cookie", options =>
                {
                    options.Events.OnValidatePrincipal = ctx =>
                    {
                        ctx.ShouldRenew = shouldRenew;
                        return(Task.CompletedTask);
                    };
                });
            };
            #endif

            await BffHost.InitializeAsync();

            await BffHost.BffLoginAsync("alice");

            var sessions = await _sessionStore.GetUserSessionsAsync(new UserSessionsFilter { SubjectId = "alice" });

            sessions.Count().Should().Be(1);

            var session = sessions.Single();

            var ticketStore = BffHost.Resolve <IServerTicketStore>();
            var firstTicket = await ticketStore.RetrieveAsync(session.Key);

            firstTicket.Should().NotBeNull();

            shouldRenew   = true;
            _clock.UtcNow = _clock.UtcNow.AddSeconds(1);
            (await BffHost.GetIsUserLoggedInAsync("slide=false")).Should().BeTrue();

            var secondTicket = await ticketStore.RetrieveAsync(session.Key);

            secondTicket.Should().NotBeNull();

            (secondTicket.Properties.IssuedUtc == firstTicket.Properties.IssuedUtc).Should().BeTrue();
            (secondTicket.Properties.ExpiresUtc == firstTicket.Properties.ExpiresUtc).Should().BeTrue();
        }
Example #24
0
        public async Task logout_endpoint_for_authenticated_should_require_sid()
        {
            await BffHost.BffLoginAsync("alice", "sid123");

            Func <Task> f = () => BffHost.BffLogoutAsync();

            f.Should().Throw <Exception>();

            (await BffHost.GetIsUserLoggedInAsync()).Should().BeTrue();
        }
        public async Task backchannel_logout_endpoint_for_incorrect_sid_should_not_logout_user()
        {
            await BffHost.BffLoginAsync("alice", "sid123");

            await IdentityServerHost.CreateIdentityServerSessionCookieAsync("alice", "sid999");

            await IdentityServerHost.RevokeSessionCookieAsync();

            (await BffHost.GetIsUserLoggedInAsync()).Should().BeTrue();
        }
Example #26
0
        public async Task unauthenticated_non_bff_endpoint_should_return_302_for_login()
        {
            var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/always_fail_authz_non_bff_endpoint"));

            req.Headers.Add("x-csrf", "1");
            var response = await BffHost.BrowserClient.SendAsync(req);

            response.StatusCode.Should().Be(HttpStatusCode.Redirect);
            response.Headers.Location.ToString().ToLowerInvariant().Should().StartWith(IdentityServerHost.Url("/connect/authorize"));
        }
Example #27
0
        public async Task logout_endpoint_for_authenticated_when_require_otpion_is_false_should_not_require_sid()
        {
            await BffHost.BffLoginAsync("alice", "sid123");

            BffHost.BffOptions.RequireLogoutSessionId = false;

            var response = await BffHost.BrowserClient.GetAsync(BffHost.Url("/bff/logout"));

            response.StatusCode.Should().Be(302); // endsession
            response.Headers.Location.ToString().ToLowerInvariant().Should().StartWith(IdentityServerHost.Url("/connect/endsession"));
        }
Example #28
0
        public async Task forbidden_api_call_should_return_403()
        {
            await BffHost.BffLoginAsync("alice");

            var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/always_fail_authz"));

            req.Headers.Add("x-csrf", "1");
            var response = await BffHost.BrowserClient.SendAsync(req);

            response.StatusCode.Should().Be(HttpStatusCode.Forbidden);
        }
Example #29
0
        public async Task user_endpoint_for_authenticated_user_should_return_claims()
        {
            await BffHost.IssueSessionCookieAsync(new Claim("sub", "alice"), new Claim("foo", "foo1"), new Claim("foo", "foo2"));

            var claims = await BffHost.GetUserClaimsAsync();

            claims.Length.Should().Be(3);
            claims.Should().Contain(new ClaimRecord("sub", "alice"));
            claims.Should().Contain(new ClaimRecord("foo", "foo1"));
            claims.Should().Contain(new ClaimRecord("foo", "foo2"));
        }
Example #30
0
        public async Task calls_to_remote_endpoint_with_useraccesstokenparameters_having_not_stored_corresponding_named_token_finds_no_matching_token_should_fail()
        {
            var loginResponse = await BffHostWithNamedTokens.BffLoginAsync("alice");

            var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/api_user_with_useraccesstokenparameters_having_not_stored_named_token/test"));

            req.Headers.Add("x-csrf", "1");

            Func <Task> f = () => BffHostWithNamedTokens.BrowserClient.SendAsync(req);

            f.Should().Throw <Exception>();
        }