Skip to main content

SSO Security

Technical specification of login through an external identity provider, prepared for security and IT teams evaluating Q247 before deployment. The configuration itself, that is the fields to fill in and the actions on the identity provider's side, is described in SSO (OIDC).

Standard and algorithms

Q247 implements SSO login based on OpenID Connect 1.0, in the Authorization Code Flow. Every identity provider compliant with this standard is supported, including Microsoft Entra ID, Okta, Google and Keycloak.

ElementSolution
Session tokensJWT
Token signingHS256 (HMAC-SHA-256), an algorithm enforced in the code
Client secret encryptionAES-256-GCM with a two-layer key
TransportHTTPS only

Enforcing a single signing algorithm at the code level means no other one will be accepted during token verification. This eliminates the class of attacks based on algorithm substitution.

Client secret encryption

The OIDC client secret, provided once during configuration, is stored in encrypted form. The key is two-layered:

  • DEK (Data Encryption Key): a random 32-byte key, generated once for each secret.
  • KEK (Key Encryption Key): the environment's master encryption key, configured at the infrastructure level and stored outside the database.

Decrypting the secret requires access to the KEK, which never reaches the database. A leak of the database alone therefore does not expose the secret in plain form.

Role of the client secret

The OIDC protocol involves two separate acts of identity verification. The first is authenticating the user, which the identity provider carries out at the moment login data is given. The second is authenticating the client application, that is Q247 confirming its own identity to the provider. The client secret serves only the second one.

It is used at one point in the flow: when exchanging the authorization code for a token. The Q247 backend then sends the token endpoint a request containing the received authorization code, the application identifier and the secret. Without a correct secret, the provider rejects the request, and an intercepted authorization code stays useless.

PropertyHow it is implemented
Server-side onlythe secret takes part only in communication from the Q247 backend to the identity provider, and is never sent to the browser
Encryption in the databaseAES-256-GCM, access to the database does not expose the plain value
Short-lived in memorydecrypted for the duration of a single HTTP call to the token endpoint, without being cached
Single use of the codethe authorization code works once and expires after a few minutes

Login flow

The flow runs through the user's browser, with no direct connection from the identity provider to Q247:

  1. The user opens the Q247 login screen and chooses login through the identity provider.
  2. The Q247 backend fetches the provider's Discovery Document and builds the authorization address, adding the state and nonce parameters.
  3. The user's browser is redirected to the identity provider.
  4. The user authenticates at the provider, outside Q247.
  5. The provider redirects the browser back to the Q247 return address, passing the authorization code.
  6. The Q247 backend verifies the state parameter and exchanges the code for a token, authenticating itself with the client secret.
  7. Q247 verifies the ID token, reads the e-mail address from it and maps it to an account in the organization.
  8. A session is created: an access token in the form of a JWT and a refresh token stored in a cookie.

Safeguards built into the flow

  • The state parameter: a random token binding the request to the response, protects against CSRF attacks. Single-use, valid for 5 minutes.
  • The nonce parameter: a random value placed in the ID token, prevents replaying an earlier response.
  • HttpOnly and Secure cookie: the refresh token is inaccessible to JavaScript code and sent only over HTTPS.
  • Scope restriction: Q247 requests only the openid, email and profile scopes, so it does not gain access to any other data in the identity directory.

Discovery Document and address validation

Every OIDC-compliant provider publishes at a predictable address a JSON document describing its endpoints and capabilities. Q247 fetches it automatically at every login session initiation, thanks to which the whole configuration comes down to providing one address, and the remaining parameters are discovered.

The address is validated at the moment the configuration is saved. It must contain the .well-known/openid-configuration segment and point to a public IP address. Private and local addresses are rejected, which protects against using this field to force requests to internal resources.

Direction of network traffic

In the Authorization Code Flow, the identity provider never establishes a connection to the Q247 server. The authorization code comes back through the user's browser, via an HTTP redirect, and all direct calls between Q247 and the provider are initiated by Q247.

ConnectionDirectionRequired
Q247 backend → provider (fetching the Discovery Document)outbound from Q247yes
Q247 backend → provider (exchanging the code for a token)outbound from Q247yes
User's browser → provider (login)via the clientyes
User's browser → Q247 (return with the code)via the clientyes
Provider → Q247 backendnoneno

Enabling SSO does not require letting in any inbound traffic from the identity provider.

See also