mirror of
https://github.com/discourse/discourse.git
synced 2026-08-08 17:53:55 +08:00
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.
127 lines
4.5 KiB
Ruby
Vendored
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
|