Single Sign-On with OpenID Connect

CityScreen Deals can act as the identity provider for your other web applications. An employee who opens a wiki, a dashboard or another application that supports OpenID Connect signs in with the CityScreen Deals account, including two-step verification when the account has it. The application receives the employee’s identity and, if it asks for them, the groups the employee belongs to. When the employee signs out of CityScreen Deals, the applications that registered a logout address are told.

This function is licensed. If your organization’s license does not include it, contact CityScreen.

Connecting an Application

An OpenID Connect client is an OAuth application with the authorization code grant and the scope openid. The registration form and the flow are described in OAuth Applications.

  1. Open Employees > OAuth applications and press Copy discovery URL. The address looks like https://deals.example.com/.well-known/openid-configuration.

  2. Press Create application and register the application: choose the grant type Authorization code, enter the redirect address that the other application shows you under Redirect URIs, and keep the Allowed scopes openid, profile, email and groups ticked. Leave api unticked unless the application also has to call the REST API.

  3. Copy the client ID and the client secret from the dialog "OAuth application created". The secret is shown only once. A web application that runs on a server keeps the default and stays a confidential client. Tick Public client (no client secret) only for an application that cannot keep a secret.

  4. In the other application, enter the discovery address, the client ID and the client secret, and ask for the scopes openid profile email groups.

  5. Optionally enter a Back-channel logout URI and Post-logout redirect URIs, see Signing out across applications.

Discovery

GET /.well-known/openid-configuration returns the description that client libraries read. GET /.well-known/oauth-authorization-server returns the OAuth part of it. Both are public. They answer 404 without the license and 503 when the address of your organization is not an https address.

Member Value

issuer

The address of your organization, without a trailing slash.

authorization_endpoint, token_endpoint, userinfo_endpoint, jwks_uri, end_session_endpoint

/oauth/authorize, /oauth/token, /oauth/userinfo, /oauth/jwks and /oauth/end-session on that address.

registration_endpoint, revocation_endpoint

/oauth/register and /oauth/revoke, see OAuth Applications.

response_types_supported

code only.

response_modes_supported

query only.

authorization_response_iss_parameter_supported

true: the redirect carries iss.

grant_types_supported

authorization_code, refresh_token and client_credentials.

code_challenge_methods_supported

S256.

token_endpoint_auth_methods_supported

client_secret_basic, client_secret_post and none.

subject_types_supported

public.

id_token_signing_alg_values_supported

RS256.

scopes_supported

openid, profile, email, groups and api.

claims_supported

sub, iss, aud, azp, exp, iat, auth_time, nonce, at_hash, name, preferred_username, locale, email, groups and group_names.

backchannel_logout_supported

true.

Claims

The scopes of the authorization request decide which claims the ID token and UserInfo carry.

Scope Claims

always

sub, the id of the employee in CityScreen Deals. It does not change.

profile

name, preferred_username (the employee’s username) and locale, when the account has one.

email

email, the e-mail address of the account.

groups

groups and group_names, see below.

With the scope groups, the claim groups lists the machine names of the employee’s groups and the claim group_names lists their names, in the same order. The groups are sorted by machine name and each group appears once. An employee without groups receives two empty lists. The claims list the groups the employee is a direct member of. Claims are read at the time the token is issued, so a refresh picks up changes of name, e-mail address and groups.

Map the groups to roles in the other application by the machine name, because a machine name never changes after the group is created. A group name can be edited at any time. See Employee Groups.

The ID Token

The ID token is a JWT signed with RS256 that carries the claims of OpenID Connect Core 1.0, section 2, and its header names the key in kid. sub is the employee’s id, and aud and azp are the client ID. The claims of the scopes are listed under Claims.

The ID token lives as long as the access token issued with it, see OAuth Applications. Only the exchange of a code puts nonce and auth_time into the ID token, and a refresh leaves them out.

An application validates the ID token as section 3.1.3.7 of the standard describes, with the keys from jwks_uri.

UserInfo

GET or POST /oauth/userinfo with Authorization: Bearer <access token> returns the same claims as the ID token for the scopes of the token. The token must come from the authorization code flow and carry the scope openid. Every other request, including one with a personal access token, a token of client credentials, or an unknown or expired token, gets 401 invalid_token.

Signing Keys

GET /oauth/jwks publishes the public keys that verify ID tokens and logout tokens. The answer may be cached for one hour, so an application fetches the key set again when it meets an unknown kid.

An administrator with the "Rotate signing key" permission presses Rotate signing key on Employees > OAuth applications. From then on a new key signs tokens, and the previous key stays published for 24 hours so that tokens signed with it still verify. A key changes only when an administrator rotates it.

Signing Out Across Applications

Back-channel logout

An application that registered a Back-channel logout URI is told when an employee has been signed out of CityScreen Deals, so that it can end its own session of that employee. The address must be an https address on a public host. For an address inside your own network, contact CityScreen.

CityScreen Deals sends a POST with the form field logout_token, a JWT signed with RS256:

  • the header has typ set to logout+jwt and the kid of the signing key;

  • the claims are iss, sub (the employee’s id, as in the ID token), aud (the client ID), iat, jti, events and exp, which is 120 seconds after iat;

  • there is no sid: the application ends all its sessions of the employee named in sub.

A 2xx answer tells CityScreen Deals that the message arrived.

CityScreen Deals sends a logout message to every application that has a logout address and holds a token of the employee when:

  • the employee logs out, or ends a session;

  • an administrator ends the employee’s sessions;

  • the employee’s password is reset, or it expires and the sessions end;

  • a password change ends sessions;

  • the account is deactivated or deleted;

  • the employee revokes the application’s authorization under Account > Authorizations.

A session that simply expires sends no message.

Delivery runs in the background so that an unavailable application never holds up a sign-out. The application answers within 5 seconds with a 2xx status, which counts as delivered. A redirect, which is not followed, and a 4xx answer other than 408 and 429 end delivery. Any other failure is tried again over several hours.

The edit form of the application shows the outcome in Last logout notification.

Sign-out requested by an application

An application can send the employee’s browser to GET or POST /oauth/end-session with these parameters:

Parameter Value

id_token_hint

An ID token that CityScreen Deals issued. It may have expired.

client_id

The client ID. It must match the audience of the hint.

post_logout_redirect_uri

One of the application’s Post-logout redirect URIs, character for character.

state

Up to 500 characters. It is appended to the redirect address.

A redirect back to the application needs a client_id or an id_token_hint that names the client, and a registered post_logout_redirect_uri.

The employee confirms the sign-out first. CityScreen Deals shows the page "{{application}} asks to sign you out of CityScreen Deals" with the buttons Sign out and Stay signed in. Sign out ends only the session of that browser and returns to the redirect address when the request had one. The other applications are told as for any other logout. The page is described in Signing In and Out.

A request that cannot be trusted is never sent back to the application. The employee sees "The sign-out request cannot be completed", and the address of that page carries one of the codes invalid_request, invalid_id_token_hint, client_mismatch or invalid_post_logout_redirect_uri.

Logging out and application tokens

Logging out of CityScreen Deals ends the current session of the employee, see Signing In and Out. The tokens the employee gave to applications stay valid. They end when the employee is deactivated, or when the employee presses Revoke under Account > Authorizations.

The length of a session is set in Settings > General, see Password Policy and Sign-In Protection.

What Administrators See

On the page of an employee, the Sessions block lists the Connected applications: the applications that hold a token of the employee. Each shows "Last used", "Told about sign-out" and "Last notification". The confirmation of End all sessions lists the applications that will be told. The list needs the permission to view the employee and the "OAuth applications" View permission at organization scope.

Example: Connecting a Generic OpenID Connect Client

Fetch the discovery document to check the addresses:

curl -s https://deals.example.com/.well-known/openid-configuration

The answer starts like this (shortened):

{
  "issuer": "https://deals.example.com",
  "authorization_endpoint": "https://deals.example.com/oauth/authorize",
  "token_endpoint": "https://deals.example.com/oauth/token",
  "userinfo_endpoint": "https://deals.example.com/oauth/userinfo",
  "jwks_uri": "https://deals.example.com/oauth/jwks",
  "end_session_endpoint": "https://deals.example.com/oauth/end-session",
  "scopes_supported": ["openid", "profile", "email", "groups", "api"],
  "code_challenge_methods_supported": ["S256"]
}

Register the application in Employees > OAuth applications with the grant type Authorization code, the redirect address https://wiki.example.com/callback, and the allowed scopes openid, profile, email and groups. The dialog shows the client ID app_43 and the client secret. Then enter these values in any application that supports OpenID Connect:

Setting Value

Issuer or discovery address

https://deals.example.com or https://deals.example.com/.well-known/openid-configuration

Client ID

app_43

Client secret

The secret from the dialog.

Flow

Authorization code. Add PKCE with S256 if the application supports it.

Client authentication

client_secret_basic or client_secret_post.

Redirect address

https://wiki.example.com/callback, written exactly as registered.

Scopes

openid profile email groups

User name claim

preferred_username

E-mail claim

email

Groups claim

groups. Map machine names such as sales-managers to roles of the application.

Enter the optional Back-channel logout URI when the application can end its own session on request.