sveltekit-auth-example 1.0.37 → 1.0.39

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/.env-sample CHANGED
@@ -1,8 +1,6 @@
1
1
  DATABASE_URL=postgres://REPLACE_WITH_USER:REPLACE_WITH_PASSWORD@localhost:5432/auth
2
2
  DOMAIN=http://localhost:3000
3
3
  JWT_SECRET=replace_with_your_own
4
- SEND_IN_BLUE_URL=https://api.sendinblue.com
5
- SEND_IN_BLUE_KEY=REPLACE_WITH_YOUR_OWN
6
- SEND_IN_BLUE_FROM='{ "email":"sender@example.com", "name":"First Last" }'
7
- SEND_IN_BLUE_ADMINS='{ "email":"admin@example.com", "name":"First Last" }'
4
+ SENDGRID_KEY=replace_with_your_own
5
+ SENDGRID_SENDER=replace_with_your_own
8
6
  PUBLIC_GOOGLE_CLIENT_ID=REPLACE_WITH_YOUR_OWN
package/CHANGELOG.md CHANGED
@@ -1,6 +1,13 @@
1
1
  # Backlog
2
2
  * Add password complexity checking on /register and /profile pages (only checks for length currently despite what the pages say)
3
3
 
4
+ # 1.0.39
5
+ * Bump Svelte, SvelteKit, adapter-node, vite, svelte-preprocess,sass, svelte-check, typescript, prettier, prettier-plugin-svelte
6
+
7
+ # 1.0.38
8
+ * Switch from SendInBlue to Sendgrid for email
9
+ * Bump SvelteKit, adapter-node, and vite
10
+
4
11
  # 1.0.37
5
12
  * Bump SvelteKit, svelte-check, and a few dev dependencies
6
13
 
package/README.md CHANGED
@@ -27,14 +27,14 @@ The website supports two types of authentication:
27
27
 
28
28
  > There is some overhead to checking the user session in a database each time versus using a JWT; however, validating each request avoids problems discussed in [this article](https://redis.com/blog/json-web-tokens-jwt-are-dangerous-for-user-sessions/) and [this one](https://scotch.io/bar-talk/why-jwts-suck-as-session-tokens). For a high-volume website, I would use Redis or the equivalent.
29
29
 
30
- The forgot password / password reset functionality uses a JWT and [**SendInBlue**](https://www.sendinblue.com) to send the email. You would need to have a **SendInBlue** account and set three environmental variables. Email sending is in /src/routes/auth/forgot.ts. This code could easily be replaced by nodemailer or something similar. Note: I have no affliation with **SendInBlue** (used their API in another project).
30
+ The forgot password / password reset functionality uses a JWT and [**SendGrid**](https://www.sendgrid.com) to send the email. You would need to have a **SendGrid** account and set two environmental variables. Email sending is in /src/routes/auth/forgot.ts. This code could easily be replaced by nodemailer or something similar. Note: I have no affliation with **SendGrid** (used their API in another project).
31
31
 
32
32
  ## Prerequisites
33
33
  - PostgreSQL 14.5 or higher
34
34
  - Node.js 18.11.0 or higher
35
35
  - npm 9.1.1 or higher
36
36
  - Google API client
37
- - SendInBlue account (only used for emailing password reset link - the sample can run without it but forgot password will not work)
37
+ - Twilio SendGrid account (only used for emailing password reset link - the sample can run without it but forgot password will not work)
38
38
 
39
39
  ## Setting up the project
40
40
 
@@ -55,15 +55,15 @@ psql -d postgres -f db_create.sql
55
55
 
56
56
  2. Create a **Google API client ID** per [these instructions](https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid). Make sure you include `http://localhost:3000`, `http://localhost` in the Authorized JavaScript origins and `http://localhost:3000/auth/google/callback` in the Authorized redirect URIs for your Client ID for Web application. ** Do not access the site using http://127.0.0.1:3000 ** - use `http://localhost:3000` or it will not work.
57
57
 
58
- 3. Create an **.env** file at the top level of the project with the following values (substituting your own id and PostgreSQL username and password):
58
+ 3. [Create a free Twilio SendGrid account](https://signup.sendgrid.com) and generate an API Key following [this documentation](https://docs.sendgrid.com/ui/account-and-settings/api-keys) and add a sender as documented [here](https://docs.sendgrid.com/ui/sending-email/senders).
59
+
60
+ 4. Create an **.env** file at the top level of the project with the following values (substituting your own id and PostgreSQL username and password):
59
61
  ```bash
60
62
  DATABASE_URL=postgres://user:password@localhost:5432/auth
61
63
  DOMAIN=http://localhost:3000
62
64
  JWT_SECRET=replace_with_your_own
63
- SEND_IN_BLUE_URL=https://api.sendinblue.com
64
- SEND_IN_BLUE_KEY=replace_with_your_own
65
- SEND_IN_BLUE_FROM='{ "email":"jdoe@example.com", "name":"John Doe" }'
66
- SEND_IN_BLUE_ADMINS='{ "email":"jdoe@example.com", "name":"John Doe" }'
65
+ SENDGRID_KEY=replace_with_your_own
66
+ SENDGRID_SENDER=replace_with_your_own
67
67
  PUBLIC_GOOGLE_CLIENT_ID=replace_with_your_own
68
68
  ```
69
69
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sveltekit-auth-example",
3
3
  "description": "SvelteKit Authentication Example",
4
- "version": "1.0.37",
4
+ "version": "1.0.39",
5
5
  "private": false,
6
6
  "author": "Nate Stuyvesant",
7
7
  "license": "https://github.com/nstuyvesant/sveltekit-auth-example/blob/master/LICENSE",
@@ -33,35 +33,36 @@
33
33
  },
34
34
  "engines": {
35
35
  "node": ">=18.11.0",
36
- "npm": "^9.1.2"
36
+ "npm": "^9.2.0"
37
37
  },
38
38
  "type": "module",
39
39
  "dependencies": {
40
+ "@sendgrid/mail": "^7.7.0",
40
41
  "pg": "^8.8.0"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@sveltejs/adapter-node": "latest",
44
45
  "@sveltejs/kit": "latest",
45
46
  "@types/bootstrap": "5.2.6",
46
- "@types/google.accounts": "0.0.3",
47
+ "@types/google.accounts": "0.0.4",
47
48
  "@types/jsonwebtoken": "^8.5.9",
48
49
  "@types/pg": "^8.6.5",
49
- "@typescript-eslint/eslint-plugin": "^5.45.0",
50
- "@typescript-eslint/parser": "^5.45.0",
50
+ "@typescript-eslint/eslint-plugin": "^5.46.0",
51
+ "@typescript-eslint/parser": "^5.46.0",
51
52
  "bootstrap": "^5.2.3",
52
- "eslint": "^8.28.0",
53
+ "eslint": "^8.29.0",
53
54
  "eslint-config-prettier": "^8.5.0",
54
55
  "eslint-plugin-svelte3": "^4.0.0",
55
56
  "google-auth-library": "^8.7.0",
56
57
  "jsonwebtoken": "^8.5.1",
57
- "prettier": "^2.8.0",
58
- "prettier-plugin-svelte": "^2.8.1",
59
- "sass": "^1.56.1",
60
- "svelte": "^3.53.1",
61
- "svelte-check": "^2.10.0",
62
- "svelte-preprocess": "^4.10.7",
58
+ "prettier": "^2.8.1",
59
+ "prettier-plugin-svelte": "^2.9.0",
60
+ "sass": "^1.56.2",
61
+ "svelte": "^3.54.0",
62
+ "svelte-check": "^2.10.2",
63
+ "svelte-preprocess": "^5.0.0",
63
64
  "tslib": "^2.4.1",
64
- "typescript": "^4.9.3",
65
- "vite": "^3.2.4"
65
+ "typescript": "^4.9.4",
66
+ "vite": "^4.0.0"
66
67
  }
67
68
  }
package/src/app.d.ts CHANGED
@@ -17,10 +17,8 @@ declare namespace App {
17
17
  DATABASE_URL: string
18
18
  DOMAIN: string
19
19
  JWT_SECRET: string
20
- SEND_IN_BLUE_URL: string
21
- SEND_IN_BLUE_KEY: string
22
- SEND_IN_BLUE_FROM: string
23
- SEND_IN_BLUE_ADMINS: string
20
+ SENDGRID_KEY: string
21
+ SENDGRID_SENDER: string
24
22
  }
25
23
 
26
24
  interface PublicEnv { // $env/static/public
@@ -40,42 +38,6 @@ interface Credentials {
40
38
  password: string
41
39
  }
42
40
 
43
- interface MessageAddressee {
44
- email: string
45
- name?: string
46
- }
47
-
48
- interface Message {
49
- sender?: MessageAddressee
50
- to?: MessageAddressee[]
51
- subject: string
52
- htmlContent?: string
53
- textContent?: string
54
- tags?: string[]
55
- contact?: Person
56
- }
57
-
58
- interface SendInBlueContact {
59
- updateEnabled: boolean
60
- email: string
61
- emailBlacklisted: boolean
62
- attributes: {
63
- NAME: string
64
- SURNAME: string
65
- }
66
- }
67
-
68
- interface SendInBlueMessage extends Message {
69
- sender: MessageAddressee
70
- to: MessageAddressee[]
71
- }
72
-
73
- interface SendInBlueRequest extends RequestInit {
74
- headers: {
75
- 'api-key': string
76
- }
77
- }
78
-
79
41
  interface UserProperties {
80
42
  id: number
81
43
  expires?: string // ISO-8601 datetime
@@ -0,0 +1,17 @@
1
+ import type { MailDataRequired } from '@sendgrid/mail'
2
+ import sgMail from '@sendgrid/mail'
3
+ import { env } from '$env/dynamic/private'
4
+
5
+ export const sendMessage = async (message: Partial<MailDataRequired>) => {
6
+ const { SENDGRID_SENDER, SENDGRID_KEY } = env
7
+ try {
8
+ sgMail.setApiKey(SENDGRID_KEY)
9
+ const completeMessage = <MailDataRequired> {
10
+ from: SENDGRID_SENDER, // default sender can be altered
11
+ ...message
12
+ }
13
+ await sgMail.send(completeMessage)
14
+ } catch (errSendingMail) {
15
+ console.error(errSendingMail)
16
+ }
17
+ }
@@ -1,9 +1,10 @@
1
- import type { RequestHandler } from './$types'
2
- import { JWT_SECRET, DOMAIN } from '$env/static/private'
3
1
  import type { Secret } from 'jsonwebtoken'
2
+ import type { MailDataRequired } from '@sendgrid/mail'
3
+ import type { RequestHandler } from './$types'
4
4
  import jwt from 'jsonwebtoken'
5
+ import { JWT_SECRET, DOMAIN, SENDGRID_SENDER } from '$env/static/private'
5
6
  import { query } from '$lib/server/db'
6
- import { sendMessage } from '$lib/server/send-in-blue'
7
+ import { sendMessage } from '$lib/server/sendgrid'
7
8
 
8
9
  export const POST: RequestHandler = async event => {
9
10
  const body = await event.request.json()
@@ -19,11 +20,12 @@ export const POST: RequestHandler = async event => {
19
20
  })
20
21
 
21
22
  // Email URL with token to user
22
- const message: Message = {
23
- to: [{ email: body.email }],
23
+ const message: MailDataRequired = {
24
+ to: { email: body.email },
25
+ from: SENDGRID_SENDER,
24
26
  subject: 'Password reset',
25
- tags: ['account'],
26
- htmlContent: `
27
+ categories: ['account'],
28
+ html: `
27
29
  <a href="${DOMAIN}/auth/reset/${token}">Reset my password</a>. Your browser will open and ask you to provide a
28
30
  new password with a confirmation then redirect you to your login page.
29
31
  `
@@ -1,22 +0,0 @@
1
- import { SEND_IN_BLUE_KEY, SEND_IN_BLUE_URL, SEND_IN_BLUE_FROM, SEND_IN_BLUE_ADMINS } from '$env/static/private'
2
-
3
- const sender = <MessageAddressee> JSON.parse(SEND_IN_BLUE_FROM || '')
4
- const to = <MessageAddressee> JSON.parse(SEND_IN_BLUE_ADMINS || '')
5
-
6
- // POST or PUT submission to SendInBlue
7
- const submit = async (method: string, url: string, data: Partial<SendInBlueContact> | SendInBlueMessage) => {
8
- const response: Response = await fetch(`${SEND_IN_BLUE_URL}${url}`, <SendInBlueRequest> {
9
- method,
10
- headers: {
11
- 'Content-Type': 'application/json',
12
- 'api-key': SEND_IN_BLUE_KEY
13
- },
14
- body: JSON.stringify(data)
15
- })
16
- if (!response.ok) {
17
- console.error('Error from SendInBlue:', response)
18
- throw new Error(`Error communicating with SendInBlue.`)
19
- }
20
- }
21
-
22
- export const sendMessage = async (message: Message) => submit('POST', '/v3/smtp/email', { sender, to: [to], ...message })