FEATURE: PKCE support (#86)

Introduces a new site setting (openid_connect_use_pkce) which enables PKCE support

Co-authored-by: Jincoco88912 <jincoco88912@gmail.com>
Co-authored-by: David Taylor <david@taylorhq.com>
This commit is contained in:
Balázs Orbán 2024-10-16 13:31:57 +02:00 committed by GitHub
parent c79a5c4ee5
commit 1130cd9716
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 21 additions and 0 deletions

View File

@ -15,6 +15,7 @@ en:
openid_connect_overrides_email: "On every login, override the user's email using the openid-connect value. Works the same as the `auth_overrides_email` setting, but is specific to OpenID Connect logins."
openid_connect_claims: "Explicitly define the claims for use with providers that don't pass data back based on scopes. (JSON)"
openid_connect_match_by_email: "Use email address to match OpenID Connect authentications to existing Discourse user accounts."
openid_connect_use_pkce: "Enable Proof Key for Code Exchange (PKCE) for OpenID Connect authentication."
login:
omniauth_error:
openid_connect_discovery_error: Unable to fetch configuration from identity provider. Please try again.

View File

@ -35,3 +35,5 @@ discourse_openid_connect:
textarea: true
openid_connect_match_by_email:
default: true
openid_connect_use_pkce:
default: false

View File

@ -1,4 +1,6 @@
# frozen_string_literal: true
require "base64"
require "openssl"
class OpenIDConnectAuthenticator < Auth::ManagedAuthenticator
def name
@ -107,6 +109,14 @@ class OpenIDConnectAuthenticator < Auth::ManagedAuthenticator
passthrough_authorize_options:
SiteSetting.openid_connect_authorize_parameters.split("|"),
claims: SiteSetting.openid_connect_claims,
pkce: SiteSetting.openid_connect_use_pkce,
pkce_options: {
code_verifier: -> { generate_code_verifier },
code_challenge: ->(code_verifier) do
generate_code_challenge(code_verifier)
end,
code_challenge_method: "S256",
},
)
opts[:client_options][:connection_opts] = {
@ -128,6 +138,14 @@ class OpenIDConnectAuthenticator < Auth::ManagedAuthenticator
}
end
def generate_code_verifier
Base64.urlsafe_encode64(OpenSSL::Random.random_bytes(32)).tr("=", "")
end
def generate_code_challenge(code_verifier)
Base64.urlsafe_encode64(Digest::SHA256.digest(code_verifier)).tr("+/", "-_").tr("=", "")
end
def request_timeout_seconds
GlobalSetting.openid_connect_request_timeout_seconds
end