Skip to content
Shop

CommunityJoin Our PatreonDonate

Sponsored Ads

Sponsored Ads

Tauri Authentication

September 26, 2024

Add authentication to your app. Based on Tauri CRUD app.

What you will need:

Create a new Tauri App

Create a new tauri app and install dependencies

bash
nvm use 18.18.0
yarn create tauri-app --rc
cd tauri-app
yarn add pinia
yarn run tauri add store
yarn add vue-router
yarn

Basic Folder Structure

Some files and folders are not shown for simplicity.

app_name/
  src/
    main.js
    /components
      Nav.vue
      Home.vue
      Login.vue
      Register.vue
  stores/
    store.js

Configuration

Set up some configuration for pinia and vue-router.

js
import { createApp } from "vue";
import { createMemoryHistory, createRouter, useRouter } from 'vue-router'
import { createPinia } from 'pinia'
import App from "./App.vue";
import Home from './components/Home.vue'
import Login from './components/Login.vue'
import Register from './components/Register.vue'
import { dataStore } from "../stores/store";

const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
const store = dataStore();

const routes = [
    { name:'Home', path: '/', component: Home },
    { name: 'Login', path: '/login', component: Login },
    { name:'Register' ,path: '/register', component: Register },
]
const router = createRouter({
    history: createMemoryHistory(),
    routes,
})

router.beforeEach((to) => {
    if (!store.loggedIn && to.name !=='Login' && to.name !=='Register'){
        return '/login'
    }
  })

app.use(router)

app.mount("#app");
javascript
import { defineStore } from "pinia";
import { Store } from "@tauri-apps/plugin-store";

export const dataStore = defineStore("dataStore", {
  state: () => {
    return {
      db: new Store("store.bin"),
      users: [],
      loggedIn: false,
    }
  },
  getters: {
    //
  },
  actions: {
    //
  }
});

The Code

All components live in /components/.

You will need to click "Create Database" in order to create a new database or the app will error.

vue
<script setup>
import { ref, onMounted } from "vue";
import { dataStore } from "../../stores/store";
import { useRouter } from 'vue-router'

const store = dataStore();
const router = useRouter();
const user_form = ref({})
const all_users = ref([])
const showData = ref(false)

async function createUser(){
    all_users.value.push(
        {
            id: all_users.value.length + 1,
            email: user_form.value.email,
            password: user_form.value.password,
        }
    )
    await store.db.set('users', all_users.value)
    await store.db.save()
    setStatusMessage("User created successfully")
    clearForm()
    router.push('/login')
    getAllUsers()
}

async function getAllUsers(){
    all_users.value = await store.db.get('users')
}

function clearForm() {
    document.getElementById("new-user-form").reset()
    user_form.value = {}
}

function setStatusMessage(msg) {
    document.getElementById("status-message").classList.remove("hidden")
    setTimeout(() => {
        document.getElementById("status-message").classList.add("hidden")
    }, 5000)
    document.getElementById("status-message").innerHTML = msg
}

// Left here if you need this. If you get an error, it may be because you haven't created the database.
async function createUserDatabase() {
    await store.db.set('users', []);
}
// Left here if you need this.
async function deleteUserDatabase() {
    await store.set('users', [])
    setStatusMessage('Deleted All users in the DB')
    getAllUsers()
}

onMounted(() => {
  getAllUsers()
})

const name = ref("Register");

</script>

<template>
    <div class="h-screen p-20 container mx-auto w-full bg-zinc-100 dark:bg-zinc-800 dark:text-white">

    <form class="rounded-2xl bg-white dark:bg-zinc-900 p-20 mx-auto space-y-4" id="new-user-form" @submit.prevent="createUser()">
        <h2 class="text-4xl">{{name}}</h2>
        <div>
          <button @click.prevent="createUserDatabase()">Create Database</button>
          <button @click.prevent="deleteUserDatabase()" class="ml-2">Delete User Database</button>
        </div>
        <div>
          <label for="email">Email</label><br>
          <input class="w-full mt-2 border p-2 rounded-lg dark:bg-zinc-800 dark:text-white bg-zinc-100" v-model="user_form.email" name="email">
        </div>
        <div>
            <label for="password">Password</label><br>
          <input class="w-full mt-2 border p-2 rounded-lg dark:bg-zinc-800 dark:text-white bg-zinc-100" v-model="user_form.password" name="password">
        </div>
        <input type="submit" class="bg-blue-500 text-white py-2 px-4 rounded-lg font-semibold"><br>
        <button @click.prevent="showData=!showData" class="bg-black text-white p-1 text-xs px-2 rounded-md">Toggle Data</button>
        <p v-if="showData" class="mt-2 dark:bg-zinc-800 dark:text-white p-2 rounded-lg">{{all_users}}</p>
    </form>

    </div>
  
</template>
vue
<script setup>
import { ref, onMounted } from "vue";
import { dataStore } from "../../stores/store";
import { useRouter } from 'vue-router'

const store = dataStore();
const router = useRouter();
const user_form = ref({})
const all_users = ref([])
const showData = ref(false)
const retrieved = ref()

async function retrieveUser(){
    const val = await store.db.get('users')
    const user = val.find(obj=> obj['email'] === user_form.value.email && obj['password'] === user_form.value.password)
    if (user!=null){
        setStatusMessage(`Retrieved ${user.email}`)
        retrieved.value = user
        store.loggedIn = true
        router.push('/')
        return user
    }else{
        setStatusMessage("User doesn't exist")
    }
}

async function getAllUsers(){
    all_users.value = await store.db.get('users')
}

function clearForm() {
    document.getElementById("new-user-form").reset()
    user_form.value = {}
}

function setStatusMessage(msg) {
    document.getElementById("status-message").classList.remove("hidden")
    setTimeout(() => {
        document.getElementById("status-message").classList.add("hidden")
    }, 5000)
    document.getElementById("status-message").innerHTML = msg
}

onMounted(() => {
    getAllUsers()
})

const name = ref("Login");

</script>

<template>
    <div class="h-screen p-20 container mx-auto w-full bg-zinc-100 dark:bg-zinc-800 dark:text-white">
    <form class="rounded-2xl bg-white dark:bg-zinc-900 p-20 mx-auto space-y-4" id="new-user-form" @submit.prevent="retrieveUser()">
        <h2 class="text-4xl">{{name}}</h2>
        <div>
        <label for="email">Email</label><br>
        <input spellcheck="false" class="w-full mt-2 border p-2 rounded-lg dark:bg-zinc-800 dark:text-white bg-zinc-100" v-model="user_form.email" name="email">
        </div>
        <div>
            <label for="password">Password</label><br>
        <input spellcheck="false" class="w-full mt-2 border p-2 rounded-lg dark:bg-zinc-800 dark:text-white bg-zinc-100" v-model="user_form.password" name="password">
        </div>
        {{retrieved}}
        <input type="submit" class="bg-blue-500 text-white px-4 py-2 rounded-lg font-semibold"><br>
        <button @click.prevent="showData=!showData" class="bg-black text-white p-1 text-xs px-2 rounded-md">Toggle Data</button>
        <p v-if="showData" class="mt-2 dark:bg-zinc-800 dark:text-white p-2 rounded-lg">{{user_form}}</p>
    </form>
    </div>
  
</template>
html
<script setup>
import { ref } from "vue";
import { dataStore } from "../../stores/store";
const store = dataStore();
</script>

<template>
  <div class="bg-white dark:bg-zinc-900 dark:text-white sticky top-0 z-50 ">
    <nav class="p-4 border-b-2 border-zinc-200">
      <ul class="flex items-center justify-start">
        <li>
          <router-link to="/">
            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-list"
              viewBox="0 0 16 16">
              <path fill-rule="evenodd"
                d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z">
              </path>
            </svg>
          </router-link>
        </li>
        <li>
          <router-link to="/"><img src="/up_dark.png" class="ml-2 w-8 h-8 logo vite" alt="Vite logo" />
          </router-link>
        </li>
        <li class="ml-auto">
          <p id="status-message" class="hidden rounded-lg bg-yellow-200 border border-yellow-800 text-yellow-800 p-2">
            status message</p>
        </li>

        <li v-if="store.loggedIn == true" @click="store.loggedIn = false" class="ml-auto flex items-center">
          <span class="ml-2"><router-link to="/login" class="px-5 p-[.2rem] bg-zinc-200 dark:bg-zinc-800 flex items-center rounded-full">
              Logout
            </router-link></span>
        </li>

        <li v-if="store.loggedIn == false" class="ml-auto flex items-center">
          <span class="ml-2"><router-link to="/login" class="px-5 p-[.2rem] bg-zinc-200 dark:bg-zinc-800 flex items-center rounded-full">
              Login
            </router-link></span>
        </li>

        <li v-if="store.loggedIn == false" class="ml-4 flex items-center">
          <span class="ml-2"><router-link to="/register"
              class="px-5 p-[.2rem] bg-zinc-200 dark:bg-zinc-800 flex items-center rounded-full">
              Register
            </router-link></span>
        </li>
      </ul>
    </nav>
  </div>
</template>
html
<script setup>
import { ref } from "vue";

const name = ref("Home");

</script>

<template>

   <h1>{{name}}</h1> 
  
</template>

Test the App

yarn tauri dev

Build the App for Release

yarn tauri build