0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-08 17:53:55 +08:00
discourse/plugins/discourse-openid-connect/spec/requests/rp_initiated_logout_spec.rb
Chris Alberti d34655f5c4
DEV: Add optional setting to include client_id in oidc logout endpoint url (#37818)
Adds support for including the `client_id` as a query parameter in the
endpoint for rp initiated logout. It's optional, turned on by a boolean
site setting, so we don't negatively impact existing users.

Meta: /t/387638

Customer requested this because although [it's optional in the
spec](https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout),
their IdP requires it.
2026-02-13 10:47:51 -06:00

127 lines
4.5 KiB
Ruby
Vendored

# frozen_string_literal: true
describe "OIDC RP-Initiated Logout" do
let(:document_url) do
SiteSetting.openid_connect_discovery_document =
"https://id.example.com/.well-known/openid-configuration"
end
let(:document) do
{
issuer: "https://id.example.com/",
authorization_endpoint: "https://id.example.com/authorize",
token_endpoint: "https://id.example.com/token",
userinfo_endpoint: "https://id.example.com/userinfo",
end_session_endpoint: "https://id.example.com/endsession",
}
end
fab!(:user)
before do
SiteSetting.openid_connect_enabled = true
SiteSetting.openid_connect_rp_initiated_logout = true
stub_request(:get, document_url).to_return(body: lambda { |r| document.to_json })
end
after { Discourse.cache.delete("openid-connect-discovery-#{document_url}") }
it "does nothing for a user with no oidc record" do
sign_in(user)
delete "/session/#{user.username}", xhr: true
expect(response.status).to eq(200)
expect(response.parsed_body["redirect_url"]).to eq("/")
end
it "does nothing for a user with no token in their oidc record" do
sign_in(user)
UserAssociatedAccount.create!(provider_name: "oidc", user: user, provider_uid: "myuid")
delete "/session/#{user.username}", xhr: true
expect(response.status).to eq(200)
expect(response.parsed_body["redirect_url"]).to eq("/")
end
context "with user and token" do
before do
sign_in(user)
UserAssociatedAccount.create!(
provider_name: "oidc",
user: user,
provider_uid: "myuid",
extra: {
id_token: "myoidctoken",
},
)
end
it "redirects the user to the logout endpoint" do
delete "/session/#{user.username}", xhr: true
expect(response.status).to eq(200)
expect(response.parsed_body["redirect_url"]).to eq(
"https://id.example.com/endsession?id_token_hint=myoidctoken",
)
end
it "correctly handles logout urls with existing query params" do
document[:end_session_endpoint] += "?param=true"
delete "/session/#{user.username}", xhr: true
expect(response.status).to eq(200)
expect(response.parsed_body["redirect_url"]).to eq(
"https://id.example.com/endsession?param=true&id_token_hint=myoidctoken",
)
end
it "includes the redirect URI if set" do
SiteSetting.openid_connect_rp_initiated_logout_redirect = "https://example.com"
delete "/session/#{user.username}", xhr: true
expect(response.status).to eq(200)
expect(response.parsed_body["redirect_url"]).to eq(
"https://id.example.com/endsession?id_token_hint=myoidctoken&post_logout_redirect_uri=https%3A%2F%2Fexample.com",
)
end
it "does not redirect if plugin disabled" do
SiteSetting.openid_connect_enabled = false
delete "/session/#{user.username}", xhr: true
expect(response.status).to eq(200)
expect(response.parsed_body["redirect_url"]).to eq("/")
end
it "does not redirect if rp initiated logout disabled" do
SiteSetting.openid_connect_rp_initiated_logout = false
delete "/session/#{user.username}", xhr: true
expect(response.status).to eq(200)
expect(response.parsed_body["redirect_url"]).to eq("/")
end
it "does not redirect if the discovery document is missing the endpoint" do
stub_request(:get, document_url).to_return(body: "{}")
SiteSetting.openid_connect_rp_initiated_logout = false
delete "/session/#{user.username}", xhr: true
expect(response.status).to eq(200)
expect(response.parsed_body["redirect_url"]).to eq("/")
end
it "does not redirect if the discovery document has a network error" do
stub_request(:get, document_url).to_timeout
SiteSetting.openid_connect_rp_initiated_logout = false
delete "/session/#{user.username}", xhr: true
expect(response.status).to eq(200)
expect(response.parsed_body["redirect_url"]).to eq("/")
end
context "with client_id included in logout endpoint" do
before do
SiteSetting.openid_connect_client_id = "test-client-id"
SiteSetting.openid_connect_rp_initiated_logout_include_client_id = true
end
it "appends the client id to the logout endpoint url" do
delete "/session/#{user.username}", xhr: true
expect(response.status).to eq(200)
expect(response.parsed_body["redirect_url"]).to eq(
"https://id.example.com/endsession?id_token_hint=myoidctoken&client_id=test-client-id",
)
end
end
end
end