Cylindo OpenID Connect
Cylindo allows third-party clients to authenticate their users on Cylindo’s behalf, using a standard OpenID Connect authentication flow. Cylindo then acts as an OIDC Provider and expose a number of user resources to the client.
As of now, the only supported authentication flow is the Authorization code flow with PKCE (Proof Key for Code Exchange). This flow is intended for third-party public clients (such as an SPA).
Authorization code flow with PKCE
Flow schema

Endpoints documentation
The OIDC issuer is https://app.cylindo.com/api/rest/services/oidc. All OIDC endpoints are subroutes of this URL.
GET /authorize endpoint
This endpoint serves the authorization step of the authentication (see OAuth’s documentation). This endpoint is intended to be navigated to directly from a browser, by a redirection from the authorized client.
Query parameters
Responses
Redirected location
As long as the redirect_uri query parameter is valid, the /authorize endpoint will redirect to it.
If the authorization is successful, the redirected location will contain the following query parameters:
If the authorization failed, the redirected location will contain the following query parameters:
Example cURL
curl -H 'referer: https://client-app.com' \ 'https://app.cylindo.com/api/rest/services/oidc/authorize?redirect_uri=https%3A%2F%2Fclient-app.com%2Fredirect&scope=openid+email&state=EatlqjKZ&nonce=n3UdyX2s&code_challenge=xLO0yqyWUBp_EZxnw23V0JNFM3TkfRvB9WF-7ZwUJCY&code_challenge_method=S256&client_id=I2r6wGHFOlvptyUOLhD8cR57&response_type=code'POST /token endpoint
This endpoint serves the authentication step of the flow (see OAuth’s documentation). This endpoint is intended to be requested directly from the public client itself (in this case, an SPA).
The POST /token request must have its parameter URI-encoded in its body, and its Content-Type must be application/x-www-form-urlencoded.
Body parameters
Responses
Example cURL
curl 'https://app.cylindo.com/api/rest/services/oidc/token' \ -H 'content-type: application/x-www-form-urlencoded;charset=UTF-8' \ -H 'origin: https://client-app.com' \ --data-raw 'redirect_uri=https%3A%2F%2Fclient-app.com%2Fredirect&code=eyJh...F7Pw&code_verifier=XDY-0Oxq1V0S2IqwbZwPNiiQt2xEMO7BvBCjZbvkT38&grant_type=authorization_code&client_id=I2r6wGHFOlvptyUOLhD8cR57'Implementation example
The following example uses the openid-client and jose libraries.
Flow initialization
This code is intended to be run when the user click a "Sign in with Cylindo" button.
import * as client from "openid-client"; // this code is adapted from this "Quick start" guide: // https://github.com/panva/openid-client?tab=readme-ov-file#authorization-code-flow const SESSION_STORAGE_KEY = "_cylindo_oauth_data"; const OIDC_SERVER_URL = "https://app.cylindo.com/api/rest/services/oidc"; const CLIENT_ID = "YOUR_CYLINDO_OAUTH_CLIENT_ID"; const REDIRECT_URI = "https://your-redirection-uri.com/callback"; const SCOPE = "openid email customer-id"; const setPersistentData = (data) => { const encoded = JSON.stringify(data); sessionStorage.setItem(SESSION_STORAGE_KEY, encoded); }; const getProviderConfig = () => client.discovery(new URL(OIDC_SERVER_URL), CLIENT_ID); const config = await getProviderConfig(); const code_verifier = client.randomPKCECodeVerifier(); const code_challenge = await client.calculatePKCECodeChallenge(code_verifier); const state = client.randomState(); const nonce = client.randomNonce(); const parameters = { redirect_uri: REDIRECT_URI, scope: SCOPE, state, nonce, code_challenge, code_challenge_method: "S256", }; const redirectTo = client.buildAuthorizationUrl(config, parameters); setPersistentData({ state, code_verifier, nonce }); window.open(redirectTo.href, "_self");Code exchange
This code is intended to be run when the user lands back on the specified redirect_uri. It will read the relevant information directly from the query parameters of the current url.
import * as client from "openid-client"; import { createRemoteJWKSet, jwtVerify } from "jose"; // this code is adapted from this "Quick start" guide: // https://github.com/panva/openid-client?tab=readme-ov-file#authorization-code-flow const SESSION_STORAGE_KEY = "_cylindo_oauth_data"; const OIDC_SERVER_URL = "https://app.cylindo.com/api/rest/services/oidc"; const CLIENT_ID = "YOUR_CYLINDO_OAUTH_CLIENT_ID"; const REDIRECT_URI = "https://your-redirection-uri.com/callback"; const getPersistentData = () => { const encoded = sessionStorage.getItem(SESSION_STORAGE_KEY); return JSON.parse(encoded); }; const getProviderConfig = () => client.discovery(new URL(OIDC_SERVER_URL), CLIENT_ID); const { state, code_verifier, nonce } = getPersistentData(); const config = await getProviderConfig(); const currentUrl = new URL(window.location.href); const checks = { pkceCodeVerifier: code_verifier, expectedState: state, expectedNonce: nonce, }; const extraParams = { redirect_uri: REDIRECT_URI, }; const tokens = await client.authorizationCodeGrant( config, currentUrl, checks, extraParams ); const publicKey = createRemoteJWKSet( new URL(config.serverMetadata()["jwks_uri"]) ); await jwtVerify(tokens.id_token, publicKey); // Past this point, id_token has been verified successfully const claims = tokens.claims(); // The resources are located under claims console.log({ email: claims.email, customerId: claims["customer-id"], }); // Now that the user is properly authenticated, we can redirect to home or whichever link they were trying to access // Don't forget to replace this line with your framework's own router implementation of replaceState window.location.href = "/";Available scopes
Token object
JSON Errors
Error codes
Cylindo public key
The RS256 public key can be found in a JWK format here. We recommend fetching it through jose's createRemoteJWKSet method, since it comes with cache handling.