2023-08-11 17:47:49 +03:00
---
title: GitHub
---
import useBaseUrl from '@docusaurus/useBaseUrl';
import DefaultBehaviour from './\_default-behaviour.md';
import OverrideIntro from './\_override-intro.md';
import OverrideExampleIntro from './\_override-example-intro.md';
import UsingAuthNote from './\_using-auth-note.md';
import WaspFileStructureNote from './\_wasp-file-structure-note.md';
import GetUserFieldsType from './\_getuserfields-type.md';
import ApiReferenceIntro from './\_api-reference-intro.md';
2024-01-18 15:42:00 +03:00
import UserSignupFieldsExplainer from '../\_user-signup-fields-explainer.md';
2023-08-11 17:47:49 +03:00
Wasp supports Github Authentication out of the box.
GitHub is a great external auth choice when you're building apps for developers, as most of them already have a GitHub account.
Letting your users log in using their GitHub accounts turns the signup process into a breeze.
Let's walk through enabling Github Authentication, explain some of the default settings, and show how to override them.
## Setting up Github Auth
Enabling GitHub Authentication comes down to a series of steps:
1. Enabling GitHub authentication in the Wasp file.
2024-01-15 13:00:54 +03:00
1. Adding the `User` entity.
2023-08-11 17:47:49 +03:00
1. Creating a GitHub OAuth app.
2024-03-18 15:09:37 +03:00
1. Adding the necessary Routes and Pages
2023-08-11 17:47:49 +03:00
1. Using Auth UI components in our Pages.
< WaspFileStructureNote / >
### 1. Adding Github Auth to Your Wasp File
Let's start by properly configuring the Auth object:
< Tabs groupId = "js-ts" >
< TabItem value = "js" label = "JavaScript" >
```wasp title="main.wasp"
app myApp {
wasp: {
2024-03-18 15:09:37 +03:00
version: "^0.13.0"
2023-08-11 17:47:49 +03:00
},
title: "My App",
auth: {
// highlight-next-line
// 1. Specify the User entity (we'll define it next)
// highlight-next-line
userEntity: User,
methods: {
// highlight-next-line
2024-01-15 13:00:54 +03:00
// 2. Enable Github Auth
2023-08-11 17:47:49 +03:00
// highlight-next-line
gitHub: {}
},
onAuthFailedRedirectTo: "/login"
},
}
```
< / TabItem >
< TabItem value = "ts" label = "TypeScript" >
```wasp title="main.wasp"
app myApp {
wasp: {
2024-03-18 15:09:37 +03:00
version: "^0.13.0"
2023-08-11 17:47:49 +03:00
},
title: "My App",
auth: {
// highlight-next-line
// 1. Specify the User entity (we'll define it next)
// highlight-next-line
userEntity: User,
methods: {
// highlight-next-line
2024-01-15 13:00:54 +03:00
// 2. Enable Github Auth
2023-08-11 17:47:49 +03:00
// highlight-next-line
gitHub: {}
},
onAuthFailedRedirectTo: "/login"
},
}
```
< / TabItem >
< / Tabs >
2024-01-15 13:00:54 +03:00
### 2. Add the User Entity
2023-08-11 17:47:49 +03:00
2024-01-15 13:00:54 +03:00
Let's now define the `app.auth.userEntity` entity:
2023-08-11 17:47:49 +03:00
< Tabs groupId = "js-ts" >
< TabItem value = "js" label = "JavaScript" >
```wasp title="main.wasp"
// ...
2024-01-15 13:00:54 +03:00
// 3. Define the User entity
2023-08-11 17:47:49 +03:00
// highlight-next-line
entity User {=psl
id Int @id @default (autoincrement())
// ...
psl=}
```
< / TabItem >
< TabItem value = "ts" label = "TypeScript" >
```wasp title="main.wasp"
// ...
2024-01-15 13:00:54 +03:00
// 3. Define the User entity
2023-08-11 17:47:49 +03:00
// highlight-next-line
entity User {=psl
id Int @id @default (autoincrement())
// ...
psl=}
```
< / TabItem >
< / Tabs >
### 3. Creating a GitHub OAuth App
To use GitHub as an authentication method, you'll first need to create a GitHub OAuth App and provide Wasp with your client key and secret. Here's how you do it:
1. Log into your GitHub account and navigate to: https://github.com/settings/developers.
2. Select **New OAuth App** .
3. Supply required information.
< img alt = "GitHub Applications Screenshot"
src={useBaseUrl('img/integrations-github-1.png')}
width="400px"
/>
- For **Authorization callback URL** :
2024-03-18 15:09:37 +03:00
- For development, put: `http://localhost:3001/auth/github/callback` .
- Once you know on which URL your API server will be deployed, you can create a new app with that URL instead e.g. `https://your-server-url.com/auth/github/callback` .
2023-08-11 17:47:49 +03:00
4. Hit **Register application** .
5. Hit **Generate a new client secret** on the next page.
6. Copy your Client ID and Client secret as you'll need them in the next step.
### 4. Adding Environment Variables
Add these environment variables to the `.env.server` file at the root of your project (take their values from the previous step):
```bash title=".env.server"
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
```
### 5. Adding the Necessary Routes and Pages
Let's define the necessary authentication Routes and Pages.
Add the following code to your `main.wasp` file:
< Tabs groupId = "js-ts" >
< TabItem value = "js" label = "JavaScript" >
```wasp title="main.wasp"
// ...
// 6. Define the routes
route LoginRoute { path: "/login", to: LoginPage }
page LoginPage {
2024-02-19 15:35:32 +03:00
component: import { Login } from "@src/pages/auth.jsx"
2023-08-11 17:47:49 +03:00
}
```
< / TabItem >
< TabItem value = "ts" label = "TypeScript" >
```wasp title="main.wasp"
// ...
// 6. Define the routes
route LoginRoute { path: "/login", to: LoginPage }
page LoginPage {
2024-02-19 15:35:32 +03:00
component: import { Login } from "@src/pages/auth.tsx"
2023-08-11 17:47:49 +03:00
}
```
< / TabItem >
< / Tabs >
2024-02-19 15:35:32 +03:00
We'll define the React components for these pages in the `src/pages/auth.{jsx,tsx}` file below.
2023-08-11 17:47:49 +03:00
### 6. Creating the Client Pages
:::info
2024-01-12 19:42:53 +03:00
We are using [Tailwind CSS ](https://tailwindcss.com/ ) to style the pages. Read more about how to add it [here ](../../project/css-frameworks ).
2023-08-11 17:47:49 +03:00
:::
2024-02-19 15:35:32 +03:00
Let's create a `auth.{jsx,tsx}` file in the `src/pages` folder and add the following to it:
2023-08-11 17:47:49 +03:00
< Tabs groupId = "js-ts" >
< TabItem value = "js" label = "JavaScript" >
2024-02-19 15:35:32 +03:00
```tsx title="src/pages/auth.jsx"
import { LoginForm } from 'wasp/client/auth'
2023-08-11 17:47:49 +03:00
export function Login() {
return (
< Layout >
< LoginForm / >
< / Layout >
)
}
// A layout component to center the content
export function Layout({ children }) {
return (
< div className = "w-full h-full bg-white" >
< div className = "min-w-full min-h-[75vh] flex items-center justify-center" >
< div className = "w-full h-full max-w-sm p-5 bg-white" >
< div > {children}< / div >
< / div >
< / div >
< / div >
)
}
```
< / TabItem >
< TabItem value = "ts" label = "TypeScript" >
2024-02-19 15:35:32 +03:00
```tsx title="src/pages/auth.tsx"
import { LoginForm } from 'wasp/client/auth'
2023-08-11 17:47:49 +03:00
export function Login() {
return (
< Layout >
< LoginForm / >
< / Layout >
)
}
// A layout component to center the content
export function Layout({ children }: { children: React.ReactNode }) {
return (
< div className = "w-full h-full bg-white" >
< div className = "min-w-full min-h-[75vh] flex items-center justify-center" >
< div className = "w-full h-full max-w-sm p-5 bg-white" >
< div > {children}< / div >
< / div >
< / div >
< / div >
)
}
```
< / TabItem >
< / Tabs >
2024-03-18 15:09:37 +03:00
We imported the generated Auth UI components and used them in our pages. Read more about the Auth UI components [here ](../../auth/ui ).
2023-08-11 17:47:49 +03:00
### Conclusion
Yay, we've successfully set up Github Auth! 🎉
![Github Auth ](/img/auth/github.png )
Running `wasp db migrate-dev` and `wasp start` should now give you a working app with authentication.
2024-01-12 19:42:53 +03:00
To see how to protect specific pages (i.e., hide them from non-authenticated users), read the docs on [using auth ](../../auth/overview ).
2023-08-11 17:47:49 +03:00
## Default Behaviour
Add `gitHub: {}` to the `auth.methods` dictionary to use it with default settings.
< Tabs groupId = "js-ts" >
< TabItem value = "js" label = "JavaScript" >
2024-01-15 13:00:54 +03:00
```wasp title=main.wasp
2023-08-11 17:47:49 +03:00
app myApp {
wasp: {
2024-03-18 15:09:37 +03:00
version: "^0.13.0"
2023-08-11 17:47:49 +03:00
},
title: "My App",
auth: {
userEntity: User,
methods: {
2024-01-15 13:00:54 +03:00
// highlight-next-line
2023-08-11 17:47:49 +03:00
gitHub: {}
},
onAuthFailedRedirectTo: "/login"
},
}
```
< / TabItem >
< TabItem value = "ts" label = "TypeScript" >
2024-01-15 13:00:54 +03:00
```wasp title=main.wasp
2023-08-11 17:47:49 +03:00
app myApp {
wasp: {
2024-03-18 15:09:37 +03:00
version: "^0.13.0"
2023-08-11 17:47:49 +03:00
},
title: "My App",
auth: {
userEntity: User,
methods: {
2024-01-15 13:00:54 +03:00
// highlight-next-line
2023-08-11 17:47:49 +03:00
gitHub: {}
},
onAuthFailedRedirectTo: "/login"
},
}
```
< / TabItem >
< / Tabs >
< DefaultBehaviour / >
## Overrides
< OverrideIntro / >
2024-03-18 15:09:37 +03:00
### Data Received From GitHub
We are using GitHub's API and its `/user` and `/user/emails` endpoints to get the user data.
:::info We combine the data from the two endpoints
You'll find the emails in the `emails` property in the object that you receive in `userSignupFields` .
This is because we combine the data from the `/user` and `/user/emails` endpoints **if the `user` or `user:email` scope is requested.**
:::
The data we receive from GitHub on the `/user` endpoint looks something this:
```json
{
"login": "octocat",
"id": 1,
"name": "monalisa octocat",
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
// ...
}
```
And the data from the `/user/emails` endpoint looks something like this:
```json
[
{
"email": "octocat@github.com",
"verified": true,
"primary": true,
"visibility": "public"
}
]
```
The fields you receive will depend on the scopes you requested. By default we don't specify any scopes. If you want to get the emails, you need to specify the `user` or `user:email` scope in the `configFn` function.
< small >
For an up to date info about the data received from GitHub, please refer to the [GitHub API documentation ](https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#get-the-authenticated-user ).
< / small >
### Using the Data Received From GitHub
2023-08-11 17:47:49 +03:00
< OverrideExampleIntro / >
< Tabs groupId = "js-ts" >
< TabItem value = "js" label = "JavaScript" >
2024-01-15 13:00:54 +03:00
```wasp title="main.wasp"
2023-08-11 17:47:49 +03:00
app myApp {
wasp: {
2024-03-18 15:09:37 +03:00
version: "^0.13.0"
2023-08-11 17:47:49 +03:00
},
title: "My App",
auth: {
userEntity: User,
methods: {
gitHub: {
2024-01-15 13:00:54 +03:00
// highlight-next-line
2024-02-19 15:35:32 +03:00
configFn: import { getConfig } from "@src/auth/github.js",
2024-01-15 13:00:54 +03:00
// highlight-next-line
2024-02-19 15:35:32 +03:00
userSignupFields: import { userSignupFields } from "@src/auth/github.js"
2023-08-11 17:47:49 +03:00
}
},
onAuthFailedRedirectTo: "/login"
},
}
entity User {=psl
id Int @id @default (autoincrement())
username String @unique
displayName String
psl=}
// ...
```
2024-02-19 15:35:32 +03:00
```js title=src/auth/github.js
2024-01-18 15:42:00 +03:00
export const userSignupFields = {
username: () => "hardcoded-username",
2024-03-18 15:09:37 +03:00
displayName: (data) => data.profile.name,
2023-08-11 17:47:49 +03:00
};
export function getConfig() {
return {
2024-03-18 15:09:37 +03:00
scopes: ['user'],
2023-08-11 17:47:49 +03:00
};
}
```
< / TabItem >
< TabItem value = "ts" label = "TypeScript" >
2024-01-15 13:00:54 +03:00
```wasp title="main.wasp"
2023-08-11 17:47:49 +03:00
app myApp {
wasp: {
2024-03-18 15:09:37 +03:00
version: "^0.13.0"
2023-08-11 17:47:49 +03:00
},
title: "My App",
auth: {
userEntity: User,
methods: {
gitHub: {
2024-01-15 13:00:54 +03:00
// highlight-next-line
2024-02-19 15:35:32 +03:00
configFn: import { getConfig } from "@src/auth/github.js",
2024-01-15 13:00:54 +03:00
// highlight-next-line
2024-02-19 15:35:32 +03:00
userSignupFields: import { userSignupFields } from "@src/auth/github.js"
2023-08-11 17:47:49 +03:00
}
},
onAuthFailedRedirectTo: "/login"
},
}
entity User {=psl
id Int @id @default (autoincrement())
username String @unique
displayName String
psl=}
// ...
```
2024-02-19 15:35:32 +03:00
```ts title=src/auth/github.ts
import { defineUserSignupFields } from 'wasp/server/auth'
2023-08-11 17:47:49 +03:00
2024-01-18 15:42:00 +03:00
export const userSignupFields = defineUserSignupFields({
username: () => "hardcoded-username",
2024-03-18 15:09:37 +03:00
displayName: (data: any) => data.profile.name,
2024-01-18 15:42:00 +03:00
})
2023-08-11 17:47:49 +03:00
export function getConfig() {
return {
2024-03-18 15:09:37 +03:00
scopes: ['user'],
2023-08-11 17:47:49 +03:00
}
}
```
< GetUserFieldsType / >
< / TabItem >
< / Tabs >
## Using Auth
< UsingAuthNote / >
## API Reference
< ApiReferenceIntro / >
< Tabs groupId = "js-ts" >
< TabItem value = "js" label = "JavaScript" >
2024-01-15 13:00:54 +03:00
```wasp title="main.wasp"
2023-08-11 17:47:49 +03:00
app myApp {
wasp: {
2024-03-18 15:09:37 +03:00
version: "^0.13.0"
2023-08-11 17:47:49 +03:00
},
title: "My App",
auth: {
userEntity: User,
methods: {
gitHub: {
2024-01-15 13:00:54 +03:00
// highlight-next-line
2024-02-19 15:35:32 +03:00
configFn: import { getConfig } from "@src/auth/github.js",
2024-01-15 13:00:54 +03:00
// highlight-next-line
2024-02-19 15:35:32 +03:00
userSignupFields: import { userSignupFields } from "@src/auth/github.js"
2023-08-11 17:47:49 +03:00
}
},
onAuthFailedRedirectTo: "/login"
},
}
```
< / TabItem >
< TabItem value = "ts" label = "TypeScript" >
2024-01-15 13:00:54 +03:00
```wasp title="main.wasp"
2023-08-11 17:47:49 +03:00
app myApp {
wasp: {
2024-03-18 15:09:37 +03:00
version: "^0.13.0"
2023-08-11 17:47:49 +03:00
},
title: "My App",
auth: {
userEntity: User,
methods: {
gitHub: {
2024-01-15 13:00:54 +03:00
// highlight-next-line
2024-02-19 15:35:32 +03:00
configFn: import { getConfig } from "@src/auth/github.js",
2024-01-15 13:00:54 +03:00
// highlight-next-line
2024-02-19 15:35:32 +03:00
userSignupFields: import { userSignupFields } from "@src/auth/github.js"
2023-08-11 17:47:49 +03:00
}
},
onAuthFailedRedirectTo: "/login"
},
}
```
< / TabItem >
< / Tabs >
The `gitHub` dict has the following properties:
2024-02-22 13:32:20 +03:00
- #### `configFn: ExtImport`
2023-08-11 17:47:49 +03:00
2024-03-18 15:09:37 +03:00
This function should return an object with the scopes for the OAuth provider.
2023-08-11 17:47:49 +03:00
< Tabs groupId = "js-ts" >
< TabItem value = "js" label = "JavaScript" >
2024-02-19 15:35:32 +03:00
```js title=src/auth/github.js
2023-08-11 17:47:49 +03:00
export function getConfig() {
return {
2024-03-18 15:09:37 +03:00
scopes: [],
2023-08-11 17:47:49 +03:00
}
}
```
< / TabItem >
< TabItem value = "ts" label = "TypeScript" >
2024-02-19 15:35:32 +03:00
```ts title=src/auth/github.ts
2023-08-11 17:47:49 +03:00
export function getConfig() {
return {
2024-03-18 15:09:37 +03:00
scopes: [],
2023-08-11 17:47:49 +03:00
}
}
```
< / TabItem >
< / Tabs >
2024-02-22 13:32:20 +03:00
- #### `userSignupFields: ExtImport`
2023-08-11 17:47:49 +03:00
2024-02-27 15:07:45 +03:00
< UserSignupFieldsExplainer / >
2024-03-18 15:09:37 +03:00
2024-02-27 15:07:45 +03:00
Read more about the `userSignupFields` function [here ](../overview#1-defining-extra-fields ).