Follow up 944: authentication sessions are not persistent (#1003)

* #944: Fixed auth. sessions not persistent

* 944: Prevent race conditions setting authOptions

* typo correction, duplicate identifier

* prevent block of auth client service on setOptions

* consider windows cred. mgr. password len limit
This commit is contained in:
David Simpson 2022-06-07 11:46:28 +02:00 committed by GitHub
parent a59e0da2af
commit eaf14aa1eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 28 additions and 12 deletions

View File

@ -43,15 +43,14 @@ export class AuthenticationClientService
readonly onSessionDidChange = this.onSessionDidChangeEmitter.event; readonly onSessionDidChange = this.onSessionDidChangeEmitter.event;
onStart(): void { async onStart(): Promise<void> {
this.toDispose.push(this.onSessionDidChangeEmitter); this.toDispose.push(this.onSessionDidChangeEmitter);
this.service.setClient(this); this.service.setClient(this);
this.service this.service
.session() .session()
.then((session) => this.notifySessionDidChange(session)); .then((session) => this.notifySessionDidChange(session));
this.setOptions(); this.setOptions().then(() => this.service.initAuthSession());
this.service.initAuthSession()
this.arduinoPreferences.onPreferenceChanged((event) => { this.arduinoPreferences.onPreferenceChanged((event) => {
if (event.preferenceName.startsWith('arduino.auth.')) { if (event.preferenceName.startsWith('arduino.auth.')) {
@ -60,8 +59,8 @@ export class AuthenticationClientService
}); });
} }
setOptions(): void { setOptions(): Promise<void> {
this.service.setOptions({ return this.service.setOptions({
redirectUri: `http://localhost:${serverPort}/callback`, redirectUri: `http://localhost:${serverPort}/callback`,
responseType: 'code', responseType: 'code',
clientID: this.arduinoPreferences['arduino.auth.clientID'], clientID: this.arduinoPreferences['arduino.auth.clientID'],

View File

@ -22,7 +22,7 @@ export interface AuthenticationService
logout(): Promise<void>; logout(): Promise<void>;
session(): Promise<AuthenticationSession | undefined>; session(): Promise<AuthenticationSession | undefined>;
disposeClient(client: AuthenticationServiceClient): void; disposeClient(client: AuthenticationServiceClient): void;
setOptions(authOptions: AuthOptions): void; setOptions(authOptions: AuthOptions): Promise<void>;
initAuthSession(): Promise<void>; initAuthSession(): Promise<void>;
} }

View File

@ -89,7 +89,7 @@ export class ArduinoAuthenticationProvider implements AuthenticationProvider {
setInterval(checkToken, REFRESH_INTERVAL); setInterval(checkToken, REFRESH_INTERVAL);
} }
public setOptions(authOptions: AuthOptions) { public async setOptions(authOptions: AuthOptions): Promise<void> {
this.authOptions = authOptions; this.authOptions = authOptions;
} }

View File

@ -20,7 +20,7 @@ export class AuthenticationServiceImpl
protected readonly clients: AuthenticationServiceClient[] = []; protected readonly clients: AuthenticationServiceClient[] = [];
protected readonly toDispose = new DisposableCollection(); protected readonly toDispose = new DisposableCollection();
private initialized = false; private initialized = false;
async onStart(): Promise<void> { async onStart(): Promise<void> {
this.toDispose.pushAll([ this.toDispose.pushAll([
@ -49,12 +49,12 @@ export class AuthenticationServiceImpl
async initAuthSession(): Promise<void> { async initAuthSession(): Promise<void> {
if (!this.initialized) { if (!this.initialized) {
await this.delegate.init(); await this.delegate.init();
this.initialized = true this.initialized = true;
} }
} }
setOptions(authOptions: AuthOptions) { setOptions(authOptions: AuthOptions): Promise<void> {
this.delegate.setOptions(authOptions); return this.delegate.setOptions(authOptions);
} }
async login(): Promise<AuthenticationSession> { async login(): Promise<AuthenticationSession> {

View File

@ -47,6 +47,15 @@ export class Keychain {
return false; return false;
} }
try { try {
const stringifiedTokenLength = stringifiedToken.length;
const tokenLengthNotSupported =
stringifiedTokenLength > 2500 && process.platform === 'win32';
if (tokenLengthNotSupported) {
// TODO manage this specific error appropriately
return false;
}
await keytar.setPassword( await keytar.setPassword(
this.credentialsSection, this.credentialsSection,
this.account, this.account,

View File

@ -44,7 +44,15 @@ export function token2IToken(token: Token): IToken {
(token.id_token && jwt_decode(token.id_token)) || {}; (token.id_token && jwt_decode(token.id_token)) || {};
return { return {
idToken: token.id_token, /*
* ".id_token" is already decoded for account details above
* so we probably don't need to keep it around as "idToken".
* If we do, and subsequently try to store it with
* Windows Credential Manager (WCM) it's probable we'll
* exceed WCMs' 2500 password character limit breaking
* our auth functionality
*/
// ! idToken: token.id_token,
expiresIn: token.expires_in, expiresIn: token.expires_in,
expiresAt: token.expires_in expiresAt: token.expires_in
? Date.now() + token.expires_in * 1000 ? Date.now() + token.expires_in * 1000