-
Notifications
You must be signed in to change notification settings - Fork 41.9k
Enable Microsoft Entra ID sign-in for Private Marketplace access #325331
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
base: main
Are you sure you want to change the base?
Changes from 40 commits
d97c8a8
6f54fb9
ab9e525
3481985
94a70a7
bd44656
eec93cb
6434607
ca0d56f
5510595
2f7a8f9
6ec632f
3aa3035
988ffeb
c0306bc
5ec451b
0b48532
b5aaf89
3789654
0630e80
322b2e3
67955a3
84ff6e0
fc4e4a0
117928b
d2626c5
af73002
c67ffce
cec950d
bbfd837
7c18968
72ec505
8da36d1
082b6c7
61ac56e
7250434
fa1f726
c41e451
e61ce45
bdf2d21
a65242b
3973ede
cdf706a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,10 @@ | |
|
|
||
| import { Event } from '../../../base/common/event.js'; | ||
| import { createDecorator } from '../../instantiation/common/instantiation.js'; | ||
| import { RawContextKey } from '../../contextkey/common/contextkey.js'; | ||
|
|
||
| /** The effective Marketplace auth provider, for `when`-clause driven welcome content. */ | ||
| export const CONTEXT_MARKETPLACE_AUTH_PROVIDER = new RawContextKey<string>('marketplaceAuthProvider', ''); | ||
|
|
||
| export const enum ExtensionGalleryResourceType { | ||
| ExtensionQueryService = 'ExtensionQueryService', | ||
|
|
@@ -98,3 +102,14 @@ export function getExtensionGalleryManifestResourceUri(manifest: IExtensionGalle | |
| } | ||
|
|
||
| export const ExtensionGalleryServiceUrlConfigKey = 'extensions.gallery.serviceUrl'; | ||
|
|
||
| export const ExtensionGalleryAuthProviderConfigKey = 'extensions.gallery.authProvider'; | ||
|
|
||
| /** Standard OpenID Connect scopes — enough to identify the user for the eligibility check. */ | ||
| export const PRIVATE_MARKETPLACE_SCOPES: string[] = ['openid', 'profile', 'email', 'offline_access']; | ||
|
|
||
| /** | ||
| * Interactive Microsoft sign-in, registered in the Electron layer and invoked by id from the | ||
| * browser-layer action so it need not cross the layer boundary. | ||
| */ | ||
| export const ExtensionGalleryMicrosoftSignInCommandId = 'workbench.extensions.marketplace.signInWithMicrosoft'; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. THere should be just one command for sign in and account service should handle signing in to microsoft or github
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in 3973ede. await accessor.get(IExtensionGalleryAccountService).signIn();GitHub's 🤖 This reply was drafted by an AI agent on behalf of Michael Cummings (MSFT) (@mcumming). |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,9 +67,8 @@ import { createActionViewItem } from '../../../../platform/actions/browser/menuE | |
| import { SeverityIcon } from '../../../../base/browser/ui/severityIcon/severityIcon.js'; | ||
| import { StandardKeyboardEvent } from '../../../../base/browser/keyboardEvent.js'; | ||
| import { KeyCode } from '../../../../base/common/keyCodes.js'; | ||
| import { IExtensionGalleryManifest, IExtensionGalleryManifestService, ExtensionGalleryManifestStatus } from '../../../../platform/extensionManagement/common/extensionGalleryManifest.js'; | ||
| import { IExtensionGalleryManifest, IExtensionGalleryManifestService, ExtensionGalleryManifestStatus, CONTEXT_MARKETPLACE_AUTH_PROVIDER } from '../../../../platform/extensionManagement/common/extensionGalleryManifest.js'; | ||
| import { URI } from '../../../../base/common/uri.js'; | ||
| import { DEFAULT_ACCOUNT_SIGN_IN_COMMAND } from '../../../services/accounts/browser/defaultAccount.js'; | ||
|
|
||
| export const ExtensionsSortByContext = new RawContextKey<string>('extensionsSortByValue', ''); | ||
| export const SearchMarketplaceExtensionsContext = new RawContextKey<boolean>('searchMarketplaceExtensions', false); | ||
|
|
@@ -146,7 +145,10 @@ export class ExtensionsViewletViewsContribution extends Disposable implements IW | |
| ContextKeyExpr.or( | ||
| ContextKeyExpr.has('searchMarketplaceExtensions'), ContextKeyExpr.and(DefaultViewsContext) | ||
| ), | ||
| ContextKeyExpr.or(CONTEXT_EXTENSIONS_GALLERY_STATUS.isEqualTo(ExtensionGalleryManifestStatus.RequiresSignIn), CONTEXT_EXTENSIONS_GALLERY_STATUS.isEqualTo(ExtensionGalleryManifestStatus.AccessDenied)) | ||
| ContextKeyExpr.or( | ||
| CONTEXT_EXTENSIONS_GALLERY_STATUS.isEqualTo(ExtensionGalleryManifestStatus.RequiresSignIn), | ||
| CONTEXT_EXTENSIONS_GALLERY_STATUS.isEqualTo(ExtensionGalleryManifestStatus.AccessDenied) | ||
| ) | ||
| ), | ||
| order: -1, | ||
| }); | ||
|
|
@@ -155,10 +157,25 @@ export class ExtensionsViewletViewsContribution extends Disposable implements IW | |
| viewRegistry.registerViews(viewDescriptors, this.container); | ||
|
|
||
| viewRegistry.registerViewWelcomeContent('workbench.views.extensions.marketplaceAccess', { | ||
| content: localize('sign in', "[Sign in to access Extensions Marketplace]({0})", `command:${DEFAULT_ACCOUNT_SIGN_IN_COMMAND}`), | ||
| when: CONTEXT_EXTENSIONS_GALLERY_STATUS.isEqualTo(ExtensionGalleryManifestStatus.RequiresSignIn) | ||
| content: localize('sign in microsoft', "[Sign in with your Microsoft account]({0}) to access the Extensions Marketplace.", `command:workbench.extensions.actions.gallery.signIn`), | ||
| when: ContextKeyExpr.and( | ||
| CONTEXT_EXTENSIONS_GALLERY_STATUS.isEqualTo(ExtensionGalleryManifestStatus.RequiresSignIn), | ||
| CONTEXT_MARKETPLACE_AUTH_PROVIDER.isEqualTo('microsoft') | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid hardcoding provider ids. They should be read only at one place which should be gallery accout service. The sign in button should just say Sign In - why does user has to know if it is github or microsoft if they have to sign in anyway - the sign in page anyway shows right
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in 3973ede — back to a single status-gated welcome entry, same shape as You were right that the fork bought nothing: both blocks already invoked the same command and differed only in the label. Collapsing them left 🤖 This reply was drafted by an AI agent on behalf of Michael Cummings (MSFT) (@mcumming). |
||
| ) | ||
| }); | ||
|
|
||
| viewRegistry.registerViewWelcomeContent('workbench.views.extensions.marketplaceAccess', { | ||
| content: localize('sign in github', "[Sign in with GitHub]({0}) to access the Extensions Marketplace.", `command:workbench.extensions.actions.gallery.signIn`), | ||
| when: ContextKeyExpr.and( | ||
| CONTEXT_EXTENSIONS_GALLERY_STATUS.isEqualTo(ExtensionGalleryManifestStatus.RequiresSignIn), | ||
| ContextKeyExpr.or( | ||
| CONTEXT_MARKETPLACE_AUTH_PROVIDER.isEqualTo('github'), | ||
| ContextKeyExpr.not('marketplaceAuthProvider') | ||
| ) | ||
| ) | ||
| }); | ||
|
|
||
| // Access denied applies to every provider (microsoft/github/default), so gate on status alone. | ||
| viewRegistry.registerViewWelcomeContent('workbench.views.extensions.marketplaceAccess', { | ||
| content: localize('access denied', "Your account does not have access to the Extensions Marketplace. Please contact your administrator."), | ||
| when: CONTEXT_EXTENSIONS_GALLERY_STATUS.isEqualTo(ExtensionGalleryManifestStatus.AccessDenied) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this scopes to product.json just like scopes for github
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in a65242b —
extensionsGallery.accessScopes, next toaccessSKUs.Followed
defaultChatAgent.providerScopesexactly: no in-source fallback, so the product file is the only source. If a deployment turns on the Microsoft path without configuring scopes it now reports no account, rather than requesting a session it can't use.These are plain OIDC scopes — we take the auth provider's default client id and
organizationstenant, so noVSCODE_*overrides are involved. That's all the eligibility check needs: an ID token carrying atidclaim.One asymmetry worth naming:
providerScopesis required in the type,accessScopescan't be —extensionsGalleryis itself optional, and requiring it would force scopes on GitHub-path deployments where they're meaningless. The fail-closed check covers that gap.🤖 This reply was drafted by an AI agent on behalf of Michael Cummings (MSFT) (@mcumming).