structure in detail, while this page provides a [quick guide](#migrating-your-project-to-the-new-structure) for migrating existing
projects.
### New auth
In Wasp 0.11.X, authentication was based on the `User` model which the developer needed to set up properly and take care of the auth fields like `email` or `password`.
From 0.12.X onwards, authentication is based on the auth models which are automatically set up by Wasp. You don't need to take care of the auth fields anymore.
The `User` model is now just a business logic model and you use it for storing the data that is relevant for your app.
```wasp title="main.wasp"
app myApp {
wasp: {
version: "^0.12.0"
},
title: "My App",
auth: {
userEntity: User,
methods: {
gitHub: {}
},
onAuthFailedRedirectTo: "/login"
},
}
entity User {=psl
id Int @id@default(autoincrement())
psl=}
```
:::caution Regression Note: Multiple Auth Identities per User
With our old auth implementation, if you were using both Google and email auth methods, your users could sign up with Google first and then, later on, reset their password and therefore also enable logging in with their email and password. This was the only way in which a single user could have multiple login methods at the same time (Google and email).
This is not possible anymore. **The new auth system doesn't support multiple login methods per user at the moment**. We do plan to add this soon though, with the introduction of the [account merging feature](https://github.com/wasp-lang/wasp/issues/954).
If you have any users that have both Google and email login credentials at the same time, you will have to pick only one of those for that user to keep when migrating them.
:::
You can read more about the new auth system in the [Auth Entities](./entities) section.
## How to Migrate?
These instructions are for migrating your app from Wasp `0.11.X` to Wasp `0.12.X`, meaning they will work for all minor releases that fit this pattern (e.g., the guide applies to `0.12.0`, `0.12.1`, ...).
2.**Position yourself in the terminal** in the directory that is a parent of your wasp project directory (so one level above: if you do `ls`, you should see your wasp project dir listed).
3.**Run the migration script** (replace `foo` at the end with the name of your Wasp project directory) and follow the instructions:
Then, check the changes it did, in case some kind of manual intervention is needed (in which case you should see TODO comments generated by the script).
Alternatively, you can find all the mappings of old imports to the new ones in [this table](https://docs.google.com/spreadsheets/d/1QW-_16KRGTOaKXx9NYUtjk6m2TQ0nUMOA74hBthTH3g/edit#gid=1725669920) and use it to fix some/all of them manually.
Your `package.json` in `foo` should now list these dependencies (Wasp already generated most of the file, you just have to list additional dependencies).
You can follow these steps to migrate to the new auth system (assuming you already migrated the project structure to 0.12, as described [above](#migrating-your-project-to-the-new-structure)):
1.**Migrate `getUserFields` and/or `additionalSignupFields` in the `main.wasp` file to the new `userSignupFields` field.**
If you are not using them, you can skip this step.
In Wasp 0.11.X, you could define a `getUserFieldsFn` to specify extra fields that would get saved to the `User` when using Google or GitHub to sign up.
You could also define `additionalSignupFields` to specify extra fields for the Email or Username & Password signup .
In 0.12.X, we unified these two concepts into the `userSignupFields` field.
<details>
<summary>Migration for <EmailPill/> and <UsernameAndPasswordPill/></summary>
First, move the value of `auth.signup.additionalFields` to `auth.methods.{method}.userSignupFields` in the `main.wasp` file.
`{method}` depends on the auth method you are using. For example, if you are using the email auth method, you should move the `auth.signup.additionalFields` to `auth.methods.email.userSignupFields`.
To finish, update the JS/TS implementation to use the `defineUserSignupFields` from `wasp/server/auth` instead of `defineAdditionalSignupFields` from `@wasp/auth/index.js`.
<Tabs>
<TabItemvalue="before"label="Before">
```wasp title="main.wasp"
app crudTesting {
// ...
auth: {
userEntity: User,
methods: {
email: {},
},
onAuthFailedRedirectTo: "/login",
// highlight-start
signup: {
additionalFields: import { fields } from "@server/auth/signup.js",
},
// highlight-end
},
}
```
```ts title="src/server/auth/signup.ts"
// highlight-next-line
import { defineAdditionalSignupFields } from '@wasp/auth/index.js'
throw new Error('Address must be at least 5 characters long')
}
return address
},
})
```
</TabItem>
<TabItemvalue="after"label="After">
```wasp title="main.wasp"
app crudTesting {
// ...
auth: {
userEntity: User,
methods: {
email: {
// highlight-next-line
userSignupFields: import { fields } from "@src/server/auth/signup.js",
},
},
onAuthFailedRedirectTo: "/login",
},
}
```
```ts title="src/server/auth/signup.ts"
// highlight-next-line
import { defineUserSignupFields } from 'wasp/server/auth'
// highlight-next-line
export const fields = defineUserSignupFields({
address: async (data) => {
const address = data.address
if (typeof address !== 'string') {
throw new Error('Address is required')
}
if (address.length <5){
throw new Error('Address must be at least 5 characters long')
}
return address
},
})
```
Read more about the `userSignupFields` function [here](/auth/overview.md#1-defining-extra-fields).
</TabItem>
</Tabs>
</details>
<details>
<summary>Migration for <GithubPill/> and <GooglePill/></summary>
First, move the value of `auth.methods.{method}.getUserFieldsFn` to `auth.methods.{method}.userSignupFields` in the `main.wasp` file.
`{method}` depends on the auth method you are using. For example, if you are using Google auth, you should move the `auth.methods.google.getUserFieldsFn` to `auth.methods.google.userSignupFields`.
To finish, update the JS/TS implementation to use the `defineUserSignupFields` from `wasp/server/auth` and modify the code to return the fields in the format that `defineUserSignupFields` expects.
<Tabs>
<TabItemvalue="before"label="Before">
```wasp title="main.wasp"
app crudTesting {
// ...
auth: {
userEntity: User,
methods: {
google: {
// highlight-next-line
getUserFieldsFn: import { getUserFields } from "@server/auth/google.js"
},
},
onAuthFailedRedirectTo: "/login",
},
}
```
```ts title="src/server/auth/google.ts"
// highlight-next-line
import type { GetUserFieldsFn } from '@wasp/types'
You should see the new `Auth`, `AuthIdentity` and `Session` tables in your database. You can use the `wasp db studio` command to open the database in a GUI and verify the tables are there. At the moment, they will be empty.
1.**Do the data migration** (move existing users from the old auth system to the new one by filling the new auth tables in the database with their data):
Below we prepared [examples of migration functions](#example-data-migration-functions) for each of the auth methods, for you to use as a starting point.
They should be fine to use as-is, meaning you can just copy them and they are likely to work out of the box for typical use cases, but you can also modify them to your needs.
1.**Run the data migration function(s)** on the local development database by running:
```bash
wasp db seed
```
If you added multiple migration functions, you can pick which one to run by selecting it from the list. You will want to run all of them.
This should be it, you can now run `wasp db studio` again and verify that there is now relevant data in the new auth tables (`Auth` and `AuthIdentity`; `Session` should still be empty for now).
1.**Verify that the basic auth functionality works** by running `wasp start` and successfully signing up / logging in with each of the auth methods.
1.**Update your JS/TS code** to work correctly with the new auth.
You might want to use the new auth helper functions to get the `email` or `username` from a user object. For example, `user.username` might not work anymore for you, since the `username` obtained by the Username & Password auth method isn't stored on the `User` entity anymore (unless you are explicitly storing something into `user.username`, e.g. via `userSignupFields` for a social auth method like Github). Same goes for `email` from Email auth method.
Instead, you can now use `getUsername(user)` to get the username obtained from Username & Password auth method, or `getEmail(user)` to get the email obtained from Email auth method.
Read more about the helpers in the [Auth Entities - Accessing the Auth Fields](auth/entities#accessing-the-auth-fields) section.
After successfully performing migration locally so far, and verifying that your app works as expected, it is time to also migrate our deployed app.
Before migrating your production (deployed) app, we advise you to back up your production database in case something goes wrong. Also, besides testing it in development, it's good to test the migration in a staging environment if you have one.
Between these two steps, so after successfully deploying the new code to production and before migrating the production database data, your app will not be working completely: new users will be able to sign up, but existing users won't be able to log in, and already logged in users will be logged out. Once you do the second step, migrating the production database data, it will all be back to normal.
You will likely want to keep the time between the two steps as short as you can (but not so short that you start doing step two before step one has finished). Make sure you know exactly what each step involves before doing them for real to eliminate any surprises. Especially the second step, which is a bit more complex.
We wrote instructions on how to do it for **Fly.io** deployments here: https://github.com/wasp-lang/wasp/issues/1464 . The instructions should be similar for other deployment providers: setting up some sort of an SSH tunnel from your local machine to the production database and running your data migrations functions locally (using `wasp db seed`) with `DATABASE_URL` pointing to the production database.
- This means any fields that were required by Wasp for authentication, like `email`, `password`, `isEmailVerified`, `emailVerificationSentAt`, `passwordResetSentAt`, `username`, etc.
1. In `main.wasp` file, remove the `externalAuthEntity` field from the `app.auth` and also remove the whole `SocialLogin` entity if you used Google or GitHub auth.
1. You can now delete the data migration function(s) you implemented earlier (e.g. in `src/migrateToNewAuth.ts`) and also the corresponding entries in the `app.db.seeds` field in `main.wasp` file.
The database migrations will automatically run on successful deployment of the server and delete the now redundant auth-related `User` columns from the database.
The migration functions provided below are written with the typical use cases in mind and you can use them as-is. If your setup requires additional logic, you can use them as a good starting point and modify them to your needs.
:::caution Users will need to migrate their password
There is a breaking change between the old and the new auth in the way the password is hashed. This means that users will need to migrate their password after the migration, as the old password will no longer work.
Since the only way users using username and password as a login method can verify their identity is by providing both their username and password (there is no email or any other info, unless you asked for it and stored it explicitly), we need to provide them a way to exchange their old password for a new password. One way to handle this is to inform them about the need to migrate their password (on the login page) and provide a custom page to migrate the password.
:::
<details>
<summary>
Steps to create a custom page for migrating the password
</summary>
1. You will need to install the `secure-password` and `sodium-native` packages to use the old hashing algorithm:
:::caution Users will need to reset their password
There is a breaking change between the old and the new auth in the way the password is hashed. This means that users will need to reset their password after the migration, as the old password will no longer work.
It would be best to notify your users about this change and put a notice on your login page to **request a password reset**.