Skip to content

docs: rework "admin/authentication" page + PKI authentication docs #9236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 70 additions & 4 deletions docs/admin/auth.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Authentication

[OIDC with Coder Sequence Diagram](https://raw.githubusercontent.com/coder/coder/138ee55abb3635cb2f3d12661f8caef2ca9d0961/docs/images/oidc-sequence-diagram.svg).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where should this image be referenced?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I link to it later in the doc under "How it works"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


By default, Coder is accessible via password authentication. Coder does not
recommend using password authentication in production, and recommends using an
authentication provider with properly configured multi-factor authentication
Expand Down Expand Up @@ -94,9 +92,9 @@ Your OIDC provider will ask you for the following parameter:

- **Redirect URI**: Set to `https://coder.domain.com/api/v2/users/oidc/callback`

### Step 2: Configure Coder with the OpenID Connect credentials
### Step 2 (Client Secret Auth): Configure Coder with the OpenID Connect credentials

Navigate to your Coder host and run the following command to start up the Coder
The most common way to authenticate with OIDC providers is with a `client_secret`. Navigate to your Coder host and run the following command to start up the Coder
server:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about adding subheadings?

  1. CLI
  2. System Service
  3. Helm

Copy link
Member Author

@bpmct bpmct Aug 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im in favor of this!

```console
Expand Down Expand Up @@ -138,6 +136,74 @@ To upgrade Coder, run:
helm upgrade <release-name> coder-v2/coder -n <namespace> -f values.yaml
```

### Step 2 (JWT/PKI/Certificate Auth): Configure Coder with the OpenID Connect credentials

<blockquote class="warning">
<p>
Only <b>Azure AD</b> has been tested with this method. Other OIDC providers may not work, as most providers add additional requirements ontop of the standard that must be implemented. If you are using another provider and run into issues, please leave an issue on our <a href="https://github.com/coder/coder/issues">Github</a>.
</p>
</blockquote>
Comment on lines +141 to +145
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that sometimes we use these HTML blockquotes and sometimes GitHub Style blockquote.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I grabbed this warning from another page. I was unaware we had two methods 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other method is I am not sure if we support. I asked Bruno if he can add it.


An alternative authentication method is to use signed JWT tokens rather than a shared `client_secret`. This requires 2 files.

- An RSA private key file
- ```text
-----BEGIN RSA PRIVATE KEY-----
... Base64 encoded key ...
-----END RSA PRIVATE KEY-----
```
- The corresponding x509 certificate file
- ```text
-----BEGIN CERTIFICATE-----
... Base64 encoded x509 cert ...
-----END CERTIFICATE-----
```

You must upload the public key (the certificate) to your OIDC provider.
Reference the documentation provided by your provider on how to do this. Depending on the provider, the name for this feature varies.

- <!-- Azure --> Authentication certificate credentials
- <!-- Okta --> JWT for Client Authentication
- <!-- Auth0 --> Authenticate with Private Key JWT

Once the key and certificate are uploaded, you can run Coder with the files. Navigate to your Coder host and run the following command to start up the Coder server:

```console
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same concept of subheadings here.

coder server --oidc-issuer-url="https://issuer.corp.com" --oidc-email-domain="your-domain-1,your-domain-2" --oidc-client-key-file="/path/to/key.pem" --oidc-client-cert-file="/path/to/cert.pem"
```

If you are running Coder as a system service, you can achieve the same result as the command above by adding the following environment variables to the /etc/coder.d/coder.env file:

```console
CODER_OIDC_ISSUER_URL="https://issuer.corp.com"
CODER_OIDC_EMAIL_DOMAIN="your-domain-1,your-domain-2"
CODER_OIDC_CLIENT_KEY_FILE="/path/to/key.pem"
CODER_OIDC_CLIENT_CERT_FILE="/path/to/cert.pem"
```

Once complete, run sudo service coder restart to reboot Coder.

If deploying Coder via Helm, you can set the above environment variables in the values.yaml file as such:

```yaml
coder:
env:
- name: CODER_OIDC_ISSUER_URL
value: "https://issuer.corp.com"
- name: CODER_OIDC_EMAIL_DOMAIN
value: "your-domain-1,your-domain-2"
- name: CODER_OIDC_CLIENT_KEY_FILE
value: "/path/to/key.pem"
- name: CODER_OIDC_CLIENT_CERT_FILE
value: "/path/to/cert.pem"
```

To upgrade Coder, run:

```console
helm upgrade <release-name> coder-v2/coder -n <namespace> -f values.yaml
```

## OIDC Claims

When a user logs in for the first time via OIDC, Coder will merge both
Expand Down
42 changes: 42 additions & 0 deletions docs/admin/auth/adfs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Active Directory Federation Services OIDC with Coder (ADFS)

> **Note:** Tested on ADFS 4.0, Windows Server 2019
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> **Note:** Tested on ADFS 4.0, Windows Server 2019
> ![NOTE]
> Tested on ADFS 4.0, Windows Server 2019


1. In your Federation Server, create a new application group for Coder. Follow the
steps as described [here.](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/development/msal/adfs-msal-web-app-web-api#app-registration-in-ad-fs)
- **Server Application**: Note the Client ID.
- **Configure Application Credentials**: Note the Client Secret.
- **Configure Web API**: Set the Client ID as the relying party identifier.
- **Application Permissions**: Allow access to the claims `openid`, `email`, `profile`, and `allatclaims`.
1. Visit your ADFS server's `/.well-known/openid-configuration` URL and note
the value for `issuer`.
> **Note:** This is usually of the form `https://adfs.corp/adfs/.well-known/openid-configuration`
1. In Coder's configuration file (or Helm values as appropriate), set the following
environment variables or their corresponding CLI arguments:

- `CODER_OIDC_ISSUER_URL`: the `issuer` value from the previous step.
- `CODER_OIDC_CLIENT_ID`: the Client ID from step 1.
- `CODER_OIDC_CLIENT_SECRET`: the Client Secret from step 1.
- `CODER_OIDC_AUTH_URL_PARAMS`: set to

```console
{"resource":"$CLIENT_ID"}
```

where `$CLIENT_ID` is the Client ID from step 1 ([see here](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/overview/ad-fs-openid-connect-oauth-flows-scenarios#:~:text=scope%E2%80%AFopenid.-,resource,-optional)).
This is required for the upstream OIDC provider to return the requested claims.

- `CODER_OIDC_IGNORE_USERINFO`: Set to `true`.

1. Configure [Issuance Transform Rules](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-rule-to-send-ldap-attributes-as-claims)
on your federation server to send the following claims:

- `preferred_username`: You can use e.g. "Display Name" as required.
- `email`: You can use e.g. the LDAP attribute "E-Mail-Addresses" as required.
- `email_verified`: Create a custom claim rule:

```console
=> issue(Type = "email_verified", Value = "true")
```

- (Optional) If using Group Sync, send the required groups in the configured groups claim field. See [here](https://stackoverflow.com/a/55570286) for an example.
68 changes: 68 additions & 0 deletions docs/admin/auth/github.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# GitHub Authentication

With GitHub authentication, users can log in to your Coder deployment using their GitHub account. GitHub Enterprise deployments are also supported.

> **Note**: [group sync](#todo) and [role sync](#) are not supported for GitHub authentication methods.

## Configuring

### Step 1: Configure the OAuth application in GitHub

First, [register a GitHub OAuth app](https://developer.github.com/apps/building-oauth-apps/creating-an-oauth-app/). GitHub will ask you for the following Coder parameters:

- **Homepage URL**: Set to your Coder deployments [`CODER_ACCESS_URL`](https://coder.com/docs/v2/latest/cli/server#--access-url) (e.g. `https://coder.example.com`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- **Homepage URL**: Set to your Coder deployments [`CODER_ACCESS_URL`](https://coder.com/docs/v2/latest/cli/server#--access-url) (e.g. `https://coder.example.com`)
- **Homepage URL**: Set to your Coder deployments [`CODER_ACCESS_URL`](https://coder.com/docs/v2/latest/cli/server.md#--access-url) (e.g. `https://coder.example.com`)

Even if this is a valid URL, our URL checker gives a 404 if .md is missing.

- **User Authorization Callback URL**: Set to `https://coder.example.com/api/v2/users/oauth2/github/callback`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per my testing, it is enough to set it to https://coder.example.com or even https://example.com if you want multiple coder deployments on different subdomains to use the same GitHub OAuth app.

As per my understanding, Coder doesn't use the callback URL and sends a redirect_uri that is of the correct form.

See, we are doing it here.

redirectURL, err := accessURL.Parse("/api/v2/users/oauth2/github/callback")

@deansheather for confirmation, please.


> Note: If you want to allow multiple coder deployments hosted on subdomains e.g. coder1.example.com, coder2.example.com, to be able to authenticate with the same GitHub OAuth app, then you can set **User Authorization Callback URL** to the `https://example.com`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> Note: If you want to allow multiple coder deployments hosted on subdomains e.g. coder1.example.com, coder2.example.com, to be able to authenticate with the same GitHub OAuth app, then you can set **User Authorization Callback URL** to the `https://example.com`
> [!NOTE]
> If you want to allow multiple coder deployments hosted on subdomains, e.g., `coder1.example.com`, `coder2.example.com`, to be able to authenticate with the same GitHub OAuth app, then you can set **User Authorization Callback URL** to the `https://example.com`


Note the Client ID and Client Secret generated by GitHub. You will use these
values in the next step.

### Step 2: Configure Coder with the OAuth credentials

See [configuring Coder](../configure.md) to learn how to modify your server configuration depending on your platform (e.g. Kubernetes, system service, etc).

Set the following environment variables for your Coder server:

```console
CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS=true
CODER_OAUTH2_GITHUB_ALLOWED_ORGS="your-org"
CODER_OAUTH2_GITHUB_CLIENT_ID="8d1...e05"
CODER_OAUTH2_GITHUB_CLIENT_SECRET="57ebc9...02c24c"
```

If you are using GitHub enterprise, set:

```console
CODER_OAUTH2_GITHUB_ENTERPRISE_BASE_URL=https://github.example.com
```

To allow everyone to signup using GitHub, set:

```console
CODER_OAUTH2_GITHUB_ALLOW_EVERYONE=true
```

To restrict specific teams, set:

```console
CODER_OAUTH2_GITHUB_ALLOWED_TEAMS=frontend,backend
```

Once complete, restart your server. GitHub authentication should appear on your log-in screen 🎉

![Log in with GitHub button](https://user-images.githubusercontent.com/22407953/261880741-87bfb1cb-7ea3-41b5-8eef-200552157cda.png)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace with a relative image URL.
Also, you can use the excellent VS Code Doc Writer profile to preview your changes better.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I like to preview with the coder site too


> We recommend requiring and auditing MFA usage for all users in your GitHub
> organizations. This can be enforced from the organization settings page in the
> "Authentication security" sidebar tab.
Comment on lines +56 to +58
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> We recommend requiring and auditing MFA usage for all users in your GitHub
> organizations. This can be enforced from the organization settings page in the
> "Authentication security" sidebar tab.
> [!NOTE]
> We recommend requiring and auditing MFA usage for all users in your GitHub
> organizations. This can be enforced from the organization settings page in the
> "Authentication security" sidebar tab.


## Restrict GitHub Signups

If you wish to manually onboard users, or use a [script](../automation.md) to add users to Coder, set:

```console
CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS=false
```

This will prevent new users from logging in via GitHub. An admin can manually add GitHub users from the "Users" page.
137 changes: 137 additions & 0 deletions docs/admin/auth/group-role-sync.md
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, this section should not be under auth directory as it is not an auth method but a feature on top of OIDC/SAML. May be we should have a subdirectory OIDC under auth directory and move this along with setting up OIDC.

These are my thoughts, and they are not very important. If you feel the current flow and organization are right. Please ignore this comment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, that makes sense to me too. Like "Identity Providers" can be a subsection under OIDC and have each one listed.

Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Group & Role Sync (Enterprise)

You can use groups and roles from your identity provider as the definitive source for Coder's user roles and groups.

## How it Works

1. **Configure OIDC**: Adjust your OIDC identity provider settings to transmit claims via the OIDC token or userinfo endpoint. These claims, usually labeled `groups` and `roles`, aren't sent by default in most OIDC clients.

1. **Configure Coder Server**: Coder can either:
- A) Create new groups in Coder, or
- B) Map claims to existing Coder groups/roles.

1. **Roles Sync on Login**: Upon user authentication, their associated groups and roles synchronize with Coder, using the identity provider as the reference.

## Group Sync (enterprise)

If your OpenID Connect provider supports group claims, you can configure Coder
to synchronize groups in your auth provider to groups within Coder.

To enable group sync, ensure that a groups claim is being sent. This is often `groups` or `memberOf`. Technically, a `roles` claim could be mapped to syncronize groups as Coder just expects an array of strings (e.g. `["Admin", "DevOps-Admin"`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To enable group sync, ensure that a groups claim is being sent. This is often `groups` or `memberOf`. Technically, a `roles` claim could be mapped to syncronize groups as Coder just expects an array of strings (e.g. `["Admin", "DevOps-Admin"`)
To enable group sync, ensure that a group's claim is being sent. This is often `groups` or `memberOf`. Technically, a `roles` claim could be mapped to synchronize groups as Coder just expects an array of strings (e.g., `["Admin", "DevOps-Admin"`)


To check, [configure](../configure.md) the Coder server with the following environment variable to send verbose logs:

```sh
CODER_VERBOSE=true
```

Be sure to restart the server. When a user logs in with OIDC, you should see the following logs from the server.


```sh
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```sh
```shell

shell is more general

[debu] coderd.userauth: got oidc claims trace=0x1b09780 span=0x1b09820 request_id=833f136a-2e6b-4df5-8ecb-1316c71a425a source=id_token claim_fields="[aio aud email exp groups iat idp iss name nbf oid preferred_username rh sub tid uti ver]" blank=[]

[debu] coderd.userauth: got oidc claims trace=0x1b09780 span=0x1b09820 request_id=833f136a-2e6b-4df5-8ecb-1316c71a425a source=userinfo claim_fields="[email family_name given_name name picture sub]" blank=[]

[debu] coderd.userauth: got oidc claims trace=0x1b09780 span=0x1b09820 request_id=833f136a-2e6b-4df5-8ecb-1316c71a425a source=merged claim_fields="[aio aud email exp family_name given_name groups iat idp iss name nbf oid picture preferred_username rh sub tid uti ver]" blank=[]
```

> ℹ️ In this example, Coder is successfully getting the `groups` OIDC claim from the token and merging the claims from userinfo endpoint. See below for troubleshooting instructions.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related to this PR. But I wonder if we should have different types of Notes e.g.,

Note

A note

Important

An important information

Warning

Be careful here

https://github.com/orgs/community/discussions/16925 for details

Copy link
Member

@matifali matifali Aug 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BrunoQuaresma, can these be rendered on coder.com/v2/docs
With some research, I found https://www.npmjs.com/package/remark-github-beta-blockquote-admonitions

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> ℹ️ In this example, Coder is successfully getting the `groups` OIDC claim from the token and merging the claims from userinfo endpoint. See below for troubleshooting instructions.
> [!NOTE]
> In this example, Coder successfully gets the `groups` OIDC claim from the token and merges the claims from the userinfo endpoint. Please take a look at the troubleshooting instructions below.

as per https://github.com/orgs/community/discussions/16925


### Enabling Group Sync

To enable group sync, you must tell Coder which claim to be used:

```sh
CODER_OIDC_GROUP_FIELD=groups
```

By default, Coder will only sync groups that match an existing group in Coder. However, there are two other options.

#### Automatically Create New Groups

To automatically create groups in Coder if they don't exist, set the following server value:

```console
CODER_OIDC_GROUP_AUTO_CREATE=true
```

#### Configuring Group Mapping

For cases when an OIDC provider only returns group IDs ([Azure AD][azure-gids])
or you want to have different group names in Coder than in your OIDC provider,
you can configure mapping between the two.

```console
CODER_OIDC_GROUP_MAPPING='{"myOIDCGroupID": "myCoderGroupName"}'
```

Below is an example mapping in the Coder Helm chart:

```yaml
coder:
env:
- name: CODER_OIDC_GROUP_MAPPING
value: >
{"myOIDCGroupID": "myCoderGroupName"}
```

### Filtering Group Sync

A basic regex filtering option on the Coder side is available. This is applied **after** the group mapping (`CODER_OIDC_GROUP_MAPPING`), meaning if the group is remapped, the remapped value is tested in the regex. This is useful if you want to filter out groups that do not match a certain pattern. For example, if you want to only allow groups that start with `my-group-` to be created, you can set the following environment variable.

```console
CODER_OIDC_GROUP_REGEX_FILTER="^my-group-.*$"
```

## Role Sync (enterprise)

If your OpenID Connect provider supports roles claims, you can configure Coder
to synchronize roles in your auth provider to deployment-wide roles within Coder.

Set the following in your Coder server [configuration](./configure.md).

```console
# Depending on your identity provider configuration, you may need to explicitly request a "roles" scope
CODER_OIDC_SCOPES=openid,profile,email,roles

# The following fields are required for role sync:
CODER_OIDC_USER_ROLE_FIELD=roles
CODER_OIDC_USER_ROLE_MAPPING='{"TemplateAuthor":["template-admin","user-admin"]}'
```

> One role from your identity provider can be mapped to many roles in Coder (e.g. the example above maps to 2 roles in Coder.)

[azure-gids]: https://github.com/MicrosoftDocs/azure-docs/issues/59766#issuecomment-664387195

### Troubleshooting

Some common issues when enabling group and role sync.

#### No `groups` claim in the `got oidc claims` log

If you are not recieving the `groups` claim, refer to your identify provider documentation. In some cases, you will need to add the claim to your identity provider and request it via a scope in the OIDC config:

```sh
CODER_OIDC_SCOPES=openid,profile,email,groups
```

Here are some general steps:

1. Ensure the user is a part of a group in the IDP. If the user has 0 groups, no `groups` claim will be sent.
2. Check if another claim appears to be the correct claim with a different name. A common name is `memberOf` instead of `groups`. If this is present, update `CODER_OIDC_GROUP_FIELD=memberOf`.
3. Make sure the number of groups being sent is under the limit of the IDP. Some IDPs will return an error, while others will just omit the `groups` claim. A common solution is to create a filter on the identity provider that returns less than the limit for your IDP.
- [Azure AD limit is 200, and omits groups if exceeded.](https://learn.microsoft.com/en-us/azure/active-directory/hybrid/connect/how-to-connect-fed-group-claims#options-for-applications-to-consume-group-information)
- [Okta limit is 100, and returns an error if exceeded.](https://developer.okta.com/docs/reference/api/oidc/#scope-dependent-claims-not-always-returned)

#### Invalid Scope

If you see an error like the following, you may have an invalid scope.

```console
The application '<oidc_application>' asked for scope 'groups' that doesn't exist on the resource...
```

This can happen because the identity provider has a different name for the scope. For example, Azure AD uses `GroupMember.Read.All` instead of `groups`. You can find the correct scope name in the IDP's documentation. Some IDP's allow configuring the name of this scope.

The solution is to update the value of `CODER_OIDC_SCOPES` to the correct value for the identity provider.
15 changes: 15 additions & 0 deletions docs/admin/auth/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Authentication

By default, Coder is accessible via password authentication. Coder does not
recommend using password authentication in production, and recommends using an
authentication provider with properly configured multi-factor authentication
(MFA). It is your responsibility to ensure the auth provider enforces MFA
correctly.

The following authentication methods are supported:

<children>
This page is rendered on https://coder.com/docs/v2/latest/admin/auth. Refer to the other documents in this directory for per-platform instructions.
</children>

A user can only log in with one authentication method, but can convert their account from a built-in account to an OIDC account in their account settings.
7 changes: 7 additions & 0 deletions docs/admin/auth/keycloak.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Keycloak Authentication with Coder

The access_type parameter has two possible values: "online" and "offline." By default, the value is set to "offline". This means that when a user authenticates using OIDC, the application requests offline access to the user's resources, including the ability to refresh access tokens without requiring the user to reauthenticate.

To enable the `offline_access` scope, which allows for the refresh token functionality, you need to add it to the list of requested scopes during the authentication flow. Including the `offline_access` scope in the requested scopes ensures that the user is granted the necessary permissions to obtain refresh tokens.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we provide the example?

CODER_OIDC_SCOPES=openid,profile,email,offline_access

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better if we also include an example


By combining the `{"access_type":"offline"}` parameter in the OIDC Auth URL with the `offline_access` scope, you can achieve the desired behavior of obtaining refresh tokens for offline access to the user's resources.
Loading