使用内置身份验证
获取session
目前,vscode通过内置的身份验证提供程序,为第三方的插件提供身份验证服务。这两个身份验证提供程序分别是:github-authentication和microsoft-authentication。它们为第三方插件提供github和微软的身份验证服务。它们的ID分别为"github"和"microsoft"。用户通过ID访问身份验证提供程序来获得Session,如果没有特殊说明,下面的session都是指AuthenticationSession。
访问方法如下例子:(摘自vscode内置插件github)
export async function getSession(): Promise<AuthenticationSession> {
return await authentication.getSession('github', scopes, { createIfNone: true });
}
它使用getSession方法获得类型为AuthenticationSession的插件对象。它的意思是:在期望的范围(scopes),获取github身份验证提供程序保存的session,如果没有则通过认证创建session。
session中保存的数据,通常是用户身份的信息(id和用户名等)和第三方访问web应用API时所用的token。
获取session时,有三种情况:
- session不存在。
- session可以正常读取。
- session可以正常读取,但是身份令牌失效了(过期)。
为了解决上述的问题,验证机制提供了以下选项。在getSession方法的第三个参数中使用。
在session不存在的时候创建新的session。(通常会通过web浏览器进入用户登录画面)
{ createIfNone: true }
session已经失效,需要重新创建session。{ forceNewSession: true }
身份认证信息变更
身份信息变更,通过用户定义的事件响应通知到用户,使用方法如下例:
vscode.authentication.onDidChangeSessions((e) => {
console.log("认证系统触发了 onDidChangeSessions: 事件" + e.provider.id);
});
上面的具体函数定义和使用方法,请参考:VS Code API | Visual Studio Code Extension API
身份访问受信插件
第三方插件使用身份验证时,由于不受信任,需要在弹出的确认对话框中频繁点击确认。如果想让系统在不弹出确认的情况下,直接开始身份验证,需要把插件id加入到product.json的trustedExtensionAuthAccess集合中。
"trustedExtensionAuthAccess": [
"vscode.git",
"vscode.github",
"ms-vscode.remote-repositories",
"github.remotehub",
"ms-vscode.azure-repos",
"ms-vscode.remote-server",
"github.vscode-pull-request-github",
"github.codespaces",
"ms-vsliveshare.vsliveshare",
"github.copilot"
],
自制身份验证提供程序(authenticProvider)
通过前面的内容,您的插件就可以通过microsoft和github的账号进行授权了,但是,如果您想让您的插件登录到您的系统中,则需要制作身份验证提供程序插件。
身份验证提供程序也是以内置插件的形式存在,通过它,访问服务器的登录页面,在用户输入用户名和密码登录服务器系统后,获得账号的访问信息。然后把它以session的方式存储到vscode的secret存储区中。
注册
身份验证提供程序插件需要把自身注册到系统中。
参考下面的代码(micrsoft-authenticProvider)
context.subscriptions.push(vscode.authentication.registerAuthenticationProvider('microsoft', 'Microsoft', {
onDidChangeSessions: onDidChangeSessions.event,
getSessions: (scopes: string[]) => loginService.getSessions(scopes),
createSession: async (scopes: string[]) => {
try {
/* __GDPR__
"login" : {
"owner": "TylerLeonhardt",
"comment": "Used to determine the usage of the Microsoft Auth Provider.",
"scopes": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight", "comment": "Used to determine what scope combinations are being requested." }
}
*/
telemetryReporter.sendTelemetryEvent('login', {
// Get rid of guids from telemetry.
scopes: JSON.stringify(scopes.map(s => s.replace(/[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}/i, '{guid}'))),
});
const session = await loginService.createSession(scopes.sort());
onDidChangeSessions.fire({ added: [session], removed: [], changed: [] });
return session;
} catch (e) {
/* __GDPR__
"loginFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users run into issues with the login flow." }
*/
telemetryReporter.sendTelemetryEvent('loginFailed');
throw e;
}
},
removeSession: async (id: string) => {
try {
/* __GDPR__
"logout" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users log out." }
*/
telemetryReporter.sendTelemetryEvent('logout');
const session = await loginService.removeSessionById(id);
if (session) {
onDidChangeSessions.fire({ added: [], removed: [session], changed: [] });
}
} catch (e) {
/* __GDPR__
"logoutFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often fail to log out." }
*/
telemetryReporter.sendTelemetryEvent('logoutFailed');
}
}
}, { supportsMultipleAccounts: true }));
registerAuthenticationProvider方法的定义请参考上面提到的API。
认证提供插件需要实现接口IAuthenticationProvider。它的方法会在创建session(登录)和销毁sessin(注销)的时候以及第三方插件申请权限时被调用。在存储的session发生变化的时候,它通过onDidChangeSessions事件,为用户插件提供事件通知。
激活插件
身份认证提供程序插件在vscode启动后并不被直接启动,知道有用户需要的时候才会被启动。
有两种方式,可以启动身份认证提供程序插件。
方法一:通过ActivityBar的账户菜单中,可以启动插件并调用登录程序。
请参考vscode的product.json定义
"configurationSync.store": {
"url": "https://vscode-sync.trafficmanager.net/",
"stableUrl": "https://vscode-sync.trafficmanager.net/",
"insidersUrl": "https://vscode-sync-insiders.trafficmanager.net/",
"canSwitch": false,
"authenticationProviders": {
"github": {
"scopes": [
"user:email"
]
},
"microsoft": {
"scopes": [
"openid",
"profile",
"email",
"offline_access"
]
}
}
},
"editSessions.store": {
"url": "https://vscode-sync.trafficmanager.net/",
"authenticationProviders": {
"microsoft": {
"scopes": [
"openid",
"profile",
"email",
"offline_access"
]
},
"github": {
"scopes": [
"user:email"
]
}
}
},
"tunnelApplicationName": "code-tunnel",
"tunnelApplicationConfig": {
"editorWebUrl": "https://vscode.dev",
"extension": {
"friendlyName": "Remote - Tunnels",
"extensionId": "ms-vscode.remote-server"
},
"authenticationProviders": {
"github": {
"scopes": [
"user:email",
"read:org"
]
}
}
},
方法二:通过用户插件的调用,用户按照正常使用getSession方法,就可以启动插件并调用登录程序。
身份验证过程
因为身份验证需要登录到服务器,而这部分工作是在浏览器中做的,为了把身份数据传递给身份验证提供程序插件,内置的github和microsoft基本都生成了一个临时的web服务器,它负责接收身份信息。收到信息后进行保存。