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

feat(login): add token verifier

parent 1cfd4bac
No related branches found
No related tags found
2 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
......@@ -15,6 +15,7 @@ export default class KeycloakOAuth2DeviceFlowConnectionTest {
this.connection = new KeycloakOAuth2DeviceFlowConnection(
'https://auth.dev.deadlock.io/auth/realms/Deadlock/protocol/openid-connect/auth/device',
'https://auth.dev.deadlock.io/auth/realms/Deadlock/protocol/openid-connect/token',
'https://auth.dev.deadlock.io/auth/realms/Deadlock/protocol/openid-connect/userinfo',
);
}
......@@ -38,5 +39,20 @@ export default class KeycloakOAuth2DeviceFlowConnectionTest {
openLink: openLinkPlaceholder,
});
console.log('refreshed tokens', refreshedTokens);
try {
console.log(`'12345' is a valid token ? ${await this.connection.tokenIsValid('12345')};`);
console.log(`'' is a valid token ? ${await this.connection.tokenIsValid('')};`);
console.log(
`${tokens.accessToken} is a valid token ? ${await this.connection.tokenIsValid(tokens.accessToken)};`,
);
console.log(
`${refreshedTokens.accessToken} is a valid token ? ${await this.connection.tokenIsValid(
refreshedTokens.accessToken,
)};`,
);
} catch (error: unknown) {
console.error(error);
}
}
}
......@@ -12,13 +12,54 @@ export default class KeycloakOAuth2DeviceFlowConnection {
private _refreshToken: string;
private _deviceAuthorizationRequestResponseData: DeviceAuthorizationRequestResponseData;
constructor(private _deviceUrl: string, private _tokenUrl: string) {
constructor(private _deviceUrl: string, private _tokenUrl: string, private _userInfoUrl?: 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 = {};
}
/**
* _userInfoUrl must be passed in constructor in order to use this
* @param accessToken
* @returns Promise
*/
public async tokenIsValid(accessToken: string) {
const url = this._userInfoUrl;
if (!url) {
return Promise.reject('tokenIsValid: missing user_info API endpoint');
}
if (!accessToken) {
return Promise.resolve(false);
}
const tokenValidationRequestResponse: Response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: `Bearer ${accessToken}`,
},
body: '',
agent: new https.Agent({ rejectUnauthorized: false }), // TODO: remove when SSL will work
});
const tokenValidationRequestResponseCode = tokenValidationRequestResponse.status;
switch (tokenValidationRequestResponseCode) {
case HttpStatusCode.OK: {
return Promise.resolve(true);
}
case HttpStatusCode.BAD_REQUEST: {
const badRequestResponse: FailedAuthenticationReponseData =
(await tokenValidationRequestResponse.json()) as FailedAuthenticationReponseData;
throw new Error('tokenIsValid: ' + badRequestResponse.error);
}
case HttpStatusCode.UNAUTHORIZED: {
return Promise.resolve(false);
}
default: {
throw new Error(`tokenIsValid: Unhandled HTTP status: ${tokenValidationRequestResponseCode}`);
}
}
}
public async getToken(args: { refreshToken?: string; openLink: (link: string) => void }) {
const { refreshToken, openLink } = args;
if (!!refreshToken) {
......@@ -145,7 +186,7 @@ export default class KeycloakOAuth2DeviceFlowConnection {
break;
}
default: {
break;
throw new Error(`tokenIsValid: Unhandled HTTP status: ${userAuthenticationRequestResponseCode}`);
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment