The official content of the Casdoor Marketplace: app integrations, identity provider templates,
sign-in themes and actions that Casdoor admins can install from the Marketplace page of the Casdoor admin console.
Marketplace · Marketplace website · Casdoor · Casdoor docs · Discord
- Add an integration: copy a similar one under
integrations/<type>/, follow the sections below, runnpm run check, and open a pull request. CI validates every manifest against the schemas inschema/. - Request an integration: open an issue with the app or identity provider you need.
- Once merged, an integration shows up on the Marketplace at its next build, and on Casdoor's Marketplace page once jsDelivr refreshes its cache of the
distbranch (up to 12 hours).
integrations/<type>/<id>/
integration.json manifest, see schema/integration.schema.json
... content files for the type
schema/ JSON Schemas for the manifest and content files
scripts/build.mjs validates everything and writes dist/
<type> is one of app, provider, theme, action. <id> is unique across all types and becomes the page address /integrations/<id>.
Single sign-on for an app people run, such as Grafana or GitLab.
| File | Contents |
|---|---|
integration.json |
Name, description, logo, categories, and the variables the installer asks for (usually appUrl) |
application.json |
The Casdoor application to create: redirect URLs, token group format (schema) |
guide.json |
Setup guide for the app's side: steps with code or form fields, tips, FAQs, and the app documentation the settings come from (schema) |
logo.svg |
Optional |
The first step of every guide, registering the app in Casdoor, is generated from application.json, so guide.json starts with the app's own settings.
An identity provider people already have accounts with, set up as a sign-in provider in Casdoor, such as Keycloak or authentik.
| File | Contents |
|---|---|
integration.json |
Name, description, logo, and the variables for the other side's address (e.g. keycloakUrl, realm) |
provider.json |
The Casdoor provider to create: type OIDC (or Custom for plain OAuth 2.0), issuer, endpoints, scopes, PKCE, user mapping (schema) |
guide.json |
The steps on the other side: registering Casdoor as a client, with redirect URI {{casdoorUrl}}/callback |
logo.svg |
Optional |
The last two steps of every guide, adding the provider in Casdoor and putting it on an application, are generated from provider.json.
- Casdoor's sign-in page builds the authorization request from
customAuthUrleven for OIDC, so list the endpoints rather than relying on discovery. Always setcustomUserInfoUrl: several providers (Authelia, authentik, ZITADEL) keep profile claims out of the ID token. - Casdoor sends the client secret with HTTP Basic first (Go's oauth2 auto-detection), so the other side can keep
client_secret_basic. - For a
Customprovider whose requests don't follow OAuth 2.0, such asappidandsecretinstead ofclient_idandclient_secret, or a userinfo endpoint that takes the token's fields in its query, write the URLs with{name}placeholders (single braces, filled in at sign-in, unlike{{variables}}).customAuthUrlgetsclientId,redirectUri,scope,stateandcodeChallenge;customTokenUrlgetsclientId,clientSecret,code,redirectUri,codeVerifierandstate, and its query is posted as the form body;customUserInfoUrlgetsclientId,stateand any field of the token response, and is requested without anAuthorizationheader. See chaoxing. - Casdoor links users of every OIDC-type provider in an organization through one user field (
oidc), so an organization should have only one; a second one should beCustom Flexible, which links accounts per provider. The generated Casdoor step says so.
"region": "cn" in integration.json lists an integration only in Chinese: on the Chinese pages of the store, and in Casdoor for admins using it in Chinese. It is for platforms only used in China, such as Chaoxing; their name, description and guide are written in Chinese, under en. Everything else is listed in both.
Everything in this repository is free. The paid integrations of the Marketplace, such as the templates of Chinese office systems, carry "edition": "Commercial" or "Enterprise" in integration.json, are kept elsewhere and are not on the CDN: the Marketplace server lists them in paid-index.json and gives their files only to a Casdoor that sends a license of that edition or a higher one, with the license written into the files. They build against sdk/ here.
A look for the sign-in pages of a Casdoor application.
| File | Contents |
|---|---|
integration.json |
Name, description, at least one screenshot, and variables such as an accent color |
theme.json |
Application fields in the shape of Casdoor's Export JSON: themeData, formOffset, formCss, formCssMobile, formSideHtml, footerHtml, formBackgroundUrl, formBackgroundUrlMobile (schema) |
screenshot.png |
1280×800 screenshot of the sign-in page, taken from a real Casdoor with the variables at their examples |
- CSS hooks:
.login-background,.login-topbar(Casdoor 4.20.0 and later;.login-background > div:first-of-typebefore that),.login-content,.login-panel,.login-form,.login-logo-box,.side-image,#footer. WithoutformCssMobile, phones get no custom CSS at all. - Form CSS may load fonts and images, with
url(),@font-faceand@import, from places an organization admin cannot read the access logs of: relative URLs on the Casdoor itself,data:URIs, Google Fonts, Fontsource on jsDelivr,cdn.jsdelivr.net/gh/casdoor/and Casdoor's own CDNs.@importis limited to Google Fonts and Fontsource stylesheets. Anything else, image functions other thanurl(), backslashes and HTML make Casdoor keep the old CSS when an organization admin saves it, and the build rejects them. A theme that loads files needscasdoorVersion>=4.20.0: earlier versions reject everyurl(). - A picture behind the whole page goes in
formBackgroundUrlandformBackgroundUrlMobile, usually as a variable of typeurl; any address works there. Keep a default picture next totheme.jsonand point the variable's example at it on jsDelivr (https://cdn.jsdelivr.net/gh/casdoor/casdoor-integrations@master/integrations/theme/<id>/<file>). formSideHtmlandfooterHtmlare for layout and branding. From Casdoor 4.20.0 an organization admin can save them as long as they hold only text, links, pictures, inline SVG and styles: no scripts, event handlers, forms, fields, buttons, frames or comments, and pictures and styles follow the same rule as form CSS about where files come from. Before 4.20.0 only a global admin can save them, so a theme that sets them is still markedrequiresGlobalAdminin the index, which those versions go by.- The public page builds the JSON for Casdoor's Import JSON button, so a theme can also be applied by hand, without the Marketplace installer.
Content files write values that differ per installation as {{name}}:
| Variable | Public page shows | Filled in by |
|---|---|---|
casdoorUrl |
https://auth.example.com |
Casdoor |
clientId |
<client ID> |
App integrations: Casdoor, from the new application. Provider templates: the admin, from the other side |
clientSecret |
<client secret> |
Same as clientId |
anything in variables |
its example |
the admin, in the install form |
Variable types are string, url (no trailing slash) and color (#rrggbb). The installer must HTML-escape values it puts into HTML fields, and check colors.
The installer should also set a provider's customLogo to the integration's logo, since templates leave it empty and Casdoor otherwise shows a generic icon on the sign-in button.
- Take every setting of the other side from its own documentation and list it in
sources. Check Casdoor's side against the Casdoor source code. - For app integrations: Casdoor's default JWT ID token has the username in
name, the display name indisplayName, andemail,email_verifiedandgroups; it has nopreferred_username./api/userinforeturns the standardpreferred_username,name,emailandgroups. JWT-Standard tokens carry no groups. - Text may use
`code`and**bold**. - Bump
versioninintegration.jsonwhenever any file of the integration changes.
Code that Casdoor runs, such as a payment or SMS provider: a Go main package compiled to WebAssembly, which Casdoor runs in a sandbox. The only way out is sdk.Fetch, to https URLs on the hosts in the manifest's permissions.hosts; the module sees nothing of Casdoor but what each call passes in.
| File | Contents |
|---|---|
integration.json |
Name, description, logo and permissions.hosts (required) |
action.json |
kind (payment, sms, push, syncer, idp, idv, password-check, password-migration or cert), abi (1) and the file name of the compiled module (schema) |
go.mod, *.go |
The Go main package, built with the SDK in sdk/ |
guide.json |
Optional: setup steps for the public page |
- A payment action calls
sdk.RegisterPaymentfrominitwith a type that hasPayandNotify. Installing it adds a payment provider of type Plugin; the provider's client ID, client secret, host and so on reach the action assdk.Config. Seeintegrations/action/revolut. - An SMS action calls
sdk.RegisterSmsfrominitwith a type that hasSendSms. Installing it adds an SMS provider of type Plugin; the provider's sign name (the sender) and template code reach the action insdk.Configtoo. Seeintegrations/action/vonage. - A push action calls
sdk.RegisterPushwith a type that hasSendPush. Installing it adds a notification provider of type Plugin that sends the sign-in confirmations of the push MFA to the user field named byreceiverFieldinaction.json. - A syncer action calls
sdk.RegisterSyncerwith a type that hasListUsersandTestConnection; the syncer's host, user and password reach it asHost,ClientIdandClientSecret. If the type also hasListGroups(sdk.GroupSyncer), the action imports the department tree too (syncer.listGroups), and each user'sGroupslists the IDs of its departments. - An idp action calls
sdk.RegisterIdpwith a type that hasGetTokenandGetUserInfo. Installing it adds an identity provider of type Plugin for a third-party sign-in with an authorization code: the admin writes the platform's authorization page into the provider's Auth URL, with the placeholders{clientId},{redirectUri},{state}and{scope}, and the action turns the code into the user. Its guide should give that template. - An idv action calls
sdk.RegisterIdvwith a type that hasVerify. Installing it adds an ID verification provider of type Plugin that checks a user's ID card and real name (and phone, for checks that include it). A mismatch is a result withOkfalse and aReasonfor the user, not an error. - A cert action calls
sdk.RegisterCertwith a type that hasVerify. An organization picks it as the certificate verifier of its certificate login, and Casdoor then hands it the certificates the user presented, the trusted CAs, the CRLs it fetched and, for a UKey plug-in, the challenge and its signature. A certificate that doesn't pass is a result withValidfalse and aReason(expired,untrusted,revoked,signatureorinvalid), not an error; a valid one returns the certificate'sFields(CN,SERIALNUMBER,Email,UID,Fingerprint). - A password check calls
sdk.RegisterPasswordCheck, a password migrationsdk.RegisterPasswordVerify; the organization's security settings run them. Notifyshould ask the payment service for the state of the order rather than trust the request body.- Libraries built on
net/http, such as a payment service's official Go SDK, work throughsdk/nethttp, at the cost of a larger module. - The build runs
GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -trimpath -buildvcs=false -ldflags="-s -w -buildid=", writes the module next tobundle.jsonand adds itssha256toaction.json, which Casdoor checks on install. With the same Go version (see.github/workflows/build.yml) the module comes out byte for byte the same, so a reviewer can rebuild it.
npm ci # actions also need Go
npm run check # validate only
npm run build # validate and write dist/dist/index.json lists every integration; each version is in dist/integrations/<id>/<version>/bundle.json (manifest plus content files) with its logo, screenshots and, for an action, its module. Paths in index.json are relative to it.
On every push to master, CI publishes dist/ to the dist branch. Casdoor instances read it from https://cdn.jsdelivr.net/gh/casdoor/casdoor-integrations@dist by default (marketplaceUrl in Casdoor's conf/app.conf points them to a mirror), and casdoor-marketplace builds the public pages from it.
Logos are from Simple Icons (CC0) or the owners' own websites; the names and marks belong to their owners.