Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions auth-oauth2/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ public function getResourceOwnerDetailstUrl() {
return $this->get('urlResourceOwnerDetails');
}

public function getLogoutUrl() {
return $this->get('urlLogout');
}

public function getPostLogoutRedirectUri() {
return $this->get('urlPostLogout') ?: osTicket::get_base_url();
}

public function getAttributeFor($name, $default=null) {
return $this->get("attr_$name", $default);
}
Expand Down Expand Up @@ -229,6 +237,46 @@ function getAllOptions() {
'default' => '',
)
),
'logout_settings' => new SectionBreakField(array(
'label' => $__('Logout Settings'),
'hint' => $__('Optional OIDC RP-Initiated Logout configuration'),
'visibility' => new VisibilityConstraint(
new Q(array('auth_type__eq' => 'auth')),
VisibilityConstraint::HIDDEN
),
)),
'urlLogout' => new TextboxField(
array(
'label' => $__('Logout Endpoint'),
'hint' => $__('OIDC end_session_endpoint. When set, users will be redirected here on logout to also end their IdP session (e.g. Keycloak: https://host/realms/{realm}/protocol/openid-connect/logout). Leave blank to disable IdP logout.'),
'required' => false,
'configuration' => array(
'size' => 64,
'length' => 0
),
'default' => '',
'visibility' => new VisibilityConstraint(
new Q(array('auth_type__eq' => 'auth')),
VisibilityConstraint::HIDDEN
),
)
),
'urlPostLogout' => new TextboxField(
array(
'label' => $__('Post-Logout Redirect URI'),
'hint' => $__('Where to redirect after the IdP logout completes. Defaults to osTicket base URL if blank. Must be registered as an allowed post-logout redirect URI in your IdP client configuration.'),
'required' => false,
'configuration' => array(
'size' => 64,
'length' => 0
),
'default' => '',
'visibility' => new VisibilityConstraint(
new Q(array('auth_type__eq' => 'auth')),
VisibilityConstraint::HIDDEN
),
)
),
'scopes' => new TextboxField(
array(
'label' => $__('Scopes'),
Expand Down
32 changes: 32 additions & 0 deletions auth-oauth2/oauth2.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ function callback($resp, $ref=null) {
&& ($token=$this->provider->getToken($resp['code']))
&& ($attrs=$token->getOwnerAttributes())) {
$this->resetState();
// Store OIDC logout data for use by signOut
if (($idToken = $token->getIdToken()))
$this->session['id_token'] = $idToken;
$this->session['logout_url'] = $this->config->getLogoutUrl();
$this->session['post_logout_uri'] = $this->config->getPostLogoutRedirectUri();
$this->session['client_id'] = $this->config->getClientId();
// Attempt to signIn the user based on returned attributes
$result = $this->signIn($attrs);
if ($result instanceof AuthenticatedUser) {
Expand Down Expand Up @@ -146,7 +152,28 @@ function redirectTo($url) {
}

static function signOut($user) {
// Capture OIDC logout data before parent clears the session
$sess = $_SESSION[':oauth'][static::$id] ?? [];
$idToken = $sess['id_token'] ?? null;
$logoutUrl = $sess['logout_url'] ?? null;
$postLogoutUri = $sess['post_logout_uri'] ?? null;
$clientId = $sess['client_id'] ?? null;

// Clear local osTicket session (existing behaviour)
parent::signOut($user);

// Clear OAuth session data
unset($_SESSION[':oauth'][static::$id]);

// Perform RP-Initiated Logout if an end_session_endpoint is configured
if ($logoutUrl) {
$params = array_filter([
'id_token_hint' => $idToken,
'client_id' => $clientId,
'post_logout_redirect_uri' => $postLogoutUri,
]);
Http::redirect($logoutUrl . '?' . http_build_query($params));
}
}

abstract function signIn($attrs);
Expand Down Expand Up @@ -652,6 +679,11 @@ protected function getUniqueName() {
return $this->getJwt()->unique_name;
}

public function getIdToken() {
$values = $this->getValues();
return $values['id_token'] ?? null;
}

public function setOwner(Object $owner) {
$this->owner = $owner;
}
Expand Down