Skip to content
Snippets Groups Projects
Commit 50ba15db authored by Christian ZHENG's avatar Christian ZHENG
Browse files

refactor(login): change some attributes and methods names + update logging + update doc + fix typo

parent dd7f8f52
No related branches found
No related tags found
3 merge requests!14feat: added mounted, .bashrc, .zshrc, added tests, added keycloak tests,!8feat(extension): login, open in devcontainer, automaticly save code, open briefing, publish extension,!1fix(view): open new views as tabs + show Getting Started button by default
...@@ -11,7 +11,7 @@ export default class KeycloakOAuth2DeviceFlowConnection { ...@@ -11,7 +11,7 @@ export default class KeycloakOAuth2DeviceFlowConnection {
private waitDuration: WaitDuration; private waitDuration: WaitDuration;
private accessToken: string; private accessToken: string;
private refreshToken: string; private refreshToken: string;
private deviceAuthorizationRequestResponseData: DeviceAuthorizationRequestResponseData; private deviceAuthorizationRequestResponse: DeviceAuthorizationRequestResponse;
constructor(private deviceUrl: string, private tokenUrl: string, private userInfoUrl: string) { constructor(private deviceUrl: string, private tokenUrl: string, private userInfoUrl: string) {
/* /*
...@@ -25,19 +25,15 @@ export default class KeycloakOAuth2DeviceFlowConnection { ...@@ -25,19 +25,15 @@ export default class KeycloakOAuth2DeviceFlowConnection {
this.waitDuration = new WaitDuration([5_000, 5_000, 5_000, 10_000, 10_000, 10_000, 30_000, 30_000, 100_000]); 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.accessToken = '';
this.refreshToken = ''; this.refreshToken = '';
this.deviceAuthorizationRequestResponseData = {}; this.deviceAuthorizationRequestResponse = {};
} }
/** /**
* userInfoUrl must be passed in constructor in order to use this
* @param accessToken * @param accessToken
* @returns Promise * @returns Promise
*/ */
public async tokenIsValid(accessToken: string) { public async tokenIsValid(accessToken: string) {
const url = this.userInfoUrl; const url = this.userInfoUrl;
if (!url) {
return Promise.reject('tokenIsValid: missing user_info API endpoint');
}
if (!accessToken) { if (!accessToken) {
return Promise.resolve(false); return Promise.resolve(false);
} }
...@@ -56,15 +52,16 @@ export default class KeycloakOAuth2DeviceFlowConnection { ...@@ -56,15 +52,16 @@ export default class KeycloakOAuth2DeviceFlowConnection {
return Promise.resolve(true); return Promise.resolve(true);
} }
case HttpStatusCode.BAD_REQUEST: { case HttpStatusCode.BAD_REQUEST: {
const badRequestResponse: FailedAuthenticationReponseData = const badRequestResponse = (await tokenValidationRequestResponse.json()) as FailedAuthenticationResponse;
(await tokenValidationRequestResponse.json()) as FailedAuthenticationReponseData; err(`${badRequestResponse.error!}: ${badRequestResponse.error_description}`);
throw new Error('tokenIsValid: ' + badRequestResponse.error); throw new Error(`${badRequestResponse.error}: ${badRequestResponse.error_description}`);
} }
case HttpStatusCode.UNAUTHORIZED: { case HttpStatusCode.UNAUTHORIZED: {
return Promise.resolve(false); return Promise.resolve(false);
} }
default: { default: {
throw new Error(`tokenIsValid: Unhandled HTTP status: ${tokenValidationRequestResponseCode}`); err(`Unhandled HTTP status: ${tokenValidationRequestResponseCode}`);
throw new Error(`Unhandled HTTP status: ${tokenValidationRequestResponseCode}`);
} }
} }
} }
...@@ -89,13 +86,13 @@ export default class KeycloakOAuth2DeviceFlowConnection { ...@@ -89,13 +86,13 @@ export default class KeycloakOAuth2DeviceFlowConnection {
await this.registerDevice(); await this.registerDevice();
} }
try { try {
openLink(this.deviceAuthorizationRequestResponseData.verification_uri_complete!); openLink(this.deviceAuthorizationRequestResponse.verification_uri_complete!);
await this.createUserAuthentication({ await this.createUserAuthentication({
url: this.tokenUrl, url: this.tokenUrl,
body: (() => { body: (() => {
const params = new URLSearchParams(); const params = new URLSearchParams();
params.append('response_type', 'token'); params.append('response_type', 'token');
params.append('device_code', this.deviceAuthorizationRequestResponseData.device_code ?? ''); params.append('device_code', this.deviceAuthorizationRequestResponse.device_code ?? '');
params.append('grant_type', 'urn:ietf:params:oauth:grant-type:device_code'); params.append('grant_type', 'urn:ietf:params:oauth:grant-type:device_code');
params.append('client_id', 'deadlock-desktop'); params.append('client_id', 'deadlock-desktop');
return params.toString(); return params.toString();
...@@ -108,7 +105,7 @@ export default class KeycloakOAuth2DeviceFlowConnection { ...@@ -108,7 +105,7 @@ export default class KeycloakOAuth2DeviceFlowConnection {
} }
private deviceIsRegistered(): boolean { private deviceIsRegistered(): boolean {
return !!this.deviceAuthorizationRequestResponseData.device_code; return !!this.deviceAuthorizationRequestResponse.device_code;
} }
public async registerDevice() { public async registerDevice() {
...@@ -121,8 +118,8 @@ export default class KeycloakOAuth2DeviceFlowConnection { ...@@ -121,8 +118,8 @@ export default class KeycloakOAuth2DeviceFlowConnection {
return params.toString(); return params.toString();
})(), })(),
}); });
this.deviceAuthorizationRequestResponseData = this.deviceAuthorizationRequestResponse =
(await deviceAuthorizationRequestResponse.json()) as DeviceAuthorizationRequestResponseData; (await deviceAuthorizationRequestResponse.json()) as DeviceAuthorizationRequestResponse;
} }
private async createDeviceAuthorization(args: { url: string; body: string }): Promise<Response> { private async createDeviceAuthorization(args: { url: string; body: string }): Promise<Response> {
...@@ -141,7 +138,7 @@ export default class KeycloakOAuth2DeviceFlowConnection { ...@@ -141,7 +138,7 @@ export default class KeycloakOAuth2DeviceFlowConnection {
/** /**
* *
* @param args API URL endpoint to ask for a new token & request form parameters * @param args API URL endpoint to ask for a new token & request form parameters
* @throw Error containing Keycloak API error_code * @throw Error containing Keycloak API `error_code`
*/ */
private async createUserAuthentication(args: { url: string; body: string }) { private async createUserAuthentication(args: { url: string; body: string }) {
const { url, body } = args; const { url, body } = args;
...@@ -159,7 +156,7 @@ export default class KeycloakOAuth2DeviceFlowConnection { ...@@ -159,7 +156,7 @@ export default class KeycloakOAuth2DeviceFlowConnection {
userAuthenticationRequestResponseCode = userAuthenticationRequestResponse.status; userAuthenticationRequestResponseCode = userAuthenticationRequestResponse.status;
switch (userAuthenticationRequestResponseCode) { switch (userAuthenticationRequestResponseCode) {
case HttpStatusCode.BAD_REQUEST: { case HttpStatusCode.BAD_REQUEST: {
await this.onUserAuthenticationFailure(userAuthenticationRequestResponse); await this.onUserAuthenticationBadRequest(userAuthenticationRequestResponse);
break; break;
} }
...@@ -169,14 +166,15 @@ export default class KeycloakOAuth2DeviceFlowConnection { ...@@ -169,14 +166,15 @@ export default class KeycloakOAuth2DeviceFlowConnection {
} }
default: { default: {
throw new Error(`tokenIsValid: Unhandled HTTP status: ${userAuthenticationRequestResponseCode}`); err(`Unhandled HTTP status: ${userAuthenticationRequestResponseCode}`);
throw new Error(`Unhandled HTTP status: ${userAuthenticationRequestResponseCode}`);
} }
} }
} }
} }
private async onUserAuthenticationFailure(userAuthenticationRequestResponse: Response) { private async onUserAuthenticationBadRequest(userAuthenticationRequestResponse: Response) {
const badRequestResponse = (await userAuthenticationRequestResponse.json()) as FailedAuthenticationReponseData; const badRequestResponse = (await userAuthenticationRequestResponse.json()) as FailedAuthenticationResponse;
const errorCode = TokenFetchErrorCode[badRequestResponse.error!]; const errorCode = TokenFetchErrorCode[badRequestResponse.error!];
switch (errorCode) { switch (errorCode) {
case TokenFetchErrorCode.invalid_client: case TokenFetchErrorCode.invalid_client:
...@@ -195,14 +193,16 @@ export default class KeycloakOAuth2DeviceFlowConnection { ...@@ -195,14 +193,16 @@ export default class KeycloakOAuth2DeviceFlowConnection {
break; break;
} }
default: { default: {
throw new Error(`createUserAuthentication: Unhandled error code [ ${badRequestResponse.error} ]`); err(`${badRequestResponse.error!}: ${badRequestResponse.error_description}`);
throw new Error(
`Unhandled error code [ ${badRequestResponse.error!}: ${badRequestResponse.error_description} ]`,
);
} }
} }
} }
private async onUserAuthenticationSuccess(userAuthenticationRequestResponse: Response) { private async onUserAuthenticationSuccess(userAuthenticationRequestResponse: Response) {
const successRequestResponse = const successRequestResponse = (await userAuthenticationRequestResponse.json()) as SuccessfulAuthenticationResponse;
(await userAuthenticationRequestResponse.json()) as SuccessfulAuthenticationResponseData;
this.accessToken = successRequestResponse.access_token ?? ''; this.accessToken = successRequestResponse.access_token ?? '';
this.refreshToken = successRequestResponse.refresh_token ?? ''; this.refreshToken = successRequestResponse.refresh_token ?? '';
} }
...@@ -212,7 +212,7 @@ export default class KeycloakOAuth2DeviceFlowConnection { ...@@ -212,7 +212,7 @@ export default class KeycloakOAuth2DeviceFlowConnection {
* KEEP the SAME case \ * KEEP the SAME case \
* to respect keycloak API return * to respect keycloak API return
*/ */
interface DeviceAuthorizationRequestResponseData { interface DeviceAuthorizationRequestResponse {
device_code?: string; device_code?: string;
user_code?: string; user_code?: string;
verification_uri?: string; verification_uri?: string;
...@@ -225,7 +225,7 @@ interface DeviceAuthorizationRequestResponseData { ...@@ -225,7 +225,7 @@ interface DeviceAuthorizationRequestResponseData {
* KEEP the SAME case \ * KEEP the SAME case \
* to respect keycloak API return * to respect keycloak API return
*/ */
interface SuccessfulAuthenticationResponseData { interface SuccessfulAuthenticationResponse {
access_token?: string; access_token?: string;
expires_in?: number; expires_in?: number;
'not-before-policy'?: number; 'not-before-policy'?: number;
...@@ -236,7 +236,7 @@ interface SuccessfulAuthenticationResponseData { ...@@ -236,7 +236,7 @@ interface SuccessfulAuthenticationResponseData {
token_type?: 'Bearer' | string; token_type?: 'Bearer' | string;
} }
interface FailedAuthenticationReponseData { interface FailedAuthenticationResponse {
error?: string; error?: string;
error_description?: string; error_description?: string;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment