From 0801760956692934f911cad8e897d5f9149d1ae1 Mon Sep 17 00:00:00 2001
From: Stephen Kirby <58410745+stirby@users.noreply.github.com>
Date: Fri, 15 Dec 2023 11:10:41 -0600
Subject: [PATCH] docs: add guides section (#11199)
* setup manifest
* added okta guide from steven M
* improved index by adding children
* changed icon to notes.svg
* added meta guide, fixed profile photo fmt
---
docs/guides/configuring-okta.md | 160 ++++++++++++++++++
docs/guides/example-guide.md | 54 ++++++
docs/guides/index.md | 10 ++
docs/images/guides/okta/add_attribute.png | Bin 0 -> 107165 bytes
docs/images/guides/okta/add_claim.png | Bin 0 -> 36151 bytes
.../guides/okta/add_claim_with_roles.png | Bin 0 -> 36151 bytes
docs/images/guides/okta/add_scope.png | Bin 0 -> 57727 bytes
docs/images/guides/okta/api_view.png | Bin 0 -> 27646 bytes
docs/images/guides/okta/oidc_id_token.png | Bin 0 -> 33699 bytes
docs/images/guides/okta/token_preview.png | Bin 0 -> 120252 bytes
docs/manifest.json | 13 ++
11 files changed, 237 insertions(+)
create mode 100644 docs/guides/configuring-okta.md
create mode 100644 docs/guides/example-guide.md
create mode 100644 docs/guides/index.md
create mode 100644 docs/images/guides/okta/add_attribute.png
create mode 100644 docs/images/guides/okta/add_claim.png
create mode 100644 docs/images/guides/okta/add_claim_with_roles.png
create mode 100644 docs/images/guides/okta/add_scope.png
create mode 100644 docs/images/guides/okta/api_view.png
create mode 100644 docs/images/guides/okta/oidc_id_token.png
create mode 100644 docs/images/guides/okta/token_preview.png
diff --git a/docs/guides/configuring-okta.md b/docs/guides/configuring-okta.md
new file mode 100644
index 0000000000..e87552be76
--- /dev/null
+++ b/docs/guides/configuring-okta.md
@@ -0,0 +1,160 @@
+# Configuring Custom Claims/Scopes with Okta for group/role
+
+
+December 13, 2023
+
+---
+
+> Okta is an identity provider that can be used for OpenID Connect (OIDC) Single
+> Sign On (SSO) on Coder.
+
+To configure custom claims in Okta to support syncing roles and groups with
+Coder, you must first have setup an Okta application with
+[OIDC working with Coder](https://coder.com/docs/v2/latest/admin/auth#openid-connect).
+From here, we will add additional claims for Coder to use for syncing groups and
+roles.
+
+You may use a hybrid of the following approaches.
+
+# (Easiest) Sync using Okta Groups
+
+If the Coder roles & Coder groups can be inferred from
+[Okta groups](https://help.okta.com/en-us/content/topics/users-groups-profiles/usgp-about-groups.htm),
+Okta has a simple way to send over the groups as a `claim` in the `id_token`
+payload.
+
+In Okta, go to the application “Sign On” settings page.
+
+Applications > Select Application > General > Sign On
+
+In the “OpenID Connect ID Token” section, turn on “Groups Claim Type” and set
+the “Claim name” to `groups`. Optionally configure a filter for which groups to
+be sent.
+
+> !! If the user does not belong to any groups, the claim will not be sent. Make
+> sure the user authenticating for testing is in at least 1 group. Defer to
+> [troubleshooting](https://coder.com/docs/v2/latest/admin/auth#troubleshooting)
+> with issues
+
+
+
+Configure Coder to use these claims for group sync. These claims are present in
+the `id_token`. See all configuration options for group sync in the
+[docs](https://coder.com/docs/v2/latest/admin/auth#group-sync-enterprise).
+
+```bash
+# Add the 'groups' scope.
+CODER_OIDC_SCOPES=openid,profile,email,groups
+# This name needs to match the "Claim name" in the configuration above.
+CODER_OIDC_GROUP_FIELD=groups
+```
+
+These groups can also be used to configure role syncing based on group
+membership.
+
+```bash
+# Requires the "groups" scope
+CODER_OIDC_SCOPES=openid,profile,email,groups
+# This name needs to match the "Claim name" in the configuration above.
+CODER_OIDC_USER_ROLE_FIELD=groups
+# Example configuration to map a group to some roles
+CODER_OIDC_USER_ROLE_MAPPING='{"admin-group":["template-admin","user-admin"]}'
+```
+
+# (Easy) Mapping Okta profile attributes
+
+If roles or groups cannot be completely inferred from Okta group memberships,
+another option is to source them from a user’s attributes. The user attribute
+list can be found in “Directory > Profile Editor > User (default)”.
+
+Coder can query an Okta profile for the application from the `/userinfo` OIDC
+endpoint. To pass attributes to Coder, create the attribute in your application,
+then add a mapping from the Okta profile to the application.
+
+“Directory > Profile Editor > {Your Application} > Add Attribute”
+
+Create the attribute for the roles, groups, or both. **Make sure the attribute
+is of type `string array`.**
+
+
+
+On the “Okta User to {Your Application}” tab, map a `roles` or `groups`
+attribute you have configured to the application.
+
+
+
+Configure using these new attributes in Coder.
+
+```bash
+# This must be set to false. Coder uses this endpoint to grab the attributes.
+CODER_OIDC_IGNORE_USERINFO=false
+# No custom scopes are required.
+CODER_OIDC_SCOPES=openid,profile,email
+# Configure the group/role field using the attribute name in the application.
+CODER_OIDC_USER_ROLE_FIELD=approles
+# See our docs for mapping okta roles to coder roles.
+CODER_OIDC_USER_ROLE_MAPPING='{"admin-group":["template-admin","user-admin"]}'
+
+# If you added an attribute for groups, set that here.
+# CODER_OIDC_GROUP_FIELD=...
+```
+
+# (Advanced) Custom scopes to retrieve custom claims
+
+Okta does not support setting custom scopes and claims in the default
+authorization server used by your application. If you require this
+functionality, you must create (or modify) an authorization server.
+
+To see your custom authorization servers go to “Security > API”. Note the
+`default` authorization server **is not the authorization server your app is
+using.** You can configure this default authorization server, or create a new
+one specifically for your application.
+
+Authorization servers also give more refined controls over things such as
+token/session lifetimes.
+
+
+
+To get custom claims working, we should map them to a custom scope. Click the
+authorization server you wish to use (likely just using the default).
+
+Go to “Scopes”, and “Add Scope”. Feel free to create one for roles, groups, or
+both.
+
+
+
+Now create the claim to go with the said scope. Go to “Claims”, then “Add
+Claim”. Make sure to select **ID Token** for the token type. The **Value**
+expression is up to you based on where you are sourcing the role information.
+Lastly, configure it to only be a claim with the requested scope. This is so if
+other applications exist, we do not send them information they do not care
+about.
+
+
+
+Now we have a custom scope + claim configured under an authorization server, we
+need to configure coder to use this.
+
+```bash
+# Grab this value from the Authorization Server > Settings > Issuer
+# DO NOT USE the application issuer URL. Make sure to use the newly configured
+# authorization server.
+CODER_OIDC_ISSUER_URL=https://dev-12222860.okta.com/oauth2/default
+# Add the new scope you just configured
+CODER_OIDC_SCOPES=openid,profile,email,roles
+# Use the claim you just configured
+CODER_OIDC_USER_ROLE_FIELD=roles
+# See our docs for mapping okta roles to coder roles.
+CODER_OIDC_USER_ROLE_MAPPING='{"admin-group":["template-admin","user-admin"]}'
+```
+
+You can use the “Token Preview” page to verify it has been correctly configured
+and verify the `roles` is in the payload.
+
+
diff --git a/docs/guides/example-guide.md b/docs/guides/example-guide.md
new file mode 100644
index 0000000000..820a6f3ffe
--- /dev/null
+++ b/docs/guides/example-guide.md
@@ -0,0 +1,54 @@
+# Guide Title (Only Visible in Github)
+
+
+December 13, 2023
+
+---
+
+This is a guide on how to make Coder guides, it is not listed on our
+[official guides page](coder.com/docs/v2/latest/guides) in the docs. This is
+intended for those who don't frequently contribute documentation changes to the
+`coder/coder` repository.
+
+## Content
+
+Defer to our
+[Contributing/Documentation](coder.com/docs/v2/latest/contributing/documentation)
+page for rules on technical writing.
+
+### Adding Photos
+
+Use relative imports in the markdown and store photos in
+`docs/images/guides//.png`.
+
+### Setting the author data
+
+At the top of this example you will find a small html snippet that nicely
+renders the author's name and photo, while linking to their Github profile.
+Before submitting your guide in a PR, replace `your_github_handle`,
+`your_github_profile_photo_url` and "Your Name". The entire `
` element can
+be omitted.
+
+## Setting up the routes
+
+Once you've written your guide, you'll need to add its route to
+`docs/manifest.json` under `Guides` > `"children"` at the bottom:
+
+```json
+{
+ // Overrides the "# Guide Title" at the top of this file
+ "title": "Contributing to Guides",
+ "description": "How to add a guide",
+ "path": "./guides/my-guide-file.md"
+},
+```
+
+## Format before push
+
+Before pushing your guide to github, run `make fmt` to format the files with
+Prettier. Then, push your changes to a new branch and create a PR.
diff --git a/docs/guides/index.md b/docs/guides/index.md
new file mode 100644
index 0000000000..d33a7a3ed3
--- /dev/null
+++ b/docs/guides/index.md
@@ -0,0 +1,10 @@
+# Guides and Tutorials
+
+Here you can find a list of employee-written guides on Coder for OSS and
+Enterprise. These tutorials are hosted on our
+[Github](https://github.com/coder/coder/) where you can leave feedback or
+request new topics to be covered.
+
+
+ This page is rendered on https://coder.com/docs/v2/latest/guides. Refer to the other documents in the `guides/` directory for specific employee-written guides.
+
diff --git a/docs/images/guides/okta/add_attribute.png b/docs/images/guides/okta/add_attribute.png
new file mode 100644
index 0000000000000000000000000000000000000000..a849f95d8f8a1b4d3a9db6dbc2e9b1e60aedba70
GIT binary patch
literal 107165
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