mirror of
https://github.com/bitwarden/directory-connector
synced 2025-12-05 23:53:21 +00:00
Refresh token with api key (#135)
* Do not persist client creds on logout
* Override refreshing token flow with re-authentication flow
* Update jslib
* PR review comments
(cherry picked from commit 647b087fa7)
This commit is contained in:
2
jslib
2
jslib
Submodule jslib updated: d7682cde3b...78ae9383fb
@@ -21,7 +21,6 @@ import { SyncService } from '../../services/sync.service';
|
||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||
import { ValidationService } from 'jslib-angular/services/validation.service';
|
||||
|
||||
import { ApiService } from 'jslib-common/services/api.service';
|
||||
import { ApiKeyService } from 'jslib-common/services/apiKey.service';
|
||||
import { AppIdService } from 'jslib-common/services/appId.service';
|
||||
import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
@@ -55,6 +54,7 @@ import { StorageService as StorageServiceAbstraction } from 'jslib-common/abstra
|
||||
import { TokenService as TokenServiceAbstraction } from 'jslib-common/abstractions/token.service';
|
||||
import { UserService as UserServiceAbstraction } from 'jslib-common/abstractions/user.service';
|
||||
|
||||
import { ApiService, refreshToken } from '../../services/api.service';
|
||||
import { AuthService } from '../../services/auth.service';
|
||||
|
||||
const logService = new ElectronLogService();
|
||||
@@ -70,7 +70,7 @@ const cryptoService = new CryptoService(storageService, secureStorageService, cr
|
||||
platformUtilsService, logService);
|
||||
const appIdService = new AppIdService(storageService);
|
||||
const tokenService = new TokenService(storageService);
|
||||
const apiService = new ApiService(tokenService, platformUtilsService,
|
||||
const apiService = new ApiService(tokenService, platformUtilsService, refreshTokenCallback,
|
||||
async (expired: boolean) => messagingService.send('logout', { expired: expired }));
|
||||
const environmentService = new EnvironmentService(apiService, storageService, null);
|
||||
const userService = new UserService(tokenService, storageService);
|
||||
@@ -86,6 +86,10 @@ const policyService = new PolicyService(userService, storageService);
|
||||
|
||||
containerService.attachToWindow(window);
|
||||
|
||||
function refreshTokenCallback(): Promise<any> {
|
||||
return refreshToken(apiKeyService, authService);
|
||||
}
|
||||
|
||||
export function initFactory(): Function {
|
||||
return async () => {
|
||||
await environmentService.setUrlsFromStorage();
|
||||
|
||||
@@ -9,6 +9,7 @@ import { ConfigurationService } from './services/configuration.service';
|
||||
import { I18nService } from './services/i18n.service';
|
||||
import { KeytarSecureStorageService } from './services/keytarSecureStorage.service';
|
||||
import { LowdbStorageService } from './services/lowdbStorage.service';
|
||||
import { NodeApiService } from './services/nodeApi.service';
|
||||
import { SyncService } from './services/sync.service';
|
||||
|
||||
import { CliPlatformUtilsService } from 'jslib-node/cli/services/cliPlatformUtils.service';
|
||||
@@ -25,11 +26,11 @@ import { NoopMessagingService } from 'jslib-common/services/noopMessaging.servic
|
||||
import { PasswordGenerationService } from 'jslib-common/services/passwordGeneration.service';
|
||||
import { TokenService } from 'jslib-common/services/token.service';
|
||||
import { UserService } from 'jslib-common/services/user.service';
|
||||
import { NodeApiService } from 'jslib-node/services/nodeApi.service';
|
||||
|
||||
import { StorageService as StorageServiceAbstraction } from 'jslib-common/abstractions/storage.service';
|
||||
|
||||
import { Program } from './program';
|
||||
import { refreshToken } from './services/api.service';
|
||||
|
||||
// tslint:disable-next-line
|
||||
const packageJson = require('./package.json');
|
||||
@@ -90,7 +91,7 @@ export class Main {
|
||||
this.appIdService = new AppIdService(this.storageService);
|
||||
this.tokenService = new TokenService(this.storageService);
|
||||
this.messagingService = new NoopMessagingService();
|
||||
this.apiService = new NodeApiService(this.tokenService, this.platformUtilsService,
|
||||
this.apiService = new NodeApiService(this.tokenService, this.platformUtilsService, this.refreshTokenCallback,
|
||||
async (expired: boolean) => await this.logout());
|
||||
this.environmentService = new EnvironmentService(this.apiService, this.storageService, null);
|
||||
this.apiKeyService = new ApiKeyService(this.tokenService, this.storageService);
|
||||
@@ -117,6 +118,10 @@ export class Main {
|
||||
await this.apiKeyService.clear();
|
||||
}
|
||||
|
||||
refreshTokenCallback() {
|
||||
return refreshToken(this.apiKeyService, this.authService);
|
||||
}
|
||||
|
||||
private async init() {
|
||||
await this.storageService.init();
|
||||
this.containerService.attachToWindow(global);
|
||||
|
||||
@@ -67,7 +67,7 @@ export class Main {
|
||||
this.messagingMain.onMessage(message);
|
||||
});
|
||||
|
||||
this.keytarStorageListener = new KeytarStorageListener('Bitwarden Directory Connector');
|
||||
this.keytarStorageListener = new KeytarStorageListener('Bitwarden Directory Connector', null);
|
||||
}
|
||||
|
||||
bootstrap() {
|
||||
|
||||
30
src/services/api.service.ts
Normal file
30
src/services/api.service.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { ApiKeyService } from 'jslib-common/abstractions/apiKey.service';
|
||||
import { AuthService } from 'jslib-common/abstractions/auth.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { TokenService } from 'jslib-common/abstractions/token.service';
|
||||
|
||||
import { ApiService as ApiServiceBase } from 'jslib-common/services/api.service';
|
||||
|
||||
export async function refreshToken(apiKeyService: ApiKeyService, authService: AuthService) {
|
||||
try {
|
||||
const clientId = await apiKeyService.getClientId();
|
||||
const clientSecret = await apiKeyService.getClientSecret();
|
||||
if (clientId != null && clientSecret != null) {
|
||||
await authService.logInApiKey(clientId, clientSecret);
|
||||
}
|
||||
} catch (e) {
|
||||
return Promise.reject(e);
|
||||
}
|
||||
}
|
||||
|
||||
export class ApiService extends ApiServiceBase {
|
||||
constructor(tokenService: TokenService, platformUtilsService: PlatformUtilsService,
|
||||
private refreshTokenCallback: () => Promise<void>, logoutCallback: (expired: boolean) => Promise<void>,
|
||||
customUserAgent: string = null) {
|
||||
super(tokenService, platformUtilsService, logoutCallback, customUserAgent);
|
||||
}
|
||||
|
||||
doRefreshToken(): Promise<void> {
|
||||
return this.refreshTokenCallback();
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,11 @@ export class AuthService extends AuthServiceBase {
|
||||
return await super.logInApiKey(clientId, clientSecret);
|
||||
}
|
||||
|
||||
async logOut(callback: Function) {
|
||||
this.apiKeyService.clear();
|
||||
super.logOut(callback);
|
||||
}
|
||||
|
||||
private async organizationLogInHelper(clientId: string, clientSecret: string) {
|
||||
const appId = await this.appIdService.getAppId();
|
||||
const deviceRequest = new DeviceRequest(appId, this.platformUtilsService);
|
||||
@@ -49,7 +54,7 @@ export class AuthService extends AuthServiceBase {
|
||||
const tokenResponse = response as IdentityTokenResponse;
|
||||
result.resetMasterPassword = tokenResponse.resetMasterPassword;
|
||||
await this.tokenService.setToken(tokenResponse.accessToken);
|
||||
await this.apiKeyService.setInformation(clientId);
|
||||
await this.apiKeyService.setInformation(clientId, clientSecret);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,10 @@ export class KeytarSecureStorageService implements StorageService {
|
||||
});
|
||||
}
|
||||
|
||||
async has(key: string): Promise<boolean> {
|
||||
return (await this.get(key)) != null;
|
||||
}
|
||||
|
||||
save(key: string, obj: any): Promise<any> {
|
||||
return setPassword(this.serviceName, key, JSON.stringify(obj));
|
||||
}
|
||||
|
||||
16
src/services/nodeApi.service.ts
Normal file
16
src/services/nodeApi.service.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { TokenService } from 'jslib-common/abstractions/token.service';
|
||||
|
||||
import { NodeApiService as NodeApiServiceBase } from 'jslib-node/services/nodeApi.service';
|
||||
|
||||
export class NodeApiService extends NodeApiServiceBase {
|
||||
constructor(tokenService: TokenService, platformUtilsService: PlatformUtilsService,
|
||||
private refreshTokenCallback: () => Promise<void>, logoutCallback: (expired: boolean) => Promise<void>,
|
||||
customUserAgent: string = null) {
|
||||
super(tokenService, platformUtilsService, logoutCallback, customUserAgent);
|
||||
}
|
||||
|
||||
doRefreshToken(): Promise<void> {
|
||||
return this.refreshTokenCallback();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user