diff --git a/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.ts b/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.ts index 8d3406ad41edc8f0cbc9ab29da01806318fa9e99..d985267cc6f5230281d4520a9ab4d7c6a03ece10 100644 --- a/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.ts +++ b/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.ts @@ -6,52 +6,79 @@ import { TokenFetchErrorCode } from '../typings/KeycloakAPITypes'; process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; // TODO: remove when SSL will work -export default class OAuth2DeviceFlowConnection { +export default class KeycloakOAuth2DeviceFlowConnection { private _waitDuration: WaitDuration; private _accessToken: string; private _refreshToken: string; private _deviceAuthorizationRequestResponseData: DeviceAuthorizationRequestResponseData; - constructor() { + constructor(private _deviceUrl: string, private _tokenUrl: string) { this._waitDuration = new WaitDuration([5_000, 5_000, 5_000, 10_000, 10_000, 10_000, 30_000, 30_000, 100_000]); this._accessToken = ''; this._refreshToken = ''; this._deviceAuthorizationRequestResponseData = {}; } - public async start() { - const deviceAuthorizationRequestResponse: Response = await this.createDeviceAuthorization({ - url: 'https://auth.dev.deadlock.io/auth/realms/Deadlock/protocol/openid-connect/auth/device', - body: (() => { - const params = new URLSearchParams(); - params.append('client_id', 'deadlock-desktop'); - return params.toString(); - })(), - }); - this._deviceAuthorizationRequestResponseData = - (await deviceAuthorizationRequestResponse.json()) as DeviceAuthorizationRequestResponseData; - console.log(this._deviceAuthorizationRequestResponseData); + public async getToken(args: { refreshToken?: string; openLink: (link: string) => void }) { + const { refreshToken, openLink } = args; + if (refreshToken) { + await this.createUserAuthentication({ + url: this._tokenUrl, + body: (() => { + const params = new URLSearchParams(); + params.append('response_type', 'token'); + params.append('client_id', 'deadlock-desktop'); + params.append('grant_type', 'refresh_token'); + params.append('refresh_token', refreshToken); + return params.toString(); + })(), + }); + return Promise.resolve({ accessToken: this._accessToken, refreshToken: this._refreshToken }); + } + if (!this._deviceIsRegistered()) { + console.log('--- device not registered'); + await this._registerDevice(); + } try { + openLink(this._deviceAuthorizationRequestResponseData.verification_uri_complete!); await this.createUserAuthentication({ - url: 'https://auth.dev.deadlock.io/auth/realms/Deadlock/protocol/openid-connect/token', + url: this._tokenUrl, body: (() => { const params = new URLSearchParams(); params.append('response_type', 'token'); params.append('device_code', this._deviceAuthorizationRequestResponseData.device_code ?? ''); params.append('grant_type', 'urn:ietf:params:oauth:grant-type:device_code'); params.append('client_id', 'deadlock-desktop'); - console.log('token query body: ', params.toString()); return params.toString(); })(), }); console.log('access token: ', this._accessToken); console.log('refresh token: ', this._refreshToken); + Promise.resolve({ accessToken: this._accessToken, refreshToken: this._refreshToken }); } catch (error: any) { err(error); - return; + Promise.reject(error); } } + private _deviceIsRegistered(): boolean { + return !!this._deviceAuthorizationRequestResponseData.device_code; + } + + private async _registerDevice() { + const deviceAuthorizationRequestResponse: Response = await this.createDeviceAuthorization({ + url: this._deviceUrl, + body: (() => { + const params = new URLSearchParams(); + params.append('client_id', 'deadlock-desktop'); + return params.toString(); + })(), + }); + this._deviceAuthorizationRequestResponseData = + (await deviceAuthorizationRequestResponse.json()) as DeviceAuthorizationRequestResponseData; + console.log('DeviceAuthorizationRequestResponseData', this._deviceAuthorizationRequestResponseData); + } + private async createDeviceAuthorization(args: { url: string; body: string }): Promise<Response> { const { url, body } = args; return fetch(url, { @@ -128,15 +155,23 @@ export default class OAuth2DeviceFlowConnection { } } +/** + * KEEP the SAME case \ + * to respect keycloak API return + */ export interface DeviceAuthorizationRequestResponseData { device_code?: string; user_code?: string; - verificationURI?: string; - verificationURIComplete?: string; - expiresIn?: number; + verification_uri?: string; + verification_uri_complete?: string; + expires_in?: number; interval?: number; } +/** + * KEEP the SAME case \ + * to respect keycloak API return + */ export interface SuccessfulAuthenticationResponseData { access_token?: string; expires_in?: number; @@ -155,7 +190,7 @@ export interface FailedAuthenticationReponseData { export type AuthenticationResponse = SuccessfulAuthenticationResponseData | FailedAuthenticationReponseData; -function sleep(ms) { +function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); }