@dev-crew-berlin/enter-js-utils 0.45.1 → 0.45.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,20 +25,29 @@ typed js client for the enter api.
25
25
  ```typescript
26
26
  import EnterAPIClient from '@dev-crew-berlin/enter-js-utils/api-client'
27
27
 
28
- const url = 'https://api.enter.events'
29
28
 
30
29
  async function apiExample() {
31
30
  // fetch access Token
32
- const accessToken = await EnterAPIClient.fetchAccessToken({
33
- url: url,
34
- user: 'me',
35
- password: 'xxx',
36
- deviceName: 'my-device',
31
+ const accessTokenResult = await EnterAPIClient.fetchAccessToken({
32
+ oidc: {
33
+ url: 'https://auth.enter.events',
34
+ projectId: '246359835166114187'
35
+ }
36
+ user: {
37
+ userId: '',
38
+ keyId: '',
39
+ key: ''
40
+ }
37
41
  })
42
+ if (!accessTokenResult.success) {
43
+ throw new Error(accessTokenResult.error)
44
+ }
45
+
46
+ const accessToken = accessTokenResult.data.accessToken
38
47
 
39
48
  // create api instance
40
49
  const api = new EnterAPIClient({
41
- credentials: { accessToken, url },
50
+ credentials: { accessToken, url: 'https://api.enter.events' },
42
51
  onLogout: (reason?: string) => {
43
52
  deleteCredetials()
44
53
  },
@@ -1,4 +1,4 @@
1
- import { APIResult } from '../lib';
1
+ import { APIResult, Result } from '../lib';
2
2
  import { paths } from '../generated/api-schema';
3
3
  export interface APICredentials {
4
4
  accessToken: string;
@@ -30,6 +30,20 @@ export default class APIBase {
30
30
  onLogout: (reason?: string) => void;
31
31
  });
32
32
  private static fetchResult;
33
+ static fetchAccessToken(args: {
34
+ oidc: {
35
+ url: string;
36
+ projectId: string;
37
+ };
38
+ user: {
39
+ userId: string;
40
+ keyId: string;
41
+ key: string;
42
+ };
43
+ }): Promise<Result<string, {
44
+ accessToken: string;
45
+ expires: Date;
46
+ }>>;
33
47
  private fetchFromEnter;
34
48
  protected get<Path extends keyof paths>(endpoint: Path): Promise<APIResult<ResponseType<Path, 'get'>>>;
35
49
  protected post<Path extends keyof paths>(endpoint: Path, data: RequestBody<Path, 'post'>): Promise<APIResult<ResponseType<Path, 'post'>>>;
@@ -1,3 +1,4 @@
1
+ import jws from 'jws';
1
2
  import { failure, success } from '../lib';
2
3
  export default class APIBase {
3
4
  constructor(args) {
@@ -15,6 +16,58 @@ export default class APIBase {
15
16
  return failure(e);
16
17
  }
17
18
  }
19
+ static async fetchAccessToken(args) {
20
+ // see https://zitadel.com/docs/guides/integrate/private-key-jwt to learn about this flow
21
+ const {
22
+ oidc,
23
+ user
24
+ } = args;
25
+ const timestampNow = new Date().getTime() / 1000;
26
+ const assertionToken = jws.sign({
27
+ header: {
28
+ alg: 'RS256',
29
+ kid: user.keyId
30
+ },
31
+ payload: {
32
+ iss: user.userId,
33
+ sub: user.userId,
34
+ aud: oidc.url,
35
+ iat: timestampNow,
36
+ exp: timestampNow + 60 * 5
37
+ },
38
+ privateKey: user.key
39
+ });
40
+ const scopes = ['openid', 'profile', `urn:zitadel:iam:org:project:id:${oidc.projectId}:aud`];
41
+ try {
42
+ const res = await fetch(`${oidc.url}/oauth/v2/token`, {
43
+ method: 'POST',
44
+ headers: {
45
+ 'Content-Type': 'application/x-www-form-urlencoded'
46
+ },
47
+ body: new URLSearchParams({
48
+ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
49
+ scope: scopes.join(' '),
50
+ assertion: assertionToken
51
+ })
52
+ });
53
+ if (res.status >= 300) {
54
+ try {
55
+ const error = await res.json();
56
+ return failure(error.toString());
57
+ } catch {
58
+ return failure(res.statusText);
59
+ }
60
+ }
61
+ const token = await res.json();
62
+ const expireTimestamp = new Date().getTime() + token.expires_in * 1000;
63
+ return success({
64
+ accessToken: token.access_token,
65
+ expires: new Date(expireTimestamp)
66
+ });
67
+ } catch (error) {
68
+ return failure(`${error}`);
69
+ }
70
+ }
18
71
  async fetchFromEnter(endpoint, method, data) {
19
72
  const body = data !== null ? JSON.stringify(data) : null;
20
73
  const headers = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev-crew-berlin/enter-js-utils",
3
- "version": "0.45.1",
3
+ "version": "0.45.2",
4
4
  "description": "utils such as vaildation and other helpers to work with data from the enter app",
5
5
  "files": [
6
6
  "dist",
@@ -52,6 +52,7 @@
52
52
  "@storybook/manager-webpack4": "^6.5.15",
53
53
  "@storybook/react": "^6.5.15",
54
54
  "@storybook/testing-library": "^0.0.13",
55
+ "@types/jws": "^3.2.9",
55
56
  "@types/node": "^17.0.38",
56
57
  "@types/react": "^18.0.10",
57
58
  "@types/react-dom": "^18.0.5",
@@ -72,6 +73,7 @@
72
73
  },
73
74
  "dependencies": {
74
75
  "fp-ts": "^2.12.1",
76
+ "jws": "^4.0.0",
75
77
  "styled-jsx": "^5.0.2",
76
78
  "uuid": "^9.0.0"
77
79
  }