-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathopenIDConnect.ts
118 lines (103 loc) · 3.12 KB
/
openIDConnect.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { fail } from 'k6';
import http from 'k6/http';
import { get } from 'lodash';
import { objectToQueryString, queryStringToObject } from '../utils';
import { Account, Token } from './auth';
export class OpenIDConnect {
#account: Account;
#baseURL: string;
#redirectURL: string;
#logonURL: string;
#tokenURL: string;
#cache?: {
validTo: Date;
token: Token;
};
constructor(account: Account, baseURL: string) {
this.#account = account;
this.#baseURL = baseURL;
this.#redirectURL = `${baseURL}/oidc-callback.html`;
this.#logonURL = `${baseURL}/signin/v1/identifier/_/logon`;
this.#tokenURL = `${baseURL}/konnect/v1/token`;
}
public get credential(): Token {
if (!this.#cache || this.#cache.validTo <= new Date()) {
const continueURI = this.getContinueURI();
const code = this.getCode(continueURI);
const token = this.getToken(code);
this.#cache = {
validTo: ((): Date => {
const offset = 5;
const d = new Date();
d.setSeconds(d.getSeconds() + token.expiresIn - offset);
return d;
})(),
token,
};
}
return this.#cache.token;
}
private getContinueURI(): string {
const logonResponse = http.post(
this.#logonURL,
JSON.stringify({
params: [this.#account.login, this.#account.password, '1'],
hello: {
scope: 'openid profile email',
client_id: 'web',
redirect_uri: this.#redirectURL,
flow: 'oidc',
},
state: '22db4af49efce268',
}),
{
headers: {
'Kopano-Konnect-XSRF': '1',
Referer: this.#baseURL,
'Content-Type': 'application/json',
},
},
);
const continueURI = get(logonResponse.json(), 'hello.continue_uri');
if (logonResponse.status !== 200 || !continueURI) {
fail(this.#logonURL);
}
return continueURI;
}
private getCode(continueURI: string): string {
const authorizeUri = `${continueURI}?${objectToQueryString({
client_id: 'web',
prompt: 'none',
redirect_uri: this.#redirectURL,
response_mode: 'query',
response_type: 'code',
scope: 'openid profile email',
})}`;
const authorizeResponse = http.get(authorizeUri, {
redirects: 0,
});
const code = get(queryStringToObject(authorizeResponse.headers.Location), 'code');
if (authorizeResponse.status !== 302 || !code) {
fail(continueURI);
}
return code;
}
private getToken(code: string): Token {
const tokenResponse = http.post(this.#tokenURL, {
client_id: 'web',
code,
redirect_uri: this.#redirectURL,
grant_type: 'authorization_code',
});
const token = {
accessToken: get(tokenResponse.json(), 'access_token'),
tokenType: get(tokenResponse.json(), 'token_type'),
idToken: get(tokenResponse.json(), 'id_token'),
expiresIn: get(tokenResponse.json(), 'expires_in'),
};
if (tokenResponse.status !== 200 || !token.accessToken || !token.tokenType || !token.idToken || !token.expiresIn) {
fail(this.#tokenURL);
}
return token;
}
}