Single Sign On

Besides signing up via email/password credentials (optionally restricted by the setup_registration_token, see Advanced), users can also sign in via SSO. This is configured in global.sso.

Each entry in that dict is the name of an SSO provider as its key. When choosing a name, it’s important to realize that this “name” will also be used in the callback or return URLs! So, this should be a short lower-case alphanumeric identifier, suitable for a URL, like foobar below.

Behind the scenes, all these entries will be set/updated in the database’s passport_settings table by a Hub. After updating the deployment, appropriate hubs will restart automatically. Any other existing rows in that table are not modified, which means if you rename a strategy, you have to delete the row manually.

The “conf” aspect is basically a set of parameters that are fed into the Passport JS strategy, selected by the “type” field. The most important detail is that the URLs have to match. I.e. for example if your strategy is called foobar then the callbackUrl must be https://$DNS/auth/foobar/return. Obviously, this is also one of the settings that need to be done at your IdP.

One other important detail is login_info. It maps attributes returned from the “profile” object into cocalc’s world. So, e.g. if your IdP profile has a field firstName for the first name of the user, then there must be {first_name: 'firstName'}, i.e. to pick firstName from the profile object and store it into cocalc’s first_name. similarly, {emails: "emailAddress"} and so on. The string on the right hand side is actually fed into dot-object, which allows you to also reach into nested objects and array.

The “info” entries are for CoCalc’s side of this. You should set public: false, doNotHide: true, to show this method on the index page.

The display, description and icon fields are user-visible elements.

Interesting is also exclusive_domains where you can force users to always authenticate using your IdP, when their email address ends with one of the listed domains (or is a sub-domain). That way, you can avoid users setting a password and then still being able to sign in, even if you had cut off their access at the level of your IdP.

(On top of this, there are also ways to manage user’s via an API or cocalc’s own Admin interface).

As an example, here is how SAML Azure AD could look like. Note, that type: saml and the name of this fictional strategy is foobar, which appears in some parameters. For more information about the SAML Passport JS parameters, check out https://github.com/node-saml/node-saml/blob/master/README.md

The up-to-date list of available types is in the extra-strategies.ts file. As of writing this, saml, oidc, and oauth2 / oauth2next, are the ones which are in use and known to work well. You have to check to corresponding Passport JS documentation to know what the conf parameters are.

Apart from the example below, please also have a look at this sso: entry in /cocalc/values.yaml with more notes and /cocalc/cocalc-eu.yaml contains another working example.

 1global:
 2  sso:
 3    foobar:
 4      conf:
 5        "type": "saml"
 6        "cert": "MIIDfiWFieF...fjwif83A=="
 7        # Verify that the value in the saml:Issuer tag in the SAMLRequest matches the Entity ID value configured in the SAML Service Provider Details section in the Admin console. This value is case-sensitive.
 8        "issuer": "cocalc-prod"
 9        "entryPoint": "https://login.microsoftonline.com/{UUID}/saml2"
10        "path": "/auth/foobar/return" # depends on the name!
11        # This maps profile attributes to these 3 cocalc fields. The right hand side is actually: https://github.com/rhalff/dot-object?tab=readme-ov-file#usage
12        "login_info": { "emails": "email", "last_name": "last_name", "first_name": "first_name" }
13        # schema: https://$DNS/auth/$STRATEGY/return, i.e. the strategy name is used to construct the callback URL
14        "callbackUrl": "https://cocalc.com/auth/foobar/return"
15        "signatureAlgorithm": "sha256"
16        # other configuration fields, e.g. for OKTA SAML – https://github.com/node-saml/node-saml/blob/master/README.md
17        #"disableRequestedAuthnContext": true
18        #"audience": true
19        #"identifierFormat": null
20        #"disableRequestedAuthnContext": true
21        #"acceptedClockSkewMs": -1
22        #"racComparison": "exact"
23      info:
24        "public": false
25        "do_not_hide": true # if true and a public=false, show it directly on the login/signup page
26        "icon": "https://{domain}/.../icon.png"
27        "display": "Foo Bar" # user visible
28        "description": "This is Foo Bar Auth" # user visiable
29        "update_on_login": true # optional, each time a user signs in, their name is set to the fields coming from the IdP
30        #"exclusive_domains": ["domain.name"] # initally, keep this optional, when the SSO works, then uncomment it to make that SSO method mandatory for all users with one of these domain names
31        #"cookie_ttl_s": 1209600 # optional, this is 14 days