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();
        }
        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 #4
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 #5
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");
        }
        public async Task backchannel_logout_endpoint_should_signout()
        {
            await BffHost.BffLoginAsync("alice", "sid123");

            await IdentityServerHost.RevokeSessionCookieAsync();

            (await BffHost.GetIsUserLoggedInAsync()).Should().BeFalse();
        }
Example #7
0
        public async Task logout_endpoint_should_signout()
        {
            await BffHost.BffLoginAsync("alice", "sid123");

            await BffHost.BffLogoutAsync("sid123");

            (await BffHost.GetIsUserLoggedInAsync()).Should().BeFalse();
        }
Example #8
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 #9
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 #10
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 #11
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();
        }
        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 #13
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();
        }
Example #14
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 #15
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 #16
0
        public async Task response_status_403_from_remote_endpoint_should_return_403_from_bff()
        {
            await BffHost.BffLoginAsync("alice");

            ApiHost.ApiStatusCodeToReturn = 403;

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

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

            response.StatusCode.Should().Be(HttpStatusCode.Forbidden);
        }
Example #17
0
        public async Task response_status_403_should_return_403()
        {
            await BffHost.BffLoginAsync("alice");

            BffHost.LocalApiStatusCodeToReturn = 403;

            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.Forbidden);
        }
Example #18
0
        public async Task StoreAsync_should_remove_conflicting_entries_prior_to_creating_new_entry()
        {
            await BffHost.BffLoginAsync("alice");

            BffHost.BrowserClient.RemoveCookie("bff");
            (await _sessionStore.GetUserSessionsAsync(new UserSessionsFilter {
                SubjectId = "alice"
            })).Count().Should().Be(1);

            await BffHost.BffOidcLoginAsync();

            (await _sessionStore.GetUserSessionsAsync(new UserSessionsFilter {
                SubjectId = "alice"
            })).Count().Should().Be(1);
        }
Example #19
0
        public async Task calls_to_authorized_local_endpoint_without_csrf_should_succeed()
        {
            await BffHost.BffLoginAsync("alice");

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

            response.IsSuccessStatusCode.Should().BeTrue();
            response.Content.Headers.ContentType.MediaType.Should().Be("application/json");
            var json = await response.Content.ReadAsStringAsync();

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

            apiResult.Method.Should().Be("GET");
            apiResult.Path.Should().Be("/local_authz_no_csrf");
            apiResult.Sub.Should().Be("alice");
        }
Example #20
0
        public async Task endpoints_that_disable_csrf_should_not_require_csrf_header()
        {
            await BffHost.BffLoginAsync("alice");

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

            response.IsSuccessStatusCode.Should().BeTrue();
            response.Content.Headers.ContentType.MediaType.Should().Be("application/json");
            var json = await response.Content.ReadAsStringAsync();

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

            apiResult.Method.Should().Be("GET");
            apiResult.Path.Should().Be("/test");
            apiResult.Sub.Should().Be("alice");
            apiResult.ClientId.Should().Be("spa");
        }
Example #21
0
        public async Task calls_to_remote_endpoint_should_forward_user_to_api()
        {
            await BffHost.BffLoginAsync("alice");

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

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

            response.IsSuccessStatusCode.Should().BeTrue();
            response.Content.Headers.ContentType.MediaType.Should().Be("application/json");
            var json = await response.Content.ReadAsStringAsync();

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

            apiResult.Method.Should().Be("GET");
            apiResult.Path.Should().Be("/test");
            apiResult.Sub.Should().Be("alice");
            apiResult.ClientId.Should().Be("spa");
        }
Example #22
0
        public async Task put_to_local_endpoint_should_succeed()
        {
            await BffHost.BffLoginAsync("alice");

            var req = new HttpRequestMessage(HttpMethod.Put, BffHost.Url("/local_authz"));

            req.Headers.Add("x-csrf", "1");
            req.Content = new StringContent(JsonSerializer.Serialize(new TestPayload("hello test api")), Encoding.UTF8, "application/json");
            var response = await BffHost.BrowserClient.SendAsync(req);

            response.IsSuccessStatusCode.Should().BeTrue();
            response.Content.Headers.ContentType.MediaType.Should().Be("application/json");
            var json = await response.Content.ReadAsStringAsync();

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

            apiResult.Method.Should().Be("PUT");
            apiResult.Path.Should().Be("/local_authz");
            apiResult.Sub.Should().Be("alice");
            var body = JsonSerializer.Deserialize <TestPayload>(apiResult.Body);

            body.message.Should().Be("hello test api");
        }
Example #23
0
        public async Task logout_endpoint_should_accept_returnUrl()
        {
            await BffHost.BffLoginAsync("alice", "sid123");

            var response = await BffHost.BrowserClient.GetAsync(BffHost.Url("/bff/logout") + "?sid=sid123&returnUrl=/foo");

            response.StatusCode.Should().Be(302); // endsession
            response.Headers.Location.ToString().ToLowerInvariant().Should().StartWith(IdentityServerHost.Url("/connect/endsession"));

            response = await IdentityServerHost.BrowserClient.GetAsync(response.Headers.Location.ToString());

            response.StatusCode.Should().Be(302); // logout
            response.Headers.Location.ToString().ToLowerInvariant().Should().StartWith(IdentityServerHost.Url("/account/logout"));

            response = await IdentityServerHost.BrowserClient.GetAsync(response.Headers.Location.ToString());

            response.StatusCode.Should().Be(302); // post logout redirect uri
            response.Headers.Location.ToString().ToLowerInvariant().Should().StartWith(BffHost.Url("/signout-callback-oidc"));

            response = await BffHost.BrowserClient.GetAsync(response.Headers.Location.ToString());

            response.StatusCode.Should().Be(302); // root
            response.Headers.Location.ToString().ToLowerInvariant().Should().Be("/foo");
        }