You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-`Members`: Read-only (required for team-based resource access control and group sync)
126
+
127
+
> **Important**: `Members: Read-only` is required for the Hub's platform-owned team synchronization. Without this organization permission, the Hub cannot list organization teams or team members and logs errors such as `Resource not accessible by integration` when calling the GitHub GraphQL API.
@@ -133,12 +135,26 @@ Teams allow you to organize members and control access to different resources in
133
135

134
136
135
137
5. After creation, note down the following:
136
-
-**Client ID**: Displayed on the App's General page (e.g., `Iv23liXXXXXX`)
137
-
-**Client secret**: Click **Generate a new client secret** — copy it immediately
138
-
-**App slug**: The URL-safe name in the App's URL (e.g., `auplc-hub`)
138
+
-**Client ID**: Displayed on the App's General page (e.g., `Iv23liXXXXXX`)
139
+
-**Client secret**: Click **Generate a new client secret** — copy it immediately
140
+
-**App ID**: Displayed on the App's General page. This is different from the Client ID.
141
+
-**App slug**: The URL-safe name in the App's URL (e.g., `auplc-hub`)
139
142
140
143

141
144
145
+
6. Generate a private key:
146
+
- On the App's General page, click **Generate a private key**.
147
+
- Store the downloaded `.pem` file as a Kubernetes secret or mount it into the Hub pod by your deployment's secret-management process.
148
+
- Record the mounted file path. You will use it as `hub.config.GitHubOAuthenticator.private_key_file`.
149
+
150
+
7. Install the GitHub App on the organization:
151
+
- Open the App's **Install App** page.
152
+
- Install it on the same organization configured as `custom.githubOrgName`.
153
+
- Select the repositories users may access if private repository cloning is enabled.
154
+
- If you later add or change permissions, an organization owner must approve the updated installation permissions.
155
+
156
+
`installation_id` does not normally need to be configured manually. The Hub can discover it from the organization installation with `GET /orgs/{org}/installation` as long as the app is installed on that organization.
157
+
142
158
## Step 5: Configure JupyterHub
143
159
144
160
1. Open your deployment configuration file (`runtime/values.yaml` or environment-specific override)
@@ -147,13 +163,20 @@ Teams allow you to organize members and control access to different resources in
# private_key: "" # Alternative to private_key_file; prefer mounted secrets for production
179
+
team_sync_ttl_seconds: 3600
157
180
client_id: "<GitHub App Client ID>"
158
181
client_secret: "<GitHub App Client Secret>"
159
182
allowed_organizations:
@@ -163,6 +186,10 @@ Teams allow you to organize members and control access to different resources in
163
186
164
187
> **Note**: `scope: []` is correct for GitHub Apps. Permissions (Contents, Members, etc.) are configured in the App settings on GitHub, not via OAuth scopes.
165
188
189
+
> **Tip**: The Hub uses the GitHub App installation token for server-to-server team synchronization. It first lists actual organization teams, intersects them with `custom.teams.mapping`, and then batches team member lookups through GitHub GraphQL. This avoids per-user OAuth token lookups and reduces GitHub API traffic. If a configured team no longer exists on GitHub, it is logged and skipped instead of failing the entire sync.
190
+
191
+
> **Warning**: The GitHub App must still be installed on the organization. Leaving `installation_id` blank only skips manual ID entry; it does not remove the installation requirement.
192
+
166
193
3. Configure team-to-resource mapping in `values.yaml`:
167
194
168
195
```yaml
@@ -182,6 +209,8 @@ Teams allow you to organize members and control access to different resources in
182
209
- Course-LLM
183
210
```
184
211
212
+
Team mapping keys should correspond to GitHub team names/slugs. The Hub normalizes configured keys for GitHub API lookup, for example `AUP` is queried as the GitHub team slug `aup`, while the JupyterHub group remains `AUP`.
213
+
185
214
4. Deploy:
186
215
187
216
```bash
@@ -201,6 +230,9 @@ Teams allow you to organize members and control access to different resources in
201
230
- **OAuth callback error**: Ensure your callback URL exactly matches what you configured in GitHub (including HTTPS)
202
231
- **Organization not found**: Verify the organization name in your configuration matches your GitHub organization exactly
203
232
- **Users can't access resources**: Check that users are added to the correct teams in GitHub
233
+
- **Team sync fails with `Resource not accessible by integration`**: Ensure the GitHub App installation on your organization has `Members: Read-only` under Organization permissions. If you changed permissions after installing the app, an organization owner must approve the updated permissions on the installed app.
234
+
- **Configured team is skipped**: Verify the team exists in the GitHub organization. The Hub lists actual GitHub teams first and only syncs teams that exist.
235
+
- **Installation token unavailable**: Verify `app_id` and `private_key_file` are configured and that the GitHub App is installed on `custom.githubOrgName`. `installation_id` can usually remain blank.
204
236
- **Authentication fails**: Verify your Client ID and Client Secret are correct and the secret hasn't expired
205
237
206
238
## Migrating from OAuth App to GitHub App
@@ -220,16 +252,22 @@ If you are currently using a legacy GitHub OAuth App, follow these steps to migr
220
252
221
253
1. **Create a GitHub App** under your organization (see [Step 4](#step-4-create-a-github-app) above)
-`Members`: Read-only (required for team-based resource access control and group sync)
97
+
98
+
:::{important}
99
+
`Members: Read-only` is required for the Hub's platform-owned team synchronization. Without this organization permission, the Hub cannot list organization teams or team members and logs errors such as `Resource not accessible by integration` when calling the GitHub GraphQL API.
100
+
:::
97
101
98
102
4. Installation scope:
99
103
-**Where can this GitHub App be installed?**: Any account
100
104
- Click **Create GitHub App**
101
105
102
106
5. After creation, note down the following:
103
-
-**Client ID**: Displayed on the App's General page (e.g., `Iv23liXXXXXX`)
104
-
-**Client secret**: Click **Generate a new client secret** -- copy it immediately
105
-
-**App slug**: The URL-safe name in the App's URL (e.g., `auplc-hub`)
107
+
-**Client ID**: Displayed on the App's General page (e.g., `Iv23liXXXXXX`)
108
+
-**Client secret**: Click **Generate a new client secret** -- copy it immediately
109
+
-**App ID**: Displayed on the App's General page. This is different from the Client ID.
110
+
-**App slug**: The URL-safe name in the App's URL (e.g., `auplc-hub`)
111
+
112
+
6. Generate a private key:
113
+
- On the App's General page, click **Generate a private key**.
114
+
- Store the downloaded `.pem` file as a Kubernetes secret or mount it into the Hub pod by your deployment's secret-management process.
115
+
- Record the mounted file path. You will use it as `hub.config.GitHubOAuthenticator.private_key_file`.
116
+
117
+
7. Install the GitHub App on the organization:
118
+
- Open the App's **Install App** page.
119
+
- Install it on the same organization configured as `custom.githubOrgName`.
120
+
- Select the repositories users may access if private repository cloning is enabled.
121
+
- If you later add or change permissions, an organization owner must approve the updated installation permissions.
122
+
123
+
`installation_id` does not normally need to be configured manually. The Hub can discover it from the organization installation with `GET /orgs/{org}/installation` as long as the app is installed on that organization.
106
124
107
125
## Step 5: Configure JupyterHub
108
126
@@ -112,22 +130,37 @@ GitHub Apps are the recommended way to integrate with GitHub. They are created u
`scope: []` is correct for GitHub Apps. Permissions (Contents, Members, etc.) are configured in the App settings on GitHub, not via OAuth scopes.
154
+
:::{note}
155
+
`scope: []` is correct for GitHub Apps. Permissions (Contents, Members, etc.) are configured in the App settings on GitHub, not via OAuth scopes.
156
+
:::
157
+
158
+
:::{tip}
159
+
The Hub uses the GitHub App installation token for server-to-server team synchronization. It first lists actual organization teams, intersects them with `custom.teams.mapping`, and then batches team member lookups through GitHub GraphQL. This avoids per-user OAuth token lookups and reduces GitHub API traffic. If a configured team no longer exists on GitHub, it is logged and skipped instead of failing the entire sync.
160
+
:::
161
+
162
+
:::{warning}
163
+
The GitHub App must still be installed on the organization. Leaving `installation_id` blank only skips manual ID entry; it does not remove the installation requirement.
131
164
:::
132
165
133
166
3. Configure team-to-resource mapping in `values.yaml`:
@@ -149,6 +182,8 @@ GitHub Apps are the recommended way to integrate with GitHub. They are created u
149
182
- Course-LLM
150
183
```
151
184
185
+
Team mapping keys should correspond to GitHub team names/slugs. The Hub normalizes configured keys for GitHub API lookup, for example `AUP` is queried as the GitHub team slug `aup`, while the JupyterHub group remains `AUP`.
186
+
152
187
4. Deploy:
153
188
154
189
```bash
@@ -168,6 +203,9 @@ GitHub Apps are the recommended way to integrate with GitHub. They are created u
168
203
- **OAuth callback error**: Ensure your callback URL exactly matches what you configured in GitHub (including HTTPS)
169
204
- **Organization not found**: Verify the organization name in your configuration matches your GitHub organization exactly
170
205
- **Users can't access resources**: Check that users are added to the correct teams in GitHub
206
+
- **Team sync fails with `Resource not accessible by integration`**: Ensure the GitHub App installation on your organization has `Members: Read-only` under Organization permissions. If you changed permissions after installing the app, an organization owner must approve the updated permissions on the installed app.
207
+
- **Configured team is skipped**: Verify the team exists in the GitHub organization. The Hub lists actual GitHub teams first and only syncs teams that exist.
208
+
- **Installation token unavailable**: Verify `app_id` and `private_key_file` are configured and that the GitHub App is installed on `custom.githubOrgName`. `installation_id` can usually remain blank.
171
209
- **Authentication fails**: Verify your Client ID and Client Secret are correct and the secret hasn't expired
172
210
173
211
## Migrating from OAuth App to GitHub App
@@ -187,16 +225,22 @@ If you are currently using a legacy GitHub OAuth App, follow these steps to migr
187
225
188
226
1. **Create a GitHub App** under your organization (see Step 4 above)
0 commit comments