big auth/integrations update

This commit is contained in:
vincanger 2023-01-30 13:48:05 +01:00
parent b698924fa9
commit f359ef6e18
9 changed files with 288 additions and 116 deletions

View File

@ -3,7 +3,7 @@ Waspello
**Waspello** is a trello clone app made with Wasp.
This app is deployed at [https://waspello.netlify.app/](https://waspello.netlify.app/).
This app is deployed at [https://waspello-demo.netlify.app/login](https://waspello-demo.netlify.app/login).
The backend is hosted on Heroku - [@matijaSos](https://github.com/matijaSos)

View File

@ -2,6 +2,8 @@
Welcome to the Waspleau example! This is a small Wasp project that will allow you to setup an easy Dashboard that pulls in data via [Jobs](https://wasp-lang.dev/docs/language/features#jobs) and stores them in the database.
The deployed version of this example can be found at https://waspleau.netlify.app/
## Step 1
Clone this repo

View File

@ -2,9 +2,30 @@
title: Examples
---
Todo App:
- source code: https://github.com/wasp-lang/wasp/tree/release/examples/tutorials/TodoApp .
import useBaseUrl from '@docusaurus/useBaseUrl';
Real World App (clone of Medium):
- source code: https://github.com/wasp-lang/wasp/tree/release/examples/realworld .
- hosted at: https://wasp-rwa.netlify.app/ .
We have a constantly growing collection of fully-functioning example apps, which you can use to learn more about Wasp's features.
The full list of examples can be found [here](https://github.com/wasp-lang/wasp/tree/release/examples/). Here is a few of them:
## Todo App
- **Features**: Auth ([username/password](language/features#authentication--authorization)), [Queries & Actions](language/features#queries-and-actions-aka-operations), [Entities](language/features#entity), [Routes](language/features#route)
- JS source code: [GitHub](https://github.com/wasp-lang/wasp/tree/release/examples/tutorials/TodoApp)
- TS source code: [GitHub](https://github.com/wasp-lang/wasp/tree/release/examples/todo-typescript)
- in-browser dev environment: [GitPod](https://gitpod.io/#https://github.com/wasp-lang/gitpod-template)
## Waspello (Trello Clone)
- **Features**: Auth ([Google](language/features#social-login-providers-oauth-20---google-github), [username/password](language/features#authentication--authorization)), [Optimistic Updates](language/features#the-useaction-hook), [Tailwind CSS integration](integrations/css-frameworks)
- Source code: [GitHub](https://github.com/wasp-lang/wasp/tree/main/examples/waspello)
- Hosted at [https://waspello-demo.netlify.app](https://waspello-demo.netlify.app/login)
<p align='center'>
<img src={useBaseUrl('img/wespello-new.png')} width='75%'/>
</p>
## Waspleau (Realtime Statistics Dashboard)
- **Features**: Cron [Jobs](language/features#jobs), [Server Setup](language/features#server-configuration)
- Source code: [GitHub](https://github.com/wasp-lang/wasp/tree/main/examples/waspleau)
- Hosted at [https://waspleau.netlify.app/](https://waspleau.netlify.app/)
<p align='center'>
<img src={useBaseUrl('img/waspleau.png')} width='75%'/>
</p>

View File

@ -6,9 +6,60 @@ import useBaseUrl from '@docusaurus/useBaseUrl';
# GitHub Integrations
To implement GitHub Auth, you'll need to add the Auth object with the following configuration to your `main.wasp` file:
```c title="main.wasp"
app Example {
wasp: {
version: "^0.8.0"
},
title: "Example",
auth: {
userEntity: User,
externalAuthEntity: SocialLogin,
methods: {
gitHub: {}
},
onAuthFailedRedirectTo: "/login"
},
}
//...
entity User {=psl
id Int @id @default(autoincrement())
username String @unique
password String
externalAuthAssociations SocialLogin[]
psl=}
entity SocialLogin {=psl
id Int @id @default(autoincrement())
provider String
providerId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int
createdAt DateTime @default(now())
@@unique([provider, providerId, userId])
psl=}
```
For more info on the specific fields, check out this [Auth](../language/features#social-login-providers-oauth-20---google-github) section of the docs.
You'll also need to add these environment variables to your `.env.server` file at the root of your project:
```bash title=".env.server"
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
```
We will cover how to get these values in the next section.
## GitHub Auth
To use GitHub as an authentication method (covered [here](/docs/language/features#github)), you'll first need to create a GitHub OAuth App and provide Wasp with your client key and secret. Here is how to do so:
To use GitHub as an authentication method (covered [here](/docs/language/features#social-login-providers-oauth-20---google-github)), you'll first need to create a GitHub OAuth App and provide Wasp with your client key and secret. Here is how to do so:
1. Log into your GitHub account and navigate to: https://github.com/settings/developers
2. Select "New OAuth App"
@ -23,4 +74,7 @@ To use GitHub as an authentication method (covered [here](/docs/language/feature
- Once you know on which URL your API server will be deployed, you can create a new app with that URL instead.
- For example: `https://someotherhost.com/auth/login/github`
4. Hit "Register application"
5. Copy your Client ID and Client secret, and expose them as environment variables named `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET` wherever your app is running
5. Copy your Client ID and Client secret, and paste them into your environment variables named `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET`in your `.env.server` file.
6. Now when youre user logs in with GitHub, you can access the logged in user on the client via the `useAuth()` hook, and on the server via the `context.user` object as described [here](/docs/language/features#accessing-the-currently-logged-in-user)!

View File

@ -6,9 +6,59 @@ import useBaseUrl from '@docusaurus/useBaseUrl';
# Google Integrations
To implement Google Auth, you'll need to add the Auth object with the following configuration to your `main.wasp` file:
```c title="main.wasp"
app Example {
wasp: {
version: "^0.8.0"
},
title: "Example",
auth: {
userEntity: User,
externalAuthEntity: SocialLogin,
methods: {
google: {}
},
onAuthFailedRedirectTo: "/login"
},
}
//...
entity User {=psl
id Int @id @default(autoincrement())
username String @unique
password String
externalAuthAssociations SocialLogin[]
psl=}
entity SocialLogin {=psl
id Int @id @default(autoincrement())
provider String
providerId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int
createdAt DateTime @default(now())
@@unique([provider, providerId, userId])
psl=}
```
For more info on the specific fields, check out this [Auth](../language/features#social-login-providers-oauth-20---google-github) section of the docs.
You'll also need to add these environment variables to your `.env.server` file at the root of your project:
```bash title=".env.server"
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
```
We will cover how to get these values in the next section.
## Google Auth
To use Google as an authentication method (covered [here](/docs/language/features#google)), you'll first need to create a Google project and provide Wasp with your client key and secret. Here is how to do so:
To use Google as an authentication method (covered [here](/docs/language/features#social-login-providers-oauth-20---google-github)), you'll first need to create a Google project and provide Wasp with your client key and secret. Here is how to do so:
1. Create a Google Cloud Platform account if you do not already have one: https://cloud.google.com/
2. Create and configure a new Google project here: https://console.cloud.google.com/home/dashboard
@ -64,4 +114,5 @@ To use Google as an authentication method (covered [here](/docs/language/feature
![Google Console Screenshot 14](../../static/img/integrations-google-14.jpg)
5. Copy your Client ID and Client secret, and expose them as environment variables named `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET` wherever your app is running
5. Copy your Client ID and Client secret, and expose them as environment variables named `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET` in your `.env.server` file.
6. Now when your user logs in with Google, you can access the logged in user on the client via the `useAuth()` hook, and on the server via the `context.user` object as described [here](/docs/language/features#accessing-the-currently-logged-in-user)!

View File

@ -809,7 +809,7 @@ In the future, we will add support for picking any version you like, but we have
## Authentication & Authorization
Wasp provides authentication and authorization support out-of-the-box. Enabling it for your app is optional and can be done by configuring `auth` field of the `app` declaration:
Wasp provides authentication and authorization support out-of-the-box. Enabling it for your app is optional and can be done by configuring the `auth` field of the `app` declaration:
```c
app MyApp {
@ -1134,7 +1134,7 @@ Wasp currently supports the following Social Login providers (with more to come)
- [GitHub](features#github)
- [Google](features#google)
The following is a quick example of how your `.wasp` file might look like when implementing social login. Make sure to read the specific sections for furter requirements (env variables) and override options:
The following is a quick example of how your `.wasp` file might look like when implementing social login. Make sure to read the specific sections for further requirements (env variables) and override options:
```c title="main.wasp"
app MyApp {
@ -1171,15 +1171,19 @@ entity SocialLogin {=psl
@@unique([provider, providerId, userId])
psl=}
```
:::caution
Be sure to include an `externalAuthEntity` in your `auth` declaration, as [described here](features#externalauthentity). Note that the same `externalAuthEntity` can be used across different social login providers (e.g., both GitHub and Google can use the same entity).
:::info
Wasp assigns generated values to the `username` and `password` fields of the `userEntity` by default, so make sure to include it them your `userEntity` declaration even if you're only using a Social Login provider.
If you require custom configuration setup or user entity field assignment, you can [override the defaults](features#google-overrides).
:::
:::info Default User Fields
When a user signs in for the first time, Wasp assigns generated values to the `username` and `password` fields of the `userEntity` by default (e.g. `username: nice-blue-horse-14357`), so make sure to include these in your `userEntity` declaration even if you're only using a Social Login provider. If you'd like to change this behavior, these values can be overridden as described below.
:::
:::tip UI Helpers and Overrides
Wasp provides you with a few UI helper components and functions to make implementing social login easier. See [here](features#ui-helpers-for-social-login-providers) for more details.
It is also posslbe to [override the default](features#overrides-for-social-login-providers) login behaviors that Wasp provides for you. This allows you to create custom setups, such as allowing Users to define a username rather than the default random username assigned by Wasp on initial Login.
:::
#### Google
@ -1201,83 +1205,9 @@ If you require custom configuration setup or user entity field assignment, you c
- By default, Wasp expects you to set two environment variables in order to use Google authentication:
- `GOOGLE_CLIENT_ID`
- `GOOGLE_CLIENT_SECRET`
- These can be obtained in your Google Cloud Console project dashboard. See [here](/docs/integrations/google#google-auth) for more.
- Sign in:
- When a user signs in for the first time, Wasp will create a new User account and link it to their Google account for future logins. The `username` will default to a random dictionary phrase that does not exist in the database, like "nice-blue-horse-27160".
:::note Changing Random Username
If you would like to allow the user to select their own username, or some other sign up flow, you could add a boolean property to your User entity which indicates if the account setup is complete. You can then check this user's property on the client with the [`useAuth()`](#useauth) hook and redirect them when appropriate -- e.g. check on homepage if `user.isAuthSetup === false`, redirect them to `EditUserDetailsPage`.
Alternatively, you could add a `displayName` property to your User entity and assign it using the details of their Google account, as described in **Overrides** below
:::
- Here is a link to the default implementations: https://github.com/wasp-lang/wasp/blob/release/waspc/data/Generator/templates/server/src/routes/auth/passport/google/defaults.js . These can be overriden as explained below.
##### Google Overrides
If you require modifications to the above, you can add one or more of the following to your `auth.methods.google` dictionary:
```js
auth: {
userEntity: User,
externalAuthEntity: SocialLogin,
methods: {
google: {
configFn: import { config } from "@server/auth/google.js",
getUserFieldsFn: import { getUserFields } from "@server/auth/google.js"
}
},
...
}
```
- `configFn`: This function should return an object with the following shape:
```js title=src/server/auth/google.js
export function config() {
// ...
return {
clientID, // look up from env or elsewhere,
clientSecret, // look up from env or elsewhere,
scope: ['profile'] // must include at least 'profile' for Google
}
}
// ...
```
- `getUserFieldsFn`: This function should return the user fields to use when creating a new user upon their first Google login. The context contains a User entity for DB access, and the args are what the OAuth provider responds with. Here is how you could generate a username based on the Google display name. In your model, you could choose to add more attributes and set additional information.
```js title=src/server/auth/google.js
import { generateAvailableUsername } from '@wasp/core/auth.js'
// ...
export async function getUserFields(_context, args) {
const username = await generateAvailableUsername(args.profile.displayName.split(' '), { separator: '.' })
return { username }
}
```
- `generateAvailableUsername` takes an array of Strings and an optional separator and generates a string ending with a random number that is not yet in the database. For example, the above could produce something like "Jim.Smith.3984" for a Google user Jim Smith.
##### Google UI helpers
To use the Google sign-in button, logo or URL on your login page, do either of the following:
```js
...
import { SignInButton as GoogleSignInButton, signInUrl as googleSignInUrl, logoUrl as googleLogoUrl } from '@wasp/auth/helpers/Google'
const Login = () => {
return (
<>
...
<GoogleSignInButton/>
{/* or */}
<a href={googleSignInUrl}>Sign in with Google</a>
</>
)
}
export default Login
```
If you need more customization than what the buttons provide, you can create your own custom component using the `googleSignInUrl`.
- These can be obtained in your Google Cloud Console project dashboard. See [here](/docs/integrations/google#google-auth) for a detailed guide.
Here is a link to the default implementations: https://github.com/wasp-lang/wasp/blob/release/waspc/data/Generator/templates/server/src/routes/auth/passport/google/defaults.js.
#### GitHub
@ -1296,20 +1226,15 @@ If you need more customization than what the buttons provide, you can create you
}
```
This method requires also requires that `externalAuthEntity` be specified in `auth` as [described here](features#externalauthentity). NOTE: The same `externalAuthEntity` can be used across different social login providers (e.g., both GitHub and Google can use the same entity).
If you require custom configuration setup or user entity field assignment, you can override the defaults. Please check out that section for [Google overrides](features#google-overrides), as the information is the same.
##### GitHub Default settings
- Configuration:
- By default, Wasp expects you to set two environment variables in order to use GitHub authentication:
- `GITHUB_CLIENT_ID`
- `GITHUB_CLIENT_SECRET`
- These can be obtained in your GitHub project dashboard. See [here](/docs/integrations/github#github-auth) for more.
- The same sign-in logic applies as for Google. Please see [that section](features#google-default-settings) for more.
- Here is a link to the default implementations: https://github.com/wasp-lang/wasp/blob/release/waspc/data/Generator/templates/server/src/routes/auth/passport/github/defaults.js
- These can be obtained in your GitHub project dashboard. See [here](/docs/integrations/github#github-auth) for a detailed guide.
Here is a link to the default implementations: https://github.com/wasp-lang/wasp/blob/release/waspc/data/Generator/templates/server/src/routes/auth/passport/github/defaults.js
NOTE: The same UI helpers apply as for Google. Please [see here](features#google-ui-helpers) for more.
#### `externalAuthEntity`
Anytime an authentication method is used that relies on an external authorization provider, for example, Google, we require an `externalAuthEntity` specified in `auth`, in addition to the `userEntity`, that contains at least the following highlighted fields:
@ -1339,6 +1264,116 @@ entity SocialLogin {=psl
psl=}
```
#### UI helpers for Social Login Providers
To use the provided sign-in buttons, logos or URLs on your login page, do either of the following:
```jsx
...
import { SignInButton as GoogleSignInButton, signInUrl as googleSignInUrl, logoUrl as googleLogoUrl } from '@wasp/auth/helpers/Google'
import { SignInButton as GitHubSignInButton, signInUrl as gitHubSignInUrl, logoUrl as gitHubLogoUrl } from '@wasp/auth/helpers/GitHub'
const Login = () => {
return (
<>
...
<GoogleSignInButton/>
<GitHubSignInButton/>
{/* or */}
<a href={googleSignInUrl}>Sign in with Google</a>
<a href={gitHubSignInUrl}>Sign in with GitHub</a>
</>
)
}
export default Login
```
If you need more customization than what the buttons provide, you can create your own custom components using the `signInUrl`s.
#### Overrides for Social Login Providers
When a user signs in for the first time, Wasp will create a new User account and link it to the chosen Auth Provider account (e.g. Google, GitHub) for future logins. The `username` will default to a random dictionary phrase that does not exist in the database, such as "nice-blue-horse-27160"
If you would like to allow the user to select their own username, or some other sign up flow, you could add a boolean property to your User entity which indicates if the account setup is complete. You can then check this user's property on the client with the [`useAuth()`](#useauth) hook and redirect them when appropriate -- e.g. check on homepage if `user.isAuthSetup === false`, redirect them to `EditUserDetailsPage`.
Alternatively, you could add a `displayName` property to your User entity and assign it using the details of their provider account. Below is an example of how to do this:
```c title=main.wasp {9,10,13,14,26}
app Example {
//...
auth: {
userEntity: User,
externalAuthEntity: SocialLogin,
methods: {
google: {
configFn: import { config } from "@server/auth/google.js",
getUserFieldsFn: import { getUserFields } from "@server/auth/google.js"
},
gitHub: {
configFn: import { config } from "@server/auth/github.js",
getUserFieldsFn: import { getUserFields } from "@server/auth/github.js"
}
},
//...
}
}
entity User {=psl
id Int @id @default(autoincrement())
username String @unique
password String
displayName String?
externalAuthAssociations SocialLogin[]
psl=}
//...
```
- `configFn`: This function should return an object with the following shape:
```js title=src/server/auth/google.js
export function config() {
// ...
return {
clientID, // look up from env or elsewhere,
clientSecret, // look up from env or elsewhere,
scope: ['profile'] // must include at least 'profile' for Google
}
}
// ...
```
```js title=src/server/auth/github.js
export function config() {
// ...
return {
clientID, // look up from env or elsewhere,
clientSecret, // look up from env or elsewhere,
scope: [] // pass an empty array for GitHub
}
}
// ...
```
- `getUserFieldsFn`: This function should return the user fields to use when creating a new user upon their first time logging in with a Social Auth Provider. The context contains a User entity for DB access, and the args are what the OAuth provider responds with. Here is how you could generate a username based on the Google display name. In your model, you could choose to add more attributes and set additional information.
```js title=src/server/auth/google.js
import { generateAvailableUsername } from '@wasp/core/auth.js'
// ...
export async function getUserFields(_context, args) {
const username = await generateAvailableUsername(args.profile.displayName.split(' '), { separator: '.' })
return { username }
}
```
- `generateAvailableUsername` takes an array of Strings and an optional separator and generates a string ending with a random number that is not yet in the database. For example, the above could produce something like "Jim.Smith.3984" for a Google user Jim Smith.
## Client configuration
You can configure the client using the `client` field inside the `app`

View File

@ -40,6 +40,27 @@ module.exports = {
},
]
},
{
type: 'category',
label: 'Guides',
collapsed: false,
items: [
'examples',
{
type: 'category',
label: 'Auth Providers',
collapsed: false,
items: [
'integrations/github',
'integrations/google',
]
},
'integrations/css-frameworks',
'deploying',
],
},
{
type: 'category',
label: 'Language',
@ -51,22 +72,10 @@ module.exports = {
]
},
'cli',
'deploying',
'examples',
{
type: 'category',
label: 'Integrations',
collapsed: false,
items: [
'integrations/github',
'integrations/google',
'integrations/css-frameworks'
]
},
{
type: 'category',
label: 'Other',
collapsed: false,
collapsed: true,
items: [
'contributing',
'vision',

BIN
web/static/img/waspleau.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB