From 2ad4402b69d30602d7e1c7eb9fcc72dd9f9d3e33 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Sat, 2 Dec 2023 16:16:36 -0500 Subject: [PATCH 1/5] lib: Allow parent scopes in lieu of exact ones I'd rather folks not put more scopes on their tokens than they actually need... But the fact this doesn't work is confusing. We've had to troubleshoot this scenario with users multiple times. And that's just the ones who reached out about it. Others are likely affected and unsure how to log in. This allows supersets of the actually required scopes. Note to users: Please just set the actual needed scopes... --- lib/models/github-login-model.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/models/github-login-model.js b/lib/models/github-login-model.js index d060a50bfb..ea4accedc9 100644 --- a/lib/models/github-login-model.js +++ b/lib/models/github-login-model.js @@ -70,6 +70,14 @@ export default class GithubLoginModel { for (const scope of this.constructor.REQUIRED_SCOPES) { if (!scopeSet.has(scope)) { + if (scope === 'read:org' && scopeSet.has('admin:org')) { + // 'admin:org' is a superset of, and implies, 'read:org'. + continue; + } + if (scope === 'user:email' && scopeSet.has('user')) { + // 'user' is a superset of, and implies, 'user:email'. + continue; + } // Token doesn't have enough OAuth scopes, need to reauthenticate this.checked.set(fingerprint, INSUFFICIENT); return INSUFFICIENT; From 7c889ec4be01ba7311ee9a82d699e7d55600970e Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Sat, 2 Dec 2023 16:23:14 -0500 Subject: [PATCH 2/5] lib: Warn in console when user's token has excessive scopes --- lib/models/github-login-model.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/models/github-login-model.js b/lib/models/github-login-model.js index ea4accedc9..9a1eb54fed 100644 --- a/lib/models/github-login-model.js +++ b/lib/models/github-login-model.js @@ -72,10 +72,14 @@ export default class GithubLoginModel { if (!scopeSet.has(scope)) { if (scope === 'read:org' && scopeSet.has('admin:org')) { // 'admin:org' is a superset of, and implies, 'read:org'. + console.warn('Excessive scopes detected on your github token. Please only set the actually needed scopes on your PAT.') + console.warn('Excessive scope "admin:org" should be "read:org" instead.') continue; } if (scope === 'user:email' && scopeSet.has('user')) { // 'user' is a superset of, and implies, 'user:email'. + console.warn('Excessive scopes detected on your github token. Please only set the actually needed scopes on your PAT.') + console.warn('Excessive scope "user" should be "user:email" instead.') continue; } // Token doesn't have enough OAuth scopes, need to reauthenticate From 28b92cdc2229865254e71e6facd4f4176b5bd5c2 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Sat, 2 Dec 2023 16:31:22 -0500 Subject: [PATCH 3/5] lib: Allow just 'public_repo', stop requiring full 'repo' scope. Just 'public_repo' is pretty-well sufficient to interact with the GitHub integration this package provides. --- lib/models/github-login-model.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/models/github-login-model.js b/lib/models/github-login-model.js index 9a1eb54fed..40cb60ceba 100644 --- a/lib/models/github-login-model.js +++ b/lib/models/github-login-model.js @@ -8,7 +8,7 @@ let instance = null; export default class GithubLoginModel { // Be sure that we're requesting at least this many scopes on the token we grant through github.atom.io or we'll // give everyone a really frustrating experience ;-) - static REQUIRED_SCOPES = ['repo', 'read:org', 'user:email'] + static REQUIRED_SCOPES = ['public_repo', 'read:org', 'user:email'] static get() { if (!instance) { @@ -70,6 +70,11 @@ export default class GithubLoginModel { for (const scope of this.constructor.REQUIRED_SCOPES) { if (!scopeSet.has(scope)) { + if (scope === 'public_repo' && scopeSet.has('repo')) { + // 'repo' is a superset of, and implies, 'public_repo'. + // Setting just 'public_repo' or full 'repo' both have legitimate use-cases. So we won't warn about it. + continue; + } if (scope === 'read:org' && scopeSet.has('admin:org')) { // 'admin:org' is a superset of, and implies, 'read:org'. console.warn('Excessive scopes detected on your github token. Please only set the actually needed scopes on your PAT.') From 507fdafde2c7ee67ca50c9c6c53f95d208056cb6 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Sat, 2 Dec 2023 17:08:01 -0500 Subject: [PATCH 4/5] lib: Show hint in token entry view when token lacks required scopes Also log in the console which scope is missing. --- lib/models/github-login-model.js | 1 + lib/views/github-login-view.js | 13 +++++++++++++ lib/views/github-tab-view.js | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/models/github-login-model.js b/lib/models/github-login-model.js index 40cb60ceba..219b4974e1 100644 --- a/lib/models/github-login-model.js +++ b/lib/models/github-login-model.js @@ -88,6 +88,7 @@ export default class GithubLoginModel { continue; } // Token doesn't have enough OAuth scopes, need to reauthenticate + console.log("GitHub token doesn't have a required scope! Missing: " + scope); this.checked.set(fingerprint, INSUFFICIENT); return INSUFFICIENT; } diff --git a/lib/views/github-login-view.js b/lib/views/github-login-view.js index 4d0ef962ab..cada25da73 100644 --- a/lib/views/github-login-view.js +++ b/lib/views/github-login-view.js @@ -2,11 +2,13 @@ import React from 'react'; import PropTypes from 'prop-types'; import {autobind} from '../helpers'; +import {INSUFFICIENT} from '../shared/keytar-strategy'; export default class GithubLoginView extends React.Component { static propTypes = { children: PropTypes.node, onLogin: PropTypes.func, + tokenStatus: PropTypes.symbol, } static defaultProps = { @@ -15,6 +17,7 @@ export default class GithubLoginView extends React.Component { Log in to GitHub to access PR information and more! , onLogin: token => {}, + tokenStatus: Symbol(), } constructor(props, context) { @@ -57,7 +60,15 @@ export default class GithubLoginView extends React.Component { ); } + renderTokenHint() { + if (this.props.tokenStatus === INSUFFICIENT) { + return(Hint: Entered token has insufficient scopes. Update the scopes on your token and try again. See Dev Tools console for details.); + } + } + renderTokenInput() { + const tokenHint = this.renderTokenHint(); + return (
@@ -73,6 +84,8 @@ export default class GithubLoginView extends React.Component {
  • Enter the token below:
  • + {tokenHint} + +

    Your token no longer has sufficient authorizations. Please re-authenticate and generate a new one.

    From 6e800cb6a56dd30a4a20213bbad75081687495ae Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Wed, 6 Dec 2023 17:41:08 -0500 Subject: [PATCH 5/5] lib: Pre-populate recommended scopes in "new PAT" link --- lib/views/github-login-view.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/views/github-login-view.js b/lib/views/github-login-view.js index cada25da73..bec893e09e 100644 --- a/lib/views/github-login-view.js +++ b/lib/views/github-login-view.js @@ -75,8 +75,10 @@ export default class GithubLoginView extends React.Component {

    Enter Token

    1. - Visit github.com/settings/tokens to generate a new - Personal Access Token (classic).[docs] + Visit + github.com/settings/tokens + to generate a new Personal Access Token (classic). + [docs]
    2. Ensure it has the following permissions: repo, workflow, read:org, and user:email.