Skip to content

Commit eb2c9e4

Browse files
committed
refactor: Update API method names and parameters
1 parent bbdbf56 commit eb2c9e4

22 files changed

+1060
-534
lines changed

.github/workflows/pull_request.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ jobs:
2828
- run: yarn test
2929
env:
3030
GOOGLE_CLOUD_CREDENTIALS: ${{ secrets.GOOGLE_CLOUD_CREDENTIALS }}
31+
FIREBASE_API_KEY: ${{ secrets.FIREBASE_API_KEY }}

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Include your project-specific ignores in this file
22
# Read about how to use .gitignore: https://help.github.com/articles/ignoring-files
33

4-
# Compiled output
4+
# Cache and compiled output
5+
/.cache/
56
/dist/
67

78
# Yarn package manager

.vscode/settings.json

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,34 @@
3131
"**/yarn.lock": true,
3232
"**/.yarn": true,
3333
"**/.pnp.*": true
34-
}
34+
},
35+
"terminal.integrated.env.linux": {
36+
"CACHE_DIR": "${workspaceFolder}/.cache"
37+
},
38+
"terminal.integrated.env.osx": {
39+
"CACHE_DIR": "${workspaceFolder}/.cache"
40+
},
41+
"terminal.integrated.env.windows": {
42+
"CACHE_DIR": "${workspaceFolder}\\.cache"
43+
},
44+
"cSpell.words": [
45+
"async",
46+
"await",
47+
"cjs",
48+
"endregion",
49+
"esm",
50+
"hono",
51+
"identitytoolkit",
52+
"jest",
53+
"mjs",
54+
"node",
55+
"ts",
56+
"tsconfig",
57+
"tslib",
58+
"tslint",
59+
"tsnode",
60+
"tsv",
61+
"tsx",
62+
"yarn"
63+
]
3564
}

README.md

Lines changed: 69 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
1-
# Authentication Library for the Web
1+
# Web Auth Library
22

33
[![NPM Version](https://img.shields.io/npm/v/web-auth-library?style=flat-square)](https://www.npmjs.com/package/web-auth-library)
44
[![NPM Downloads](https://img.shields.io/npm/dm/web-auth-library?style=flat-square)](https://www.npmjs.com/package/web-auth-library)
55
[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg?style=flat-square)](http://www.typescriptlang.org/)
66
[![Donate](https://img.shields.io/badge/dynamic/json?color=%23ff424d&label=Patreon&style=flat-square&query=data.attributes.patron_count&suffix=%20patrons&url=https%3A%2F%2Fwww.patreon.com%2Fapi%2Fcampaigns%2F233228)](http://patreon.com/koistya)
77
[![Discord](https://img.shields.io/discord/643523529131950086?label=Chat&style=flat-square)](https://discord.gg/bSsv7XM)
88

9-
A collection of utility functions for working with [Web Crypto API](https://developer.mozilla.org/docs/Web/API/Web_Crypto_API).
9+
Authentication library for Google Cloud, Firebase, and other cloud providers that uses standard [Web Crypto API](https://developer.mozilla.org/docs/Web/API/Web_Crypto_API) and runs in different environments and runtimes, including but not limited to:
10+
11+
- [Bun](https://bun.sh/)
12+
- [Browsers](https://developer.mozilla.org/docs/Web/API/Web_Crypto_API)
13+
- [Cloudflare Workers](https://workers.cloudflare.com/)
14+
- [Deno](https://deno.land/)
15+
- [Electron](https://www.electronjs.org/)
16+
- [Node.js](https://nodejs.org/)
17+
- [Vercel's Edge Runtime](https://edge-runtime.vercel.app/)
18+
19+
It has minimum dependencies, small bundle size, and optimized for speed and performance.
20+
21+
## Getting Stated
1022

1123
```bash
1224
# Install using NPM
@@ -16,121 +28,93 @@ $ npm install web-auth-library --save
1628
$ yarn add web-auth-library
1729
```
1830

19-
## Usage Example
31+
## Usage Examples
2032

21-
### Retrieving an access token from Google's OAuth 2.0 authorization server
33+
### Verify the user ID Token issued by Google or Firebase
34+
35+
**NOTE**: The `credentials` argument in the examples below is expected to be a serialized JSON string of a [Google Cloud service account key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys), `apiKey` is Google Cloud API Key (Firebase API Key), and `projectId` is a Google Cloud project ID.
2236

2337
```ts
24-
import { getAuthToken } from "web-auth-library/google";
38+
import { verifyIdToken } from "web-auth-library/google";
2539

26-
const token = await getAuthToken({
40+
const token = await verifyIdToken({
41+
idToken,
2742
credentials: env.GOOGLE_CLOUD_CREDENTIALS,
28-
scope: "https://www.googleapis.com/auth/cloud-platform",
2943
});
44+
3045
// => {
31-
// accessToken: "ya29.c.b0AXv0zTOQVv0...",
32-
// type: "Bearer",
33-
// expires: 1653855236,
46+
// iss: 'https://securetoken.google.com/example',
47+
// aud: 'example',
48+
// auth_time: 1677525930,
49+
// user_id: 'temp',
50+
// sub: 'temp',
51+
// iat: 1677525930,
52+
// exp: 1677529530,
53+
// firebase: {}
3454
// }
35-
36-
return fetch("https://cloudresourcemanager.googleapis.com/v1/projects", {
37-
headers: {
38-
authorization: `Bearer ${token.accessToken}`,
39-
},
40-
});
4155
```
4256

43-
Where `env.GOOGLE_CLOUD_CREDENTIALS` is an environment variable / secret
44-
containing a [service account key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys)
45-
(JSON) obtained from the [Google Cloud Platform](https://cloud.google.com/).
46-
47-
#### Retrieving an ID token for the target audience
57+
### Create an access token for accessing [Google Cloud APIs](https://developers.google.com/apis-explorer)
4858

4959
```ts
50-
import { getAuthToken } from "web-auth-library/google";
60+
import { getAccessToken } from "web-auth-library/google";
5161

52-
const token = await getAuthToken({
62+
// Generate a short lived access token from the service account key credentials
63+
const accessToken = await getAccessToken({
5364
credentials: env.GOOGLE_CLOUD_CREDENTIALS,
54-
audience: "https://example.com",
65+
scope: "https://www.googleapis.com/auth/cloud-platform",
5566
});
56-
// => {
57-
// idToken: "eyJhbGciOiJSUzI1NiIsImtpZ...",
58-
// audience: "https://example.com",
59-
// expires: 1654199401,
60-
// }
61-
```
6267

63-
#### Decoding an ID token
64-
65-
```ts
66-
import { jwt } from "web-auth-library/google";
67-
68-
jwt.decode(idToken);
69-
// {
70-
// header: {
71-
// alg: 'RS256',
72-
// kid: '38f3883468fc659abb4475f36313d22585c2d7ca',
73-
// typ: 'JWT'
74-
// },
75-
// payload: {
76-
// iss: 'https://accounts.google.com',
77-
// sub: '118363561738753879481'
78-
// aud: 'https://example.com',
79-
80-
// email: '[email protected]',
81-
// email_verified: true,
82-
// exp: 1654199401,
83-
// iat: 1654195801,
84-
// },
85-
// data: 'eyJhbGciOiJ...',
86-
// signature: 'MDzBStL...'
87-
// }
68+
// Make a request to one of the Google's APIs using that token
69+
const res = await fetch(
70+
"https://cloudresourcemanager.googleapis.com/v1/projects",
71+
{
72+
headers: { Authorization: `Bearer ${accessToken}` },
73+
}
74+
);
8875
```
8976

90-
#### Verifying an ID token
77+
## Create a custom ID token using Service Account credentials
9178

9279
```ts
93-
import { verifyIdToken } from "web-auth-library/google";
80+
import { getIdToken } from "web-auth-library/google";
9481

95-
const token = await verifyIdToken(idToken, { audience: "https://example.com" });
96-
// => {
97-
// iss: 'https://accounts.google.com',
98-
// aud: 'https://example.com',
99-
// sub: '118363561738753879481'
100-
101-
// email: '[email protected]',
102-
// email_verified: true,
103-
// exp: 1654199401,
104-
// iat: 1654195801,
105-
// }
82+
const idToken = await getIdToken({
83+
credentials: env.GOOGLE_CLOUD_CREDENTIALS,
84+
audience: "https://example.com",
85+
});
10686
```
10787

108-
#### Generating a digital signature
88+
## An alternative way passing credentials
89+
90+
Instead of passing credentials via `options.credentials` argument, you can also let the library pick up credentials from the list of environment variables using standard names such as `GOOGLE_CLOUD_CREDENTIALS`, `GOOGLE_CLOUD_PROJECT`, `FIREBASE_API_KEY`, for example:
10991

11092
```ts
111-
import { getCredentials, importKey, sign } from "web-auth-library/google";
93+
import { verifyIdToken } from "web-auth-library/google";
11294

113-
const credentials = getCredentials(env.GOOGLE_CLOUD_CREDENTIALS);
114-
const signingKey = await importKey(credentials.private_key, ["sign"]);
115-
const signature = await sign(signingKey, "xxx");
95+
const env = { GOOGLE_CLOUD_CREDENTIALS: "..." };
96+
const token = await verifyIdToken({ idToken, env });
11697
```
11798

118-
#### Decoding a `JWT` token
99+
## Optimize cache renewal background tasks
100+
101+
Pass the optional `waitUntil(promise)` function provided by the target runtime to optimize the way authentication tokens are being renewed in background. For example, using Cloudflare Workers and [Hono.js](https://hono.dev/):
119102

120103
```ts
121-
import { jwt } from "web-auth-library";
104+
import { Hono } from "hono";
105+
import { verifyIdToken } from "web-auth-library/google";
122106

123-
jwt.decode("eyJ0eXAiOiJKV1QiLC...");
124-
// => {
125-
// header: { alg: "HS256", typ: "JWT" },
126-
// payload: { iss: "...", aud: "...", iat: ..., exp: ... },
127-
// signature: "xxx"
128-
// }
107+
const app = new Hono();
129108

130-
jwt.decode("eyJ0eXAiOiJKV1QiLC...", { header: false, signature: false });
131-
// => {
132-
// payload: { iss: "...", aud: "...", iat: ..., exp: ... },
133-
// }
109+
app.get("/", ({ env, executionCtx, json }) => {
110+
const idToken = await verifyIdToken({
111+
idToken: "...",
112+
waitUntil: executionCtx.waitUntil,
113+
env,
114+
});
115+
116+
return json({ ... });
117+
})
134118
```
135119

136120
## Backers 💰

core/error.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/* SPDX-FileCopyrightText: 2022-present Kriasoft */
2+
/* SPDX-License-Identifier: MIT */
3+
4+
export class FetchError extends Error {
5+
readonly name: string = "FetchError";
6+
readonly response: Response;
7+
8+
constructor(
9+
message: string,
10+
options: { response: Response; cause?: unknown }
11+
) {
12+
super(message, { cause: options?.cause });
13+
this.response = options.response;
14+
15+
if (Error.captureStackTrace) {
16+
Error.captureStackTrace(this, Error);
17+
}
18+
}
19+
}

google/accessToken.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/* SPDX-FileCopyrightText: 2022-present Kriasoft */
2+
/* SPDX-License-Identifier: MIT */
3+
4+
import { decodeJwt } from "jose";
5+
import env from "../test/env.js";
6+
import { getAccessToken } from "./accessToken.js";
7+
8+
test("getAccessToken({ credentials, scope })", async () => {
9+
const accessToken = await getAccessToken({
10+
credentials: env.GOOGLE_CLOUD_CREDENTIALS,
11+
scope: "https://www.googleapis.com/auth/cloud-platform",
12+
});
13+
14+
expect(accessToken?.substring(0, 30)).toEqual(
15+
expect.stringContaining("ya29.c.")
16+
);
17+
});
18+
19+
test("getAccessToken({ credentials, audience })", async () => {
20+
const idToken = await getAccessToken({
21+
credentials: env.GOOGLE_CLOUD_CREDENTIALS,
22+
audience: "https://example.com",
23+
});
24+
25+
expect(idToken?.substring(0, 30)).toEqual(
26+
expect.stringContaining("eyJhbGciOi")
27+
);
28+
29+
expect(decodeJwt(idToken)).toEqual(
30+
expect.objectContaining({
31+
aud: "https://example.com",
32+
email_verified: true,
33+
iss: "https://accounts.google.com",
34+
})
35+
);
36+
});

0 commit comments

Comments
 (0)