diff --git a/.lift/ignoreFiles b/.lift/ignoreFiles deleted file mode 100644 index 1069ffa8e..000000000 --- a/.lift/ignoreFiles +++ /dev/null @@ -1,3 +0,0 @@ -**/test/** -**/*.min.js -examples/** diff --git a/docs/docs/guides/tutorials/nextjs.mdx b/docs/docs/guides/tutorials/nextjs.mdx new file mode 100644 index 000000000..1e3c7302e --- /dev/null +++ b/docs/docs/guides/tutorials/nextjs.mdx @@ -0,0 +1,774 @@ +--- +title: Next.js and Hanko Tutorial +sidebar_label: Next.js +keywords: [next, next.js] +--- + +# Using Hanko for a Todo app with Next.js 13 and Prisma + +In this tutorial, you’ll learn how to build a Todo app with the Next.js 13 popular “App Router” structure and understand some of the most important changes that come with it. We will build a fully functional todo app, handling the creation, updating when completed and the option to delete the todos. + +## Let’s set it up + +At Hanko, we understand that finding the right stack for the project is a big step. In this guide, we will bring Next.js as the main character of the project, we will test the Client vs Server Components. For the style, we will use Tailwind CSS. We will use Hanko for the login and registration, user management and logout. Prisma will handle the storage. + +### Initialize the Next.js app + +To create a new Next.js app, we can use the `create-next-app` or `create-next-app@latest` command-line tool followed by the name of your choice for the app. Open your terminal in Visual Studio Code and run the following command: + +```shell +npx create-next-app@latest todo-nextjs-hanko + +Then you’ll be asked some prompts on what you will use for the app. The project configuration options should look something like this: + +![Pre-config Next.js prompts](/img/next-tutorial/next-config.png) + +The above choices will create a new Next.js app with the chosen name, all the required dependencies for this project will also be installed. + +#### Understanding the project structure + +When using the version 13 of Next.js, we have the option to work with the App Router directory instead of the Pages Router, for a quick summary we could say that: + +- The new directory named “app” is replacing “pages” +- “page.tsx|page.jsx” is the new “index.tsx|index.jsx” +- “layout.tsx” is the new “\_app.tsx” +- Everything is a Server Component unless you make it a Client Component using the “use client” directive at the top of the file. +- API Routes are now Server Components or Route Handlers (... More info on how this is very important) + +Remove unnecessary files, such as logos, icons, etc. If you are going to use Tailwind CSS make sure to bring your desired configuration to the `tailwind.config.ts` file, defining your color palette, fonts, breakpoints, ect. + +ℹ️ For more information about the App Router of Next.js click [here](https://nextjs.org/docs). + +### Setting up Prisma + +Install the Prisma CLI as a development dependency in the project: + +```shell npm2yarn +$ npm install prisma --save-dev +``` + +Set up Prisma with the init command of the Prisma CLI: + +```shell +npx prisma init --datasource-provider sqlite + +This creates a new `prisma` directory with your Prisma schema file and configures SQLite as your database. Once we also create the "Todo" model, the Prisma schema file should look like this: + +``` +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "sqlite" + url = env("DATABASE_URL") +} + +model Todo { + + id String @id @default(uuid()) + title String + complete Boolean + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} +``` + +At this point, you have a Prisma schema but no database yet. Run the following command in your terminal to create the SQLite database and the Todo table: + +``` +npx prisma migrate dev --name init +``` + +This command did two things: + +1. It creates a new SQL migration file for this migration in the `prisma/migrations` directory. +2. It runs the SQL migration file against the database. + +Because the SQLite database file didn't exist before, the command also created it inside the `prisma` directory with the name `dev.db` as defined via the environment variable in the `.env` file. + +To prevent problems when instantiating PrismaClient, on the Prisma Docs there’s a [section](https://www.prisma.io/docs/guides/other/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) dedicated to the best practice to do it. Let’s try it by creating a `db.ts` file in the root of the app and add the following code inside: + +```js +import { PrismaClient } from "@prisma/client"; + +const globalForPrisma = globalThis as unknown as { + prisma: PrismaClient | undefined; +}; + +export const prisma = globalForPrisma.prisma ?? new PrismaClient(); + +if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; +``` + +ℹ️ For more information about Prisma integration click [here](https://www.prisma.io/docs/getting-started). + +## Building the user interface + +The goal is to build a simple "todo app" with a nice login to protect the todos, for this we will only need two pages: + +- The login page where the Hanko-auth component will play its part in handling authentication. +- The todo page where all the todos will be displayed. + +### App structure + +In the App Router directory, the `page.tsx` is like the new `index.tsx`, which means that this name will play an important role when creating a new route. You can define a page by exporting a component from a `page.tsx` file. + +Now you can update the `page.tsx` file to display "Hello World" as done below. + +```js +export default function Home() { + return ( +
+

Hello World

+
+ ); +} +``` + +We will get back to it later to add a nice login with Hanko. + +### The Todo page + +We will style this page using Tailwind CSS classes to create a centered container to display the todos. We need a form with an input to create the new todos, and every todo element will have a checkbox and a delete button. Inside the `app` directory, create a new `todo` folder with a `page.tsx` file inside of it. Use the code below as the `todo/page.tsx` contents: + +```js +export default function Todo() { + return ( +
+
+

My to dos

+
+
+ + +
+
+ +
+
+ ); +} +``` + +ℹ️ For a better understanding of the Tailwind CSS classes click [here](https://tailwindcomponents.com/cheatsheet/). + +## Todos in the making + +To make our app functional, we need to be able to create a new todo, then check the todo once it’s completed and finally be able to remove a single todo from the list. + +### API Routes in Next.js 13 + +What we know as API Routes are replaced by Route Handlers and they are defined in a `route.ts|js` file inside the `app` directory. Read more about the Route Handlers in the [Next.js Docs](https://nextjs.org/docs/app/building-your-application/routing/route-handlers). + +Inside the `app` directory create an `api` folder. We will group our Route Handlers as follows: one directory `todo` with a `route.tsx` which will contain the `POST` HTTP method handler for creating a new todo, and in that same directory we will use a dynamic route to `GET` and `DELETE` todos. Should look like the following example: + +``` +api +└── todo + ├── [id] + │ └── route.ts + └── route.ts +``` + +### New Todo + +This is a good moment to start breaking it down into components, let’s first create a `components` folder at the root directory, then create a `components/todos/NewTodo.tsx` file and use the following as its contents: + +```js +"use client"; +import { useState } from "react"; +import { useRouter } from "next/navigation"; + +export const NewTodo = () => { + const [newItem, setNewItem] = useState(""); + + const router = useRouter(); + const create = async (e: React.SyntheticEvent) => { + e.preventDefault(); + await fetch(`/api/todo`, { + method: "POST", + credentials: "include", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + title: newItem, + }), + }); + + router.refresh(); + setNewItem(""); + }; + return ( +
+
+ setNewItem(e.target.value)} + placeholder="New todo" + className=" border border-slate-400 rounded-full flex-1 py-1 px-2 outline-none focus-within:border-slate-100 bg-slate-50 focus-within:bg-slate-100 placeholder:text-slate-300" + required + /> + +
+
+ ); +}; +``` + +This is a good example of where to use the "use client" directive since we are using `useState()` and subscribing to interactive events. + +This is how we call Prisma to create the todo inside the `api/todo/route.ts` Route Handler: + +```js +import { NextResponse } from "next/server"; +import { prisma } from "@/db"; + +export async function POST(req: Request) { + const { title } = await req.json(); + + await prisma.todo.create({ + data: { title, complete: false }, + }); + + return NextResponse.json({ message: "Created Todo" }, { status: 200 }); +} +``` + +By default, Next.js uses Server Components, thanks to that we can now call Prisma from the `todo/page.tsx` file to get all our todos, then we pass them to our `components/todos/TodoItem.tsx` file to be displayed. This is how the `todo/page.tsx` should look after our changes: + +```js +import { NewTodo } from "@/components/todos/NewTodo"; +import { TodoItem } from "@/components/todos/TodoItem"; +import { prisma } from "@/db"; + +export default async function Todo() { + const todos = await prisma.todo.findMany(); + + return ( +
+
+

My to dos

+ +
    + +
+
+
+ ); +} +``` + +🚨 Client Components themselves cannot be async functions ([official FAQ](https://nextjs.org/docs/messages/no-async-client-component)). Prisma will break the app if you try to call it inside a Client Component. + +### Update and Delete todo by ID + +In the next step, we need a way to handle marking a todo as completed and to handle the deletion of a todo. Accordingly, we create `update` and `delete` functions that fetch our dynamic route. This would be the `components/todos/TodoItem.tsx` file: + +```js +"use client"; +import { useRouter } from "next/navigation"; +import { Todo } from "@prisma/client"; + +export const TodoItem = ({ todos }: { todos: Todo[] }) => { + const router = useRouter(); + const update = async (todo: Todo) => { + await fetch(`/api/todo/${todo.id}`, { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + completed: !todo.complete, + }), + }); + router.refresh(); + }; + + const deleteTodo = async (todo: Todo) => { + await fetch(`/api/todo/${todo.id}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + id: todo.id, + }), + }); + + router.refresh(); + }; + return ( + <> + {todos.map((todo) => { + return ( +
  • + + update(todo)} + className="peer cursor-pointer accent-slate-300 " + /> + + + +
  • + ); + })} + + ); +}; +``` + +Add the following code inside the `api/todo/[id]/route.tsx` Route Handler: + +```js +import { NextResponse } from "next/server"; +import { prisma } from "@/db"; + +export async function PATCH( + req: Request, + { params: { id } }: { params: { id: string } } +) { + const { completed } = await req.json(); + + await prisma.todo.update({ + where: { + id: id, + }, + data: { + complete: completed, + }, + }); + return NextResponse.json({ message: "Updated" }, { status: 200 }); +} + +export async function DELETE(req: Request) { + const { id } = await req.json(); + + await prisma.todo.delete({ + where: { + id: id, + }, + }); + return NextResponse.json({ message: "Deleted Item" }, { status: 200 }); +} +``` + +ℹ️ For more information on the Prisma Client Api click [here](https://www.prisma.io/docs/reference/api-reference/prisma-client-reference). + +## Authentication with Hanko + +Now is time to start working on the security. + +### Hanko Cloud setup + +Visit [Hanko Cloud](https://cloud.hanko.io/login) and create an account. Then create an organization to manage your Hanko project. + +![Hanko Cloud Organization](/img/next-tutorial/cloud-organization.png) + +Then create a new project and set the App URL to your development URL (example: http://localhost:3000): + +![Hanko Cloud Project](/img/next-tutorial/new-project.png) + +And that’s all! Now you can always return to your Hanko Cloud dashboard to see your API URL and other insights about your project, you can also change the app URL in the settings, so that once you want to move from "development" to "production", you can change it to a proper domain/URL. Take the time to discover all the features. + +![Hanko Cloud dashboard](/img/next-tutorial/dashboard.png) + +### Adding Hanko to the Next.js app + +Let’s bring Hanko to the game by installing the `@teamhanko/hanko-elements` package running the code below: + +```shell npm2yarn +npm install @teamhanko/hanko-elements +``` + +First, let’s update our "Home" page and rename the function to "Login". Import the register function from `@teamhanko/hanko-elements`, and call the function with the Hanko API URL as an argument to register the ``. Now include it in your JSX: + +```js +"use client"; +import { useEffect } from "react"; +import { register } from "@teamhanko/hanko-elements"; + +const hankoApi = "YOUR_HANKO_API_URL"; +export default function Login() { + useEffect(() => { + // + register(hankoApi ?? "").catch((error) => { + console.log(error); + }); + }, []); + + return ( +
    + +
    + ); +} +``` + +The code snippet above should display the Hanko authentication component: + +![Hanko Authentication component](/img/next-tutorial/hanko-auth.png) + +The `` component offers a page for managing email addresses and passkeys. Let's create a profile button component by creating a file `components/Profile.tsx` and use the following code as its content: + +```js +"use client"; +import { useEffect, useState } from "react"; +import { register } from "@teamhanko/hanko-elements"; + +const hankoApi = "YOUR_HANKO_API_URL"; + +export const Profile = () => { + const [openState, setOpenState] = useState(false); + + useEffect(() => { + register(hankoApi ?? "").catch((error) => { + console.log(error); + }); + }, []); + + const openProfile = () => { + setOpenState(!openState); + }; + + return ( + <> + + {openState && ( +
    +
    + +
    +
    + )} + + ); +}; +``` + +It should look like this: + +![Hanko Profile Component](/img/next-tutorial/hanko-profile.png) + +Now let’s use `@teamhanko/hanko-elements` to manage user logouts by creating a logout button component. Create a file `components/Logout.tsx` and use the following as its content: + +```js +"use client"; +import { useState, useEffect, useCallback } from "react"; +import { useRouter } from "next/navigation"; +import { Hanko } from "@teamhanko/hanko-elements"; + +const hankoApi = "YOUR_HANKO_API_URL"; + +export const Logout = () => { + const router = useRouter(); + const [hanko, setHanko] = useState(); + + useEffect(() => { + import("@teamhanko/hanko-elements").then(({ Hanko }) => + setHanko(new Hanko(hankoApi ?? "")) + ); + }, []); + + const logout = () => { + hanko?.user + .logout() + .then(() => { + router.push("/"); + router.refresh(); + return; + }) + .catch((error) => { + console.log(error); + }); + }; + return ( + <> + + + ); +}; +``` + +When a user logs out, a specific event is triggered that you can subscribe to, like redirecting to a specific page after logout: + +```js +const renewSession = useCallback(() => { + router.replace("/"); +}, [router]); + +useEffect( + () => + hanko?.onSessionExpired(() => { + renewSession(); + }), + + [hanko, renewSession] +); +``` + +ℹ️ For more information about all the events that you can "listen" from the Hanko client click [here](https://github.com/teamhanko/hanko/blob/main/frontend/elements/README.md#events). + +ℹ️ You can also find information on how to customize Hanko Components by clicking [here](https://github.com/teamhanko/hanko/blob/main/frontend/elements/README.md#ui-customization). + +## Verifying JWT with jose library + +Hanko issues a cookie after a successful login. The value of this cookie is a JWT and to secure our app we still need to verify the JWT. + +> **What are JWTs?** > _A JSON Web Token (JWT) is a compact and self-contained way for transmitting information between parties as a JSON object in a secure way. The purpose of a JWT is to ensure the authenticity of the data._ + +Hanko handles the authentication and signing of the JWT. On successful authentication with Hanko a cookie, which contains said JWT as its value, is set. We don’t really need to know a lot about JWTs, but it’s worth getting familiar with the parts of a JWT (header, payload and signature), and with what a [JWKS](https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-key-sets) is. For more information you can visit [JWT.io](https://jwt.io/). + +To verify the JWT we need to install the `jose` package: + +```shell npm2yarn +npm install jose + +`jose` is a JavaScript module that supports JWT and provides functionality for signing and verifying tokens. + +ℹ️ For more information about `jose` click [here](https://www.npmjs.com/package/jose). + +### Middleware + +Create a new file `middleware.tsx` in the root of your project and use the following code: + +```js +import * as jose from "jose"; +import { NextRequest } from "next/server"; + +const hankoApi = "YOUR_HANKO_API_URL"; + +export default async function middleware(req: NextRequest) { + const token = req.cookies.get("hanko")?.value; + + const JWKS = jose.createRemoteJWKSet( + new URL(`${hankoApi}/.well-known/jwks.json`) + ); + + try { + const verifiedJWT = await jose.jwtVerify(token, JWKS); + console.log(verifiedJWT); + } catch { + return NextResponse.redirect(new URL("/", req.url)); + } +} +``` + +To verify the JWT we need the token and the JWKS. We get the token from the "hanko" cookie, and then we obtain the JSON Web Key Set (JWKS) calling the `createRemoteJWKSet` function from jose. Then we call `await jose.jwtVerify(token, JWKS)`. If the token can be verified, then the promise returned from the function resolves to a decoded token. If it cannot be verified, then the promise rejects and we can catch the error and handle it appropriately, e.g. by redirecting the user to the login/home page. If you console.log the const `verifiedJWT` you should see the decoded token showing the payload, the protectedHeader and the key. Inside the key, you should be able to see a "true" if it’s verified. + +ℹ️ For more information about Next.js Middleware click [here](https://nextjs.org/docs/app/building-your-application/routing/middleware#conditional-statements). + +### Securing the application and redirecting + +To prevent unauthorized users from getting access to private user data, we can add the paths to be protected in the Middleware configuration. Following the example on the Next.js Docs about the [middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware#example), copy the following code to the bottom of your `middleware.tsx` file: + +```js +export const config = { + matcher: ["/todo"], +}; +``` + +Update the `Login` page to subscribe to the events of the Hanko client and redirect to the `Todo` page after a successful login: + +```js +"use client"; +import { useEffect, useState, useCallback } from "react"; +import { useRouter } from "next/navigation"; +import { register } from "@teamhanko/hanko-elements"; + +const hankoApi = "YOUR_HANKO_API_URL"; +export default function Login() { + const router = useRouter(); + const [hanko, setHanko] = useState(); + + useEffect(() => { + import("@teamhanko/hanko-elements").then(({ Hanko }) => + setHanko(new Hanko(hankoApi ?? "")) + ); + }, []); + + const redirectAfterLogin = useCallback(() => { + router.replace("/todo"); + }, [router]); + + useEffect( + () => + hanko?.onAuthFlowCompleted(() => { + redirectAfterLogin(); + }), + [hanko, redirectAfterLogin] + ); + + useEffect(() => { + // + register(hankoApi ?? "").catch((error) => { + console.log(error); + }); + }, []); + + return ( +
    +
    + +
    +
    + ); +} + +``` + +## Time to display the right Todos + +Lastly, we should only display the todos for the user that is logged in. To do so, we need to link the todos to the correct "user ID". The first step is to update the Todo model in the `prisma schema`: + +``` +model Todo { + userId String + id String @id @default(uuid()) + title String + complete Boolean + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} +``` + +Then run the following command to create a migration: + +``` +npx prisma migrate +``` + +Or the following to push the schema changes directly to the database: + +``` +npx prisma db push +``` + +The next step is to update the `api/todo/route.tsx` file to get the user ID from the token, then create a new todo if there is a user ID: + +```js +import { NextResponse } from "next/server"; +import { cookies } from "next/headers"; +import * as jose from "jose"; +import { prisma } from "@/db"; + +export async function userId() { + const token = cookies().get("hanko")?.value; + const payload = jose.decodeJwt(token ?? ""); + + return payload.sub; +} + +export async function POST(req: Request) { + const userID = await userId(); + const { title } = await req.json(); + + if (userID) { + if (typeof title !== "string" || title.length === 0) { + throw new Error("That can't be a title"); + } + await prisma.todo.create({ + data: { title, complete: false, userId: userID ?? "" }, + }); + + return NextResponse.json({ message: "Created Todo" }, { status: 200 }); + } else { + return NextResponse.json({ error: "Not Found" }, { status: 404 }); + } +} +``` + +The final step is to update the Prisma call to fetch all the todos from the `todo/page.tsx`: + +```js +import { Logout } from "@/components/Logout"; +import { Profile } from "@/components/Profile"; +import { NewTodo } from "@/components/todos/NewTodo"; +import { TodoItem } from "@/components/todos/TodoItem"; +import { prisma } from "@/db"; +import { userId } from "../api/todo/route"; + +export default async function Todo() { + const userID = await userId(); + + const todos = await prisma.todo.findMany({ + where: { + userId: { equals: userID }, + }, + }); + + return ( +
    +
    +
    + + +
    +
    +
    +

    My to dos

    + +
      + +
    +
    +
    + ); +} +``` + +That’s all, you’ve successfully created a Todo app with Next.js, Hanko, Prisma and Tailwind CSS! diff --git a/docs/sidebars.js b/docs/sidebars.js index ee6bd7210..957dc1bcf 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -69,7 +69,7 @@ const sidebars = { { type: "category", label: "Tutorials", - items: ["guides/tutorials/php", "guides/tutorials/userData"], + items: ["guides/tutorials/php", "guides/tutorials/nextjs", "guides/tutorials/userData"], }, ], }; diff --git a/docs/static/img/next-tutorial/cloud-organization.png b/docs/static/img/next-tutorial/cloud-organization.png new file mode 100644 index 000000000..5c6386099 Binary files /dev/null and b/docs/static/img/next-tutorial/cloud-organization.png differ diff --git a/docs/static/img/next-tutorial/dashboard.png b/docs/static/img/next-tutorial/dashboard.png new file mode 100644 index 000000000..d5616cde6 Binary files /dev/null and b/docs/static/img/next-tutorial/dashboard.png differ diff --git a/docs/static/img/next-tutorial/hanko-auth.png b/docs/static/img/next-tutorial/hanko-auth.png new file mode 100644 index 000000000..b8242e580 Binary files /dev/null and b/docs/static/img/next-tutorial/hanko-auth.png differ diff --git a/docs/static/img/next-tutorial/hanko-profile.png b/docs/static/img/next-tutorial/hanko-profile.png new file mode 100644 index 000000000..221b5d544 Binary files /dev/null and b/docs/static/img/next-tutorial/hanko-profile.png differ diff --git a/docs/static/img/next-tutorial/new-project.png b/docs/static/img/next-tutorial/new-project.png new file mode 100644 index 000000000..58462d1f1 Binary files /dev/null and b/docs/static/img/next-tutorial/new-project.png differ diff --git a/docs/static/img/next-tutorial/next-config.png b/docs/static/img/next-tutorial/next-config.png new file mode 100644 index 000000000..686eff3bf Binary files /dev/null and b/docs/static/img/next-tutorial/next-config.png differ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/AccountConfig.html b/docs/static/jsdoc/hanko-frontend-sdk/AccountConfig.html index 7d7a010c1..bfb5ec3d5 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/AccountConfig.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/AccountConfig.html @@ -66,7 +66,7 @@ @@ -125,7 +125,6 @@
    Properties:
    allow_deletion - allow_signup @@ -145,6 +144,29 @@
    Properties:
    + + + + allow_signup + + + + + +boolean + + + + + + + + + + Indicates the current user is allowed to sign up. + + + @@ -245,4 +267,4 @@
    Properties:
    - + \ No newline at end of file diff --git a/docs/static/jsdoc/hanko-frontend-sdk/AuthFlowCompletedDetail.html b/docs/static/jsdoc/hanko-frontend-sdk/AuthFlowCompletedDetail.html index dd5801eed..e82a87a63 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/AuthFlowCompletedDetail.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/AuthFlowCompletedDetail.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Client.html b/docs/static/jsdoc/hanko-frontend-sdk/Client.html index 3074891e5..5e8eb24b9 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Client.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Client.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Config.html b/docs/static/jsdoc/hanko-frontend-sdk/Config.html index 85c2bd4ba..0cc887fa7 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Config.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Config.html @@ -66,7 +66,7 @@ @@ -254,7 +254,7 @@
    Properties:

    View Source - lib/Dto.ts, line 28 + lib/Dto.ts, line 29

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/ConfigClient.html b/docs/static/jsdoc/hanko-frontend-sdk/ConfigClient.html index b13e7d6d4..1e87b4c5a 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/ConfigClient.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/ConfigClient.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/ConflictError.html b/docs/static/jsdoc/hanko-frontend-sdk/ConflictError.html index 53f84529c..cdf9c9e81 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/ConflictError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/ConflictError.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Cookie.html b/docs/static/jsdoc/hanko-frontend-sdk/Cookie.html index acb019fb2..3ea21b86d 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Cookie.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Cookie.html @@ -66,7 +66,7 @@ @@ -347,7 +347,7 @@

    View Source - lib/Cookie.ts, line 57 + lib/Cookie.ts, line 66

    @@ -467,7 +467,7 @@

    View Source - lib/Cookie.ts, line 70 + lib/Cookie.ts, line 79

    @@ -504,7 +504,7 @@

    - setAuthCookie(token, secureopt) + setAuthCookie(token, options)

    @@ -538,8 +538,6 @@
    Parameters:
    Type - Attributes - @@ -566,14 +564,6 @@
    Parameters:
    - - - - - - - - @@ -586,33 +576,23 @@
    Parameters:
    - secure + options -boolean +SetAuthCookieOptions - - - <optional>
    - - - - - - - - Indicates a secure cookie should be set. Default is `true`. + Options for setting the auth cookie. @@ -660,7 +640,7 @@
    Parameters:

    View Source - lib/Cookie.ts, line 65 + lib/Cookie.ts, line 74

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/CookieOptions.html b/docs/static/jsdoc/hanko-frontend-sdk/CookieOptions.html index 736267920..53e34c9e0 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/CookieOptions.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/CookieOptions.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Credential.html b/docs/static/jsdoc/hanko-frontend-sdk/Credential.html index c475d3ff3..4359e33d6 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Credential.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Credential.html @@ -66,7 +66,7 @@ @@ -185,7 +185,7 @@
    Properties:

    View Source - lib/Dto.ts, line 71 + lib/Dto.ts, line 72

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Dispatcher.html b/docs/static/jsdoc/hanko-frontend-sdk/Dispatcher.html index 6f04c34ea..e713dd1ad 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Dispatcher.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Dispatcher.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/DispatcherOptions.html b/docs/static/jsdoc/hanko-frontend-sdk/DispatcherOptions.html index d263c3f33..06ae99971 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/DispatcherOptions.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/DispatcherOptions.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Email.html b/docs/static/jsdoc/hanko-frontend-sdk/Email.html index cb9624500..7d55e58a2 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Email.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Email.html @@ -66,7 +66,7 @@ @@ -277,7 +277,7 @@
    Properties:

    View Source - lib/Dto.ts, line 118 + lib/Dto.ts, line 119

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/EmailAddressAlreadyExistsError.html b/docs/static/jsdoc/hanko-frontend-sdk/EmailAddressAlreadyExistsError.html index 91b15b761..9fb8d5293 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/EmailAddressAlreadyExistsError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/EmailAddressAlreadyExistsError.html @@ -66,7 +66,7 @@ @@ -167,7 +167,7 @@

    View Source - lib/Errors.ts, line 240 + lib/Errors.ts, line 254

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/EmailClient.html b/docs/static/jsdoc/hanko-frontend-sdk/EmailClient.html index 9a6aa82a8..fd1b89331 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/EmailClient.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/EmailClient.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/EmailConfig.html b/docs/static/jsdoc/hanko-frontend-sdk/EmailConfig.html index 8fce5e775..3ea361970 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/EmailConfig.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/EmailConfig.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Emails.html b/docs/static/jsdoc/hanko-frontend-sdk/Emails.html index 6e04eac89..5f4edbe8c 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Emails.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Emails.html @@ -66,7 +66,7 @@ @@ -181,7 +181,7 @@

    Properties:

    View Source - lib/Dto.ts, line 129 + lib/Dto.ts, line 130

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/ForbiddenError.html b/docs/static/jsdoc/hanko-frontend-sdk/ForbiddenError.html new file mode 100644 index 000000000..5c63cddd8 --- /dev/null +++ b/docs/static/jsdoc/hanko-frontend-sdk/ForbiddenError.html @@ -0,0 +1,428 @@ + + + + + + + + ForbiddenError + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    + +
    +
    +
    +

    Class

    +

    ForbiddenError

    +
    + + + + + +
    + +
    + +

    ForbiddenError()

    + +
    A 'ForbiddenError' occurs when the user is not allowed to perform the requested action.
    + + +
    + +
    +
    + + +
    +
    +
    +
    + Constructor +
    + + + + +

    + # + + + + new ForbiddenError() + + +

    + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    + View Source + + lib/Errors.ts, line 210 + +

    + +
    + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + +
    + + +

    Extends

    + + + + + + + + + + + + + + + + + + + + +
    +

    Members

    +
    + +
    + + + + +Error + + + + +

    + # + + + cause + + + Optional + +

    + + + + + + + + +
    + + + + + + + + +
    Overrides:
    +
    + + + + + + + + + + + + + + + + + + + + + + + + +

    + View Source + + lib/Errors.ts, line 27 + +

    + +
    + + + + + +
    + +
    + + + + +string + + + + +

    + # + + + code + + +

    + + + + + + + + +
    + + + + + + + + +
    Overrides:
    +
    + + + + + + + + + + + + + + + + + + + + + + + + +

    + View Source + + lib/Errors.ts, line 22 + +

    + +
    + + + + + +
    + +
    +
    + + + + + + + +
    + +
    + + + + +
    + + + +
    +
    +
    +
    + + + + + + + \ No newline at end of file diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Hanko.html b/docs/static/jsdoc/hanko-frontend-sdk/Hanko.html index 22df6bf04..b669a1a15 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Hanko.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Hanko.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Hanko.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/Hanko.ts.html index 76c11669c..eae1dc7e9 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Hanko.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Hanko.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/HankoError.html b/docs/static/jsdoc/hanko-frontend-sdk/HankoError.html index 69f818130..b4b5645f4 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/HankoError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/HankoError.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/HankoOptions.html b/docs/static/jsdoc/hanko-frontend-sdk/HankoOptions.html index cd70067d3..93d9f01e2 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/HankoOptions.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/HankoOptions.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Headers.html b/docs/static/jsdoc/hanko-frontend-sdk/Headers.html index 1557fb2a8..205fb1d29 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Headers.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Headers.html @@ -66,7 +66,7 @@ @@ -398,7 +398,7 @@
    Parameters:

    View Source - lib/client/HttpClient.ts, line 285 + lib/client/HttpClient.ts, line 286

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/HttpClient.html b/docs/static/jsdoc/hanko-frontend-sdk/HttpClient.html index d96ebec4b..c29160ae4 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/HttpClient.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/HttpClient.html @@ -66,7 +66,7 @@ @@ -422,7 +422,7 @@
    Parameters:

    View Source - lib/client/HttpClient.ts, line 375 + lib/client/HttpClient.ts, line 376

    @@ -630,7 +630,7 @@
    Parameters:

    View Source - lib/client/HttpClient.ts, line 332 + lib/client/HttpClient.ts, line 333

    @@ -883,7 +883,7 @@
    Parameters:

    View Source - lib/client/HttpClient.ts, line 365 + lib/client/HttpClient.ts, line 366

    @@ -1136,7 +1136,7 @@
    Parameters:

    View Source - lib/client/HttpClient.ts, line 343 + lib/client/HttpClient.ts, line 344

    @@ -1370,7 +1370,7 @@
    Parameters:

    View Source - lib/client/HttpClient.ts, line 322 + lib/client/HttpClient.ts, line 323

    @@ -1563,7 +1563,7 @@
    Parameters:

    View Source - lib/client/HttpClient.ts, line 354 + lib/client/HttpClient.ts, line 355

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/HttpClientOptions.html b/docs/static/jsdoc/hanko-frontend-sdk/HttpClientOptions.html index 52a6d7e2c..b265f5182 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/HttpClientOptions.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/HttpClientOptions.html @@ -66,7 +66,7 @@ @@ -233,7 +233,7 @@
    Properties:

    View Source - lib/client/HttpClient.ts, line 303 + lib/client/HttpClient.ts, line 304

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Identity.html b/docs/static/jsdoc/hanko-frontend-sdk/Identity.html index 35d100574..045aa656a 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Identity.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Identity.html @@ -66,7 +66,7 @@ @@ -202,7 +202,7 @@
    Properties:

    View Source - lib/Dto.ts, line 157 + lib/Dto.ts, line 158

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/InvalidPasscodeError.html b/docs/static/jsdoc/hanko-frontend-sdk/InvalidPasscodeError.html index d7f4840f3..f70d88802 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/InvalidPasscodeError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/InvalidPasscodeError.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/InvalidPasswordError.html b/docs/static/jsdoc/hanko-frontend-sdk/InvalidPasswordError.html index 6824d93c3..ccbff608a 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/InvalidPasswordError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/InvalidPasswordError.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/InvalidWebauthnCredentialError.html b/docs/static/jsdoc/hanko-frontend-sdk/InvalidWebauthnCredentialError.html index bd0b6f2fa..b672b9a3d 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/InvalidWebauthnCredentialError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/InvalidWebauthnCredentialError.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Listener.html b/docs/static/jsdoc/hanko-frontend-sdk/Listener.html index d76845f5c..3c0b09325 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Listener.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Listener.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/LocalStorage.html b/docs/static/jsdoc/hanko-frontend-sdk/LocalStorage.html index c91fc005c..0019db7c8 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/LocalStorage.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/LocalStorage.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/LocalStoragePasscode.html b/docs/static/jsdoc/hanko-frontend-sdk/LocalStoragePasscode.html index 6b8e766a4..c1fa7dbc7 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/LocalStoragePasscode.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/LocalStoragePasscode.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/LocalStoragePassword.html b/docs/static/jsdoc/hanko-frontend-sdk/LocalStoragePassword.html index 2f3ca7dc6..42df4e2fd 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/LocalStoragePassword.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/LocalStoragePassword.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageSession.html b/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageSession.html index 17cda0d1f..d0325f6cd 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageSession.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageSession.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageUser.html b/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageUser.html index 579dc5194..0a28d313a 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageUser.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageUser.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageUsers.html b/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageUsers.html index 6c1608652..339abc71e 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageUsers.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageUsers.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageWebauthn.html b/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageWebauthn.html index 5029842dd..9c7356dc9 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageWebauthn.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/LocalStorageWebauthn.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/MaxNumOfEmailAddressesReachedError.html b/docs/static/jsdoc/hanko-frontend-sdk/MaxNumOfEmailAddressesReachedError.html index 006a81e21..4a24073b7 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/MaxNumOfEmailAddressesReachedError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/MaxNumOfEmailAddressesReachedError.html @@ -66,7 +66,7 @@ @@ -168,7 +168,7 @@

    View Source - lib/Errors.ts, line 226 + lib/Errors.ts, line 240

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/MaxNumOfPasscodeAttemptsReachedError.html b/docs/static/jsdoc/hanko-frontend-sdk/MaxNumOfPasscodeAttemptsReachedError.html index 266daa0ab..680dff598 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/MaxNumOfPasscodeAttemptsReachedError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/MaxNumOfPasscodeAttemptsReachedError.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/NotFoundError.html b/docs/static/jsdoc/hanko-frontend-sdk/NotFoundError.html index 01142cbb7..ede4775f1 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/NotFoundError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/NotFoundError.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Passcode.html b/docs/static/jsdoc/hanko-frontend-sdk/Passcode.html index dd967664d..90c4238b4 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Passcode.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Passcode.html @@ -66,7 +66,7 @@ @@ -208,7 +208,7 @@

    Properties:

    View Source - lib/Dto.ts, line 95 + lib/Dto.ts, line 96

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/PasscodeClient.html b/docs/static/jsdoc/hanko-frontend-sdk/PasscodeClient.html index 6fa8293d3..1ab7e4da1 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/PasscodeClient.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/PasscodeClient.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/PasscodeExpiredError.html b/docs/static/jsdoc/hanko-frontend-sdk/PasscodeExpiredError.html index 734899ca7..76c22c1c7 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/PasscodeExpiredError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/PasscodeExpiredError.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/PasscodeState.html b/docs/static/jsdoc/hanko-frontend-sdk/PasscodeState.html index a5f6c80c2..0ac53d7a2 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/PasscodeState.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/PasscodeState.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/PasswordClient.html b/docs/static/jsdoc/hanko-frontend-sdk/PasswordClient.html index b77589d91..046a37a52 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/PasswordClient.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/PasswordClient.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/PasswordConfig.html b/docs/static/jsdoc/hanko-frontend-sdk/PasswordConfig.html index 88cf36f5e..6a95c92d0 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/PasswordConfig.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/PasswordConfig.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/PasswordState.html b/docs/static/jsdoc/hanko-frontend-sdk/PasswordState.html index 0e60b3783..7bc99c6a1 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/PasswordState.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/PasswordState.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Relay.html b/docs/static/jsdoc/hanko-frontend-sdk/Relay.html index fbec79bb0..77bf0e89b 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Relay.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Relay.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/RelayOptions.html b/docs/static/jsdoc/hanko-frontend-sdk/RelayOptions.html index 194edded9..f04d845c7 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/RelayOptions.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/RelayOptions.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/RequestTimeoutError.html b/docs/static/jsdoc/hanko-frontend-sdk/RequestTimeoutError.html index d435986a9..ebaf9d9d9 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/RequestTimeoutError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/RequestTimeoutError.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Response.html b/docs/static/jsdoc/hanko-frontend-sdk/Response.html index 9a7b70b9d..4d6167679 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Response.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Response.html @@ -66,7 +66,7 @@ @@ -719,7 +719,7 @@

    View Source - lib/client/HttpClient.ts, line 293 + lib/client/HttpClient.ts, line 294

    @@ -891,7 +891,7 @@

    Parameters:

    View Source - lib/client/HttpClient.ts, line 302 + lib/client/HttpClient.ts, line 303

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Scheduler.html b/docs/static/jsdoc/hanko-frontend-sdk/Scheduler.html index 458b3daaa..ce0f58532 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Scheduler.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Scheduler.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Session.html b/docs/static/jsdoc/hanko-frontend-sdk/Session.html index 7bb08bad7..a4d944e77 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Session.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Session.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/SessionDetail.html b/docs/static/jsdoc/hanko-frontend-sdk/SessionDetail.html index f4da1db3a..b4c5f023e 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/SessionDetail.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/SessionDetail.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/SessionOptions.html b/docs/static/jsdoc/hanko-frontend-sdk/SessionOptions.html index 9dd4d3357..ac13a8840 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/SessionOptions.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/SessionOptions.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/SessionState.html b/docs/static/jsdoc/hanko-frontend-sdk/SessionState.html index 98e80f4af..f49f5de28 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/SessionState.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/SessionState.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/SessionStateOptions.html b/docs/static/jsdoc/hanko-frontend-sdk/SessionStateOptions.html index 787746c79..279476c05 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/SessionStateOptions.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/SessionStateOptions.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/SetAuthCookieOptions.html b/docs/static/jsdoc/hanko-frontend-sdk/SetAuthCookieOptions.html new file mode 100644 index 000000000..d630a9290 --- /dev/null +++ b/docs/static/jsdoc/hanko-frontend-sdk/SetAuthCookieOptions.html @@ -0,0 +1,278 @@ + + + + + + + + SetAuthCookieOptions + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    + +
    +
    +
    +

    Interface

    +

    SetAuthCookieOptions

    +
    + + + + + +
    + +
    + +

    SetAuthCookieOptions

    + + +
    + +
    +
    + + +
    Options for setting the auth cookie.
    + + + + + +
    Properties:
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    secure + + +boolean + + + + Indicates if the Secure attribute of the cookie should be set.
    expires + + +number +| + +Date +| + +undefined + + + + The expiration of the cookie.
    +
    + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    + View Source + + lib/Cookie.ts, line 50 + +

    + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + + +
    +
    +
    +
    + + + + + + + \ No newline at end of file diff --git a/docs/static/jsdoc/hanko-frontend-sdk/State.html b/docs/static/jsdoc/hanko-frontend-sdk/State.html index 76906ccf1..c86202a68 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/State.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/State.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/TechnicalError.html b/docs/static/jsdoc/hanko-frontend-sdk/TechnicalError.html index 74733d5c6..813bc5918 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/TechnicalError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/TechnicalError.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/ThirdPartyClient.html b/docs/static/jsdoc/hanko-frontend-sdk/ThirdPartyClient.html index 04582a36f..3308ccc0f 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/ThirdPartyClient.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/ThirdPartyClient.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/ThirdPartyError.html b/docs/static/jsdoc/hanko-frontend-sdk/ThirdPartyError.html index 731290496..57bdef65c 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/ThirdPartyError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/ThirdPartyError.html @@ -66,7 +66,7 @@ @@ -168,7 +168,7 @@

    View Source - lib/Errors.ts, line 255 + lib/Errors.ts, line 269

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/Throttle.html b/docs/static/jsdoc/hanko-frontend-sdk/Throttle.html index 71b11939b..af03896b0 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/Throttle.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/Throttle.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/ThrottleOptions.html b/docs/static/jsdoc/hanko-frontend-sdk/ThrottleOptions.html index 754154bce..21fd1b69c 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/ThrottleOptions.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/ThrottleOptions.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/TokenClient.html b/docs/static/jsdoc/hanko-frontend-sdk/TokenClient.html index c78632960..ce3fcf419 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/TokenClient.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/TokenClient.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/TokenFinalized.html b/docs/static/jsdoc/hanko-frontend-sdk/TokenFinalized.html index 06609aee1..020459bea 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/TokenFinalized.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/TokenFinalized.html @@ -66,7 +66,7 @@ @@ -185,7 +185,7 @@

    Properties:

    View Source - lib/Dto.ts, line 46 + lib/Dto.ts, line 47

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/TooManyRequestsError.html b/docs/static/jsdoc/hanko-frontend-sdk/TooManyRequestsError.html index 0d5117d39..c9f216586 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/TooManyRequestsError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/TooManyRequestsError.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/UnauthorizedError.html b/docs/static/jsdoc/hanko-frontend-sdk/UnauthorizedError.html index 3957807fe..79ddc2b58 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/UnauthorizedError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/UnauthorizedError.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/User.html b/docs/static/jsdoc/hanko-frontend-sdk/User.html index bc3d4c3ee..db83f2faa 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/User.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/User.html @@ -66,7 +66,7 @@ @@ -231,7 +231,7 @@
    Properties:

    View Source - lib/Dto.ts, line 78 + lib/Dto.ts, line 79

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/UserClient.html b/docs/static/jsdoc/hanko-frontend-sdk/UserClient.html index 92862a14f..13d1ef6ae 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/UserClient.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/UserClient.html @@ -66,7 +66,7 @@ @@ -448,7 +448,7 @@
    Parameters:

    View Source - lib/client/UserClient.ts, line 169 + lib/client/UserClient.ts, line 172

    @@ -624,7 +624,7 @@

    View Source - lib/client/UserClient.ts, line 193 + lib/client/UserClient.ts, line 196

    @@ -809,7 +809,7 @@

    View Source - lib/client/UserClient.ts, line 182 + lib/client/UserClient.ts, line 185

    @@ -1045,7 +1045,7 @@

    Parameters:

    View Source - lib/client/UserClient.ts, line 155 + lib/client/UserClient.ts, line 158

    @@ -1221,7 +1221,7 @@

    View Source - lib/client/UserClient.ts, line 203 + lib/client/UserClient.ts, line 206

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/UserCreated.html b/docs/static/jsdoc/hanko-frontend-sdk/UserCreated.html index 906539d56..d19eeff20 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/UserCreated.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/UserCreated.html @@ -66,7 +66,7 @@ @@ -208,7 +208,7 @@

    Properties:

    View Source - lib/Dto.ts, line 87 + lib/Dto.ts, line 88

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/UserInfo.html b/docs/static/jsdoc/hanko-frontend-sdk/UserInfo.html index eab792e0f..ef52347e0 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/UserInfo.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/UserInfo.html @@ -66,7 +66,7 @@ @@ -254,7 +254,7 @@
    Properties:

    View Source - lib/Dto.ts, line 53 + lib/Dto.ts, line 54

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/UserState.html b/docs/static/jsdoc/hanko-frontend-sdk/UserState.html index a61e63a89..2ab73f997 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/UserState.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/UserState.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/UserVerificationError.html b/docs/static/jsdoc/hanko-frontend-sdk/UserVerificationError.html index 262ddb13b..2772febb4 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/UserVerificationError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/UserVerificationError.html @@ -66,7 +66,7 @@ @@ -168,7 +168,7 @@

    View Source - lib/Errors.ts, line 211 + lib/Errors.ts, line 225

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnClient.html b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnClient.html index 6b117b469..88aead4d6 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnClient.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnClient.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnCredential.html b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnCredential.html index f27b93b3a..885f1cbf8 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnCredential.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnCredential.html @@ -66,7 +66,7 @@ @@ -398,7 +398,7 @@

    Properties:

    View Source - lib/Dto.ts, line 136 + lib/Dto.ts, line 137

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnCredentials.html b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnCredentials.html index 3315199e8..27fb7ad26 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnCredentials.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnCredentials.html @@ -66,7 +66,7 @@ @@ -181,7 +181,7 @@
    Properties:

    View Source - lib/Dto.ts, line 150 + lib/Dto.ts, line 151

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnFinalized.html b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnFinalized.html index 2973ae9f7..5e901c8f7 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnFinalized.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnFinalized.html @@ -66,7 +66,7 @@ @@ -208,7 +208,7 @@
    Properties:

    View Source - lib/Dto.ts, line 38 + lib/Dto.ts, line 39

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnRequestCancelledError.html b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnRequestCancelledError.html index 3a1179476..46ebe1186 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnRequestCancelledError.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnRequestCancelledError.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnState.html b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnState.html index b3486d7a6..7420da49f 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnState.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnState.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnSupport.html b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnSupport.html index 999f7ceec..2aee27015 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnSupport.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnSupport.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnTransports.html b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnTransports.html index 7f1d6cd85..0e6218b85 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/WebauthnTransports.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/WebauthnTransports.html @@ -66,7 +66,7 @@ @@ -181,7 +181,7 @@
    Properties:

    View Source - lib/Dto.ts, line 103 + lib/Dto.ts, line 104

    diff --git a/docs/static/jsdoc/hanko-frontend-sdk/index.html b/docs/static/jsdoc/hanko-frontend-sdk/index.html index a1428ce4b..da06863a1 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/index.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/index.html @@ -66,7 +66,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_Cookie.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_Cookie.ts.html index fea8df89e..920fb89d3 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_Cookie.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_Cookie.ts.html @@ -68,7 +68,7 @@ @@ -98,6 +98,19 @@

    lib/Cookie.ts

    cookieName: string; } +/** + * Options for setting the auth cookie. + * + * @category SDK + * @subcategory Internal + * @property {boolean} secure - Indicates if the Secure attribute of the cookie should be set. + * @property {number | Date | undefined} expires - The expiration of the cookie. + */ +interface SetAuthCookieOptions { + secure?: boolean; + expires?: number | Date | undefined; +} + /** * A class to manage cookies. * @@ -126,10 +139,13 @@

    lib/Cookie.ts

    * Stores the authentication token to the cookie. * * @param {string} token - The authentication token to be stored. - * @param {boolean=} secure - Indicates a secure cookie should be set. Default is `true`. + * @param {SetAuthCookieOptions} options - Options for setting the auth cookie. */ - setAuthCookie(token: string, secure = true) { - JSCookie.set(this.authCookieName, token, { secure }); + setAuthCookie( + token: string, + options: SetAuthCookieOptions = { secure: true }, + ) { + JSCookie.set(this.authCookieName, token, options); } /** diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_Dto.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_Dto.ts.html index 3207d00d7..105e7841f 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_Dto.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_Dto.ts.html @@ -68,7 +68,7 @@ @@ -116,9 +116,11 @@

    lib/Dto.ts

    * @category SDK * @subcategory DTO * @property {boolean} allow_deletion - Indicates the current user is allowed to delete the account. + * @property {boolean} allow_signup - Indicates the current user is allowed to sign up. */ export interface AccountConfig { allow_deletion: boolean; + allow_signup: boolean; } /** diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_Errors.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_Errors.ts.html index 315605a40..6fe41d9d7 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_Errors.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_Errors.ts.html @@ -68,7 +68,7 @@ @@ -308,6 +308,21 @@

    lib/Errors.ts

    } } +/** + * A 'ForbiddenError' occurs when the user is not allowed to perform the requested action. + * + * @category SDK + * @subcategory Errors + * @extends {HankoError} + */ +class ForbiddenError extends HankoError { + // eslint-disable-next-line require-jsdoc + constructor(cause?: Error) { + super("Forbidden error", "forbidden", cause); + Object.setPrototypeOf(this, ForbiddenError.prototype); + } +} + /** * A 'UserVerificationError' occurs when the user verification requirements * for a WebAuthn ceremony are not met. @@ -393,6 +408,7 @@

    lib/Errors.ts

    NotFoundError, TooManyRequestsError, UnauthorizedError, + ForbiddenError, UserVerificationError, MaxNumOfEmailAddressesReachedError, EmailAddressAlreadyExistsError, diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_Session.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_Session.ts.html index d452e39f9..514d0ea0b 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_Session.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_Session.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_Throttle.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_Throttle.ts.html index 8632af8a4..57451acca 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_Throttle.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_Throttle.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_WebauthnSupport.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_WebauthnSupport.ts.html index ea258b305..0930429b4 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_WebauthnSupport.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_WebauthnSupport.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_Client.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_Client.ts.html index 4fa87f89a..81ad37dd6 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_Client.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_Client.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_ConfigClient.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_ConfigClient.ts.html index 7767f4209..fae4c3fba 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_ConfigClient.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_ConfigClient.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_EmailClient.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_EmailClient.ts.html index 86270781c..9ae7910b3 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_EmailClient.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_EmailClient.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_HttpClient.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_HttpClient.ts.html index 23dfa255b..da0d676ef 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_HttpClient.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_HttpClient.ts.html @@ -68,7 +68,7 @@ @@ -296,14 +296,15 @@

    lib/client/HttpClient.ts

    } else if (header.startsWith("x-session-lifetime")) { expirationSeconds = parseInt( response.headers.getResponseHeader("X-Session-Lifetime"), - 10 + 10, ); } }); if (jwt) { const secure = !!this.api.match("^https://"); - this.cookie.setAuthCookie(jwt, secure); + const expires = new Date(new Date().getTime() + expirationSeconds * 1000); + this.cookie.setAuthCookie(jwt, { secure, expires }); } this.passcodeState.read().reset(userID).write(); diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_PasscodeClient.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_PasscodeClient.ts.html index c08f27113..44b76811d 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_PasscodeClient.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_PasscodeClient.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_PasswordClient.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_PasswordClient.ts.html index 0ede203e5..8bbedf225 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_PasswordClient.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_PasswordClient.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_ThirdPartyClient.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_ThirdPartyClient.ts.html index 4c3b9d2f8..606b791a5 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_ThirdPartyClient.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_ThirdPartyClient.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_TokenClient.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_TokenClient.ts.html index ca9fbd591..9841992f9 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_TokenClient.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_TokenClient.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_UserClient.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_UserClient.ts.html index 6953c798b..0b8b83d06 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_UserClient.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_UserClient.ts.html @@ -68,7 +68,7 @@ @@ -91,6 +91,7 @@

    lib/client/UserClient.ts

    NotFoundError, TechnicalError, UnauthorizedError, + ForbiddenError, } from "../Errors"; import { Client } from "./Client"; @@ -142,6 +143,8 @@

    lib/client/UserClient.ts

    if (response.status === 409) { throw new ConflictError(); + } if (response.status === 403) { + throw new ForbiddenError(); } else if (!response.ok) { throw new TechnicalError(); } diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_WebauthnClient.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_WebauthnClient.ts.html index 06551168b..f8c4cc74d 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_client_WebauthnClient.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_client_WebauthnClient.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_events_CustomEvents.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_events_CustomEvents.ts.html index 085178d22..9a79d1b18 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_events_CustomEvents.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_events_CustomEvents.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Dispatcher.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Dispatcher.ts.html index cb6ee03bb..3f01503cf 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Dispatcher.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Dispatcher.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Listener.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Listener.ts.html index 640d4493f..2ea7cf815 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Listener.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Listener.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Relay.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Relay.ts.html index a4e9197de..353393cc6 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Relay.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Relay.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Scheduler.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Scheduler.ts.html index 4776a2087..29ca36d24 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Scheduler.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_events_Scheduler.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_state_State.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_state_State.ts.html index 3532dc316..b48a86140 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_state_State.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_state_State.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_state_session_SessionState.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_state_session_SessionState.ts.html index ac2516183..87f0507ea 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_state_session_SessionState.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_state_session_SessionState.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_PasscodeState.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_PasscodeState.ts.html index 4caa14ee6..34676fdc1 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_PasscodeState.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_PasscodeState.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_PasswordState.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_PasswordState.ts.html index 3048e2b20..99d5258bf 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_PasswordState.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_PasswordState.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_UserState.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_UserState.ts.html index be1050b96..b6c987fb6 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_UserState.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_UserState.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_WebauthnState.ts.html b/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_WebauthnState.ts.html index 39c4f11c3..6c85102d5 100644 --- a/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_WebauthnState.ts.html +++ b/docs/static/jsdoc/hanko-frontend-sdk/lib_state_users_WebauthnState.ts.html @@ -68,7 +68,7 @@ diff --git a/docs/static/spec/admin.yaml b/docs/static/spec/admin.yaml index 27ffbdefa..34577b8e6 100644 --- a/docs/static/spec/admin.yaml +++ b/docs/static/spec/admin.yaml @@ -1,6 +1,6 @@ openapi: 3.0.0 info: - version: '0.8.0' + version: '0.8.4' title: 'Hanko Admin API' description: | ## Introduction diff --git a/docs/static/spec/public.yaml b/docs/static/spec/public.yaml index acf985ca4..04789bf70 100644 --- a/docs/static/spec/public.yaml +++ b/docs/static/spec/public.yaml @@ -1,7 +1,7 @@ openapi: 3.0.0 info: - version: '0.8.0' + version: '0.8.4' title: 'Hanko Public API' description: | ## Introduction diff --git a/frontend/elements/package.json b/frontend/elements/package.json index eedd2d2e2..1ad260daf 100644 --- a/frontend/elements/package.json +++ b/frontend/elements/package.json @@ -1,6 +1,6 @@ { "name": "@teamhanko/hanko-elements", - "version": "0.8.3", + "version": "0.8.4", "private": false, "publishConfig": { "access": "public" @@ -107,7 +107,7 @@ }, "dependencies": { "@denysvuika/preact-translate": "^0.5.0", - "@teamhanko/hanko-frontend-sdk": "^0.8.3", + "@teamhanko/hanko-frontend-sdk": "^0.8.4", "@teamhanko/preact-custom-element": "^4.2.2", "classnames": "^2.3.2", "preact": "^10.13.1" diff --git a/frontend/examples/angular/package.json b/frontend/examples/angular/package.json index 994618a86..e58428fdc 100644 --- a/frontend/examples/angular/package.json +++ b/frontend/examples/angular/package.json @@ -19,7 +19,7 @@ "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.13.0", - "@teamhanko/hanko-elements": "^0.8.3" + "@teamhanko/hanko-elements": "^0.8.4" }, "devDependencies": { "@angular-devkit/build-angular": "^15.2.4", diff --git a/frontend/examples/fresh/.gitignore b/frontend/examples/fresh/.gitignore index 4e06ffcae..00e2e86d0 100644 --- a/frontend/examples/fresh/.gitignore +++ b/frontend/examples/fresh/.gitignore @@ -4,3 +4,6 @@ .env.test.local .env.production.local .env.local + +# Fresh build directory +_fresh/ diff --git a/frontend/examples/fresh/.vscode/extensions.json b/frontend/examples/fresh/.vscode/extensions.json new file mode 100644 index 000000000..971c0ed56 --- /dev/null +++ b/frontend/examples/fresh/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "denoland.vscode-deno", + "sastan.twind-intellisense" + ] +} diff --git a/frontend/examples/fresh/.vscode/settings.json b/frontend/examples/fresh/.vscode/settings.json new file mode 100644 index 000000000..a5f0701f2 --- /dev/null +++ b/frontend/examples/fresh/.vscode/settings.json @@ -0,0 +1,17 @@ +{ + "deno.enable": true, + "deno.lint": true, + "editor.defaultFormatter": "denoland.vscode-deno", + "[typescriptreact]": { + "editor.defaultFormatter": "denoland.vscode-deno" + }, + "[typescript]": { + "editor.defaultFormatter": "denoland.vscode-deno" + }, + "[javascriptreact]": { + "editor.defaultFormatter": "denoland.vscode-deno" + }, + "[javascript]": { + "editor.defaultFormatter": "denoland.vscode-deno" + } +} diff --git a/frontend/examples/fresh/README.md b/frontend/examples/fresh/README.md index 7fc9e3097..7a4b49f3a 100644 --- a/frontend/examples/fresh/README.md +++ b/frontend/examples/fresh/README.md @@ -17,4 +17,4 @@ In the `config.ts` file set up the correct variables: ### Run development server -Run `deno task start` for a development server. Navigate to `http://localhost:8888/`. This will watch the project directory and restart as necessary. +Run `deno task start` for a development server. Navigate to `http://localhost:8888/`. This will watch the project directory and restart as necessary. diff --git a/frontend/examples/fresh/components/TodoItem.tsx b/frontend/examples/fresh/components/TodoItem.tsx index 6c803ad5f..154e1ca3b 100644 --- a/frontend/examples/fresh/components/TodoItem.tsx +++ b/frontend/examples/fresh/components/TodoItem.tsx @@ -21,8 +21,7 @@ export function TodoItem(props: TodoItemProps) { if (response.ok) { setChecked(target.checked); props.onUpdate(props.todoID, target.checked); - } - else { + } else { props.onError(response.statusText); } }; @@ -34,15 +33,20 @@ export function TodoItem(props: TodoItemProps) { if (response.ok) { props.onDelete(props.todoID); - } - else { + } else { props.onError(response.statusText); } }; return (
    - + {props.description}
    diff --git a/frontend/examples/fresh/deno.json b/frontend/examples/fresh/deno.json index 37db4a1d7..1fff6a1f1 100644 --- a/frontend/examples/fresh/deno.json +++ b/frontend/examples/fresh/deno.json @@ -1,9 +1,40 @@ { "lock": false, "tasks": { - "start": "deno run -A --watch=static/,routes/ dev.ts" + "check": "deno fmt --check && deno lint && deno check **/*.ts && deno check **/*.tsx", + "start": "deno run -A --watch=static/,routes/ dev.ts", + "build": "deno run -A dev.ts build", + "preview": "deno run -A main.ts", + "update": "deno run -A -r https://fresh.deno.dev/update ." + }, + "lint": { + "rules": { + "tags": [ + "fresh", + "recommended" + ] + }, + "exclude": [ + "_fresh" + ] + }, + "fmt": { + "exclude": [ + "README.md", + "_fresh" + ] + }, + "imports": { + "$fresh/": "https://deno.land/x/fresh@1.4.3/", + "preact": "https://esm.sh/preact@10.15.1", + "preact/": "https://esm.sh/preact@10.15.1/", + "preact-render-to-string": "https://esm.sh/*preact-render-to-string@6.2.1", + "@preact/signals": "https://esm.sh/*@preact/signals@1.1.3", + "@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.2.3", + "twind": "https://esm.sh/twind@0.16.19", + "twind/": "https://esm.sh/twind@0.16.19/", + "$std/": "https://deno.land/std@0.193.0/" }, - "importMap": "./import_map.json", "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "preact", diff --git a/frontend/examples/fresh/dev.ts b/frontend/examples/fresh/dev.ts index 2d85d6c18..ae73946d7 100755 --- a/frontend/examples/fresh/dev.ts +++ b/frontend/examples/fresh/dev.ts @@ -1,5 +1,8 @@ #!/usr/bin/env -S deno run -A --watch=static/,routes/ import dev from "$fresh/dev.ts"; +import config from "./fresh.config.ts"; -await dev(import.meta.url, "./main.ts"); +import "$std/dotenv/load.ts"; + +await dev(import.meta.url, "./main.ts", config); diff --git a/frontend/examples/fresh/fresh.config.ts b/frontend/examples/fresh/fresh.config.ts new file mode 100644 index 000000000..3a9509b24 --- /dev/null +++ b/frontend/examples/fresh/fresh.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "$fresh/server.ts"; +import twindPlugin from "$fresh/plugins/twind.ts"; +import twindConfig from "./twind.config.ts"; +export default defineConfig({ + port: 8888, + plugins: [twindPlugin(twindConfig)], +}); diff --git a/frontend/examples/fresh/fresh.gen.ts b/frontend/examples/fresh/fresh.gen.ts index 98c420f76..3efc6bc6b 100644 --- a/frontend/examples/fresh/fresh.gen.ts +++ b/frontend/examples/fresh/fresh.gen.ts @@ -1,8 +1,7 @@ -// DO NOT EDIT. This file is generated by fresh. +// DO NOT EDIT. This file is generated by Fresh. // This file SHOULD be checked into source version control. // This file is automatically updated during development when running `dev.ts`. -import config from "./deno.json" assert { type: "json" }; import * as $0 from "./routes/_app.tsx"; import * as $1 from "./routes/api/_middleware.ts"; import * as $2 from "./routes/api/todo/[id].ts"; @@ -32,7 +31,6 @@ const manifest = { "./islands/TodoList.tsx": $$3, }, baseUrl: import.meta.url, - config, }; export default manifest; diff --git a/frontend/examples/fresh/import_map.json b/frontend/examples/fresh/import_map.json deleted file mode 100644 index c3957061d..000000000 --- a/frontend/examples/fresh/import_map.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "imports": { - "$fresh/": "https://deno.land/x/fresh@1.1.6/", - "preact": "https://esm.sh/preact@10.13.1", - "preact/": "https://esm.sh/preact@10.13.1/", - "preact-render-to-string": "https://esm.sh/*preact-render-to-string@5.2.6", - "@preact/signals": "https://esm.sh/*@preact/signals@1.1.3", - "@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.2.3", - "twind": "https://esm.sh/twind@0.16.19", - "twind/": "https://esm.sh/twind@0.16.19/", - "$std/": "https://deno.land/std@0.187.0/" - } -} diff --git a/frontend/examples/fresh/islands/Login.tsx b/frontend/examples/fresh/islands/Login.tsx index 6f67e5f3c..5a3baee2c 100644 --- a/frontend/examples/fresh/islands/Login.tsx +++ b/frontend/examples/fresh/islands/Login.tsx @@ -1,7 +1,7 @@ import { HANKO_API_URL } from "../config.ts"; const code = ` - import { register } from 'https://esm.sh/@teamhanko/hanko-elements@0.5.5-beta'; + import { register } from 'https://esm.sh/@teamhanko/hanko-elements@0.8.4'; register('${HANKO_API_URL}', { shadow: true }); document.addEventListener('hankoAuthSuccess', (event) => { diff --git a/frontend/examples/fresh/islands/LogoutButton.tsx b/frontend/examples/fresh/islands/LogoutButton.tsx index 8e54437a9..2bc663240 100644 --- a/frontend/examples/fresh/islands/LogoutButton.tsx +++ b/frontend/examples/fresh/islands/LogoutButton.tsx @@ -1,7 +1,7 @@ import { HANKO_API_URL } from "../config.ts"; const code = ` - import { register, Hanko } from 'https://esm.sh/@teamhanko/hanko-elements@0.5.5-beta'; + import { register, Hanko } from 'https://esm.sh/@teamhanko/hanko-elements@0.8.4'; register('${HANKO_API_URL}', { shadow: true }); window.addEventListener('logout', () => { @@ -16,7 +16,6 @@ const code = ` }); `; - export default function Profile() { const logout = () => { window.dispatchEvent(new Event("logout")); diff --git a/frontend/examples/fresh/islands/Profile.tsx b/frontend/examples/fresh/islands/Profile.tsx index 6026dd03a..cb8210681 100644 --- a/frontend/examples/fresh/islands/Profile.tsx +++ b/frontend/examples/fresh/islands/Profile.tsx @@ -1,7 +1,7 @@ import { HANKO_API_URL } from "../config.ts"; const code = ` - import { register } from 'https://esm.sh/@teamhanko/hanko-elements@0.5.5-beta'; + import { register } from 'https://esm.sh/@teamhanko/hanko-elements@0.8.4'; register('${HANKO_API_URL}', { shadow: true }); `; diff --git a/frontend/examples/fresh/islands/TodoList.tsx b/frontend/examples/fresh/islands/TodoList.tsx index 1b8218c22..43a6a5e50 100644 --- a/frontend/examples/fresh/islands/TodoList.tsx +++ b/frontend/examples/fresh/islands/TodoList.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState, useRef } from "preact/hooks"; +import { useEffect, useRef, useState } from "preact/hooks"; import { TodoItem } from "../components/TodoItem.tsx"; export default function TodoList() { @@ -18,8 +18,9 @@ export default function TodoList() { }, []); useEffect(() => { - if (error) - modalRef.current.show() + if (error) { + modalRef.current.show(); + } }, [error]); const handleSubmit = async (event: Event) => { @@ -31,7 +32,7 @@ export default function TodoList() { body: JSON.stringify({ description, checked: false, - }) + }), }); if (response.ok) { @@ -40,7 +41,7 @@ export default function TodoList() { setDescription(""); } } - } + }; const handleDelete = async (todoID: string) => { setTodos(todos.filter((todo) => todo.todoID !== todoID)); @@ -57,25 +58,41 @@ export default function TodoList() { return ( <> - { - error && - -
    {error}
    - Please login again.

    - Login -
    - } + {error && + ( + +
    {error}
    + Please login again.
    +
    + + Login + +
    + )}
    - setDescription(event.target.value)} /> - + setDescription(event.target.value)} + /> +
    - { - todos.map((todo) => setError(error)} />) - } + {todos.map((todo) => ( + setError(error)} + /> + ))}
    diff --git a/frontend/examples/fresh/main.ts b/frontend/examples/fresh/main.ts index 8fbb7ed32..675f529bb 100644 --- a/frontend/examples/fresh/main.ts +++ b/frontend/examples/fresh/main.ts @@ -8,8 +8,6 @@ import "$std/dotenv/load.ts"; import { start } from "$fresh/server.ts"; import manifest from "./fresh.gen.ts"; +import config from "./fresh.config.ts"; -import twindPlugin from "$fresh/plugins/twind.ts"; -import twindConfig from "./twind.config.ts"; - -await start(manifest, { port: 8888, plugins: [twindPlugin(twindConfig)] }); +await start(manifest, config); diff --git a/frontend/examples/fresh/routes/_app.tsx b/frontend/examples/fresh/routes/_app.tsx index cd972311f..dca16b0de 100644 --- a/frontend/examples/fresh/routes/_app.tsx +++ b/frontend/examples/fresh/routes/_app.tsx @@ -1,16 +1,19 @@ -import {AppProps} from "$fresh/server.ts"; -import {Head} from "$fresh/runtime.ts"; +import { AppProps } from "$fresh/server.ts"; -export default function App({Component}: AppProps) { +export default function App({ Component }: AppProps) { return ( - <> - + + + + Hanko App - - -
    - -
    - + + + +
    + +
    + + ); } diff --git a/frontend/examples/fresh/routes/api/_middleware.ts b/frontend/examples/fresh/routes/api/_middleware.ts index 4197fe496..bef981a41 100644 --- a/frontend/examples/fresh/routes/api/_middleware.ts +++ b/frontend/examples/fresh/routes/api/_middleware.ts @@ -1,30 +1,35 @@ import { HANKO_API_URL } from "../../config.ts"; import { MiddlewareHandlerContext } from "$fresh/server.ts"; import { getCookies } from "$std/http/cookie.ts"; -import * as jose from 'https://deno.land/x/jose@v4.14.4/index.ts'; +import * as jose from "https://deno.land/x/jose@v4.14.4/index.ts"; const JWKS_ENDPOINT = `${HANKO_API_URL}/.well-known/jwks.json`; const store: Store = new Map(); function getToken(req: Request): string | undefined { const cookies = getCookies(req.headers); - const authorization = req.headers.get("authorization") + const authorization = req.headers.get("authorization"); - if (authorization && authorization.split(" ")[0] === "Bearer") - return authorization.split(" ")[1] - else if (cookies.hanko) - return cookies.hanko + if (authorization && authorization.split(" ")[0] === "Bearer") { + return authorization.split(" ")[1]; + } else if (cookies.hanko) { + return cookies.hanko; + } } -export async function handler(req: Request, ctx: MiddlewareHandlerContext) { +export async function handler( + req: Request, + ctx: MiddlewareHandlerContext, +) { const JWKS = jose.createRemoteJWKSet(new URL(JWKS_ENDPOINT), { cooldownDuration: 120000, timeoutDuration: 15000, }); const jwt = getToken(req); - if (!jwt) + if (!jwt) { return new Response(null, { status: 401 }); + } try { const { payload } = await jose.jwtVerify(jwt, JWKS); diff --git a/frontend/examples/fresh/routes/api/todo/index.ts b/frontend/examples/fresh/routes/api/todo/index.ts index 4438af0bb..0d9ea2429 100644 --- a/frontend/examples/fresh/routes/api/todo/index.ts +++ b/frontend/examples/fresh/routes/api/todo/index.ts @@ -1,5 +1,5 @@ import { HandlerContext, Handlers } from "$fresh/server.ts"; -import { cryptoRandomString } from "https://deno.land/x/crypto_random_string@1.0.0/mod.ts" +import { cryptoRandomString } from "https://deno.land/x/crypto_random_string@1.0.0/mod.ts"; export const handler: Handlers = { GET(_req: Request, ctx: HandlerContext) { @@ -7,9 +7,12 @@ export const handler: Handlers = { const todos = ctx.state.store.get(userID) ?? new Map(); return new Response(JSON.stringify(Array.from(todos.values()))); }, - async POST(req: Request, ctx: HandlerContext): Promise { + async POST( + req: Request, + ctx: HandlerContext, + ): Promise { const userID = ctx.state.auth.sub!; - const todoID = cryptoRandomString({ length: 10, type: 'alphanumeric' }); + const todoID = cryptoRandomString({ length: 10, type: "alphanumeric" }); const { description, checked } = await req.json(); const todos = ctx.state.store.get(userID) || new Map(); todos.set(todoID, { todoID, description, checked }); diff --git a/frontend/examples/fresh/routes/index.tsx b/frontend/examples/fresh/routes/index.tsx index adfdb8b2d..29ca5d24b 100644 --- a/frontend/examples/fresh/routes/index.tsx +++ b/frontend/examples/fresh/routes/index.tsx @@ -1,5 +1,5 @@ import Login from "../islands/Login.tsx"; export default function Home() { - return ; + return ; } diff --git a/frontend/examples/fresh/routes/profile.tsx b/frontend/examples/fresh/routes/profile.tsx index 4d95e29dc..6e5c6306e 100644 --- a/frontend/examples/fresh/routes/profile.tsx +++ b/frontend/examples/fresh/routes/profile.tsx @@ -7,9 +7,9 @@ export default function UserProfile() { - + ); } diff --git a/frontend/examples/fresh/routes/todo.tsx b/frontend/examples/fresh/routes/todo.tsx index aeadc20db..d5cbfdfc6 100644 --- a/frontend/examples/fresh/routes/todo.tsx +++ b/frontend/examples/fresh/routes/todo.tsx @@ -7,9 +7,9 @@ export default function Todo() { - + ); } diff --git a/frontend/examples/fresh/types.d.ts b/frontend/examples/fresh/types.d.ts index b8e61d334..8e601431b 100644 --- a/frontend/examples/fresh/types.d.ts +++ b/frontend/examples/fresh/types.d.ts @@ -1,12 +1,11 @@ -import * as jose from 'https://deno.land/x/jose@v4.14.4/index.ts'; - +import * as jose from "https://deno.land/x/jose@v4.14.4/index.ts"; declare global { - type Todo = { todoID: string, description: string, checked: boolean }; + type Todo = { todoID: string; description: string; checked: boolean }; type Store = Map>; interface AppState { - store: Store, + store: Store; auth: jose.JWTPayload; } } diff --git a/frontend/examples/nextjs/package.json b/frontend/examples/nextjs/package.json index 3d39d6e94..b16e81a3d 100644 --- a/frontend/examples/nextjs/package.json +++ b/frontend/examples/nextjs/package.json @@ -6,7 +6,7 @@ "build": "next build" }, "dependencies": { - "@teamhanko/hanko-elements": "^0.8.3", + "@teamhanko/hanko-elements": "^0.8.4", "next": "^13.2.1", "react": "^18.2.0", "react-dom": "^18.2.0" diff --git a/frontend/examples/react/package.json b/frontend/examples/react/package.json index 0ad314ea9..38e24023d 100644 --- a/frontend/examples/react/package.json +++ b/frontend/examples/react/package.json @@ -2,7 +2,7 @@ "name": "example-react", "private": true, "dependencies": { - "@teamhanko/hanko-elements": "^0.8.3", + "@teamhanko/hanko-elements": "^0.8.4", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.7", "react": "^18.2.0", diff --git a/frontend/examples/svelte/package.json b/frontend/examples/svelte/package.json index a97e1a9bd..c84f71c56 100644 --- a/frontend/examples/svelte/package.json +++ b/frontend/examples/svelte/package.json @@ -17,7 +17,7 @@ "vite": "^4.4.9" }, "dependencies": { - "@teamhanko/hanko-elements": "^0.8.3", + "@teamhanko/hanko-elements": "^0.8.4", "svelte-navigator": "^3.2.2" } } diff --git a/frontend/examples/vue/package.json b/frontend/examples/vue/package.json index 30fbd4006..6529c4506 100644 --- a/frontend/examples/vue/package.json +++ b/frontend/examples/vue/package.json @@ -5,7 +5,7 @@ "build": "vite build" }, "dependencies": { - "@teamhanko/hanko-elements": "^0.8.3", + "@teamhanko/hanko-elements": "^0.8.4", "vue": "^3.2.47", "vue-router": "^4.1.6" }, diff --git a/frontend/frontend-sdk/package.json b/frontend/frontend-sdk/package.json index 4a58b3946..8286eb6c1 100644 --- a/frontend/frontend-sdk/package.json +++ b/frontend/frontend-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@teamhanko/hanko-frontend-sdk", - "version": "0.8.3", + "version": "0.8.4", "private": false, "publishConfig": { "access": "public" @@ -8,12 +8,15 @@ "files": [ "dist" ], - "types": "dist/index.d.ts", "type": "module", "source": "src/index.ts", + "types": "dist/index.d.ts", "exports": { - "require": "./dist/sdk.cjs", - "default": "./dist/sdk.modern.js" + ".": { + "require": "./dist/sdk.cjs", + "types": "./dist/index.d.ts", + "default": "./dist/sdk.modern.js" + } }, "main": "./dist/sdk.cjs", "module": "./dist/sdk.module.js", diff --git a/frontend/frontend-sdk/src/lib/Cookie.ts b/frontend/frontend-sdk/src/lib/Cookie.ts index 518d541e7..383d7673c 100644 --- a/frontend/frontend-sdk/src/lib/Cookie.ts +++ b/frontend/frontend-sdk/src/lib/Cookie.ts @@ -11,6 +11,19 @@ interface CookieOptions { cookieName: string; } +/** + * Options for setting the auth cookie. + * + * @category SDK + * @subcategory Internal + * @property {boolean} secure - Indicates if the Secure attribute of the cookie should be set. + * @property {number | Date | undefined} expires - The expiration of the cookie. + */ +interface SetAuthCookieOptions { + secure?: boolean; + expires?: number | Date | undefined; +} + /** * A class to manage cookies. * @@ -39,10 +52,13 @@ export class Cookie { * Stores the authentication token to the cookie. * * @param {string} token - The authentication token to be stored. - * @param {boolean=} secure - Indicates a secure cookie should be set. Default is `true`. + * @param {SetAuthCookieOptions} options - Options for setting the auth cookie. */ - setAuthCookie(token: string, secure = true) { - JSCookie.set(this.authCookieName, token, { secure }); + setAuthCookie( + token: string, + options: SetAuthCookieOptions = { secure: true }, + ) { + JSCookie.set(this.authCookieName, token, options); } /** diff --git a/frontend/frontend-sdk/src/lib/client/HttpClient.ts b/frontend/frontend-sdk/src/lib/client/HttpClient.ts index b6aa3f425..dadf448bc 100644 --- a/frontend/frontend-sdk/src/lib/client/HttpClient.ts +++ b/frontend/frontend-sdk/src/lib/client/HttpClient.ts @@ -209,14 +209,15 @@ class HttpClient { } else if (header.startsWith("x-session-lifetime")) { expirationSeconds = parseInt( response.headers.getResponseHeader("X-Session-Lifetime"), - 10 + 10, ); } }); if (jwt) { const secure = !!this.api.match("^https://"); - this.cookie.setAuthCookie(jwt, secure); + const expires = new Date(new Date().getTime() + expirationSeconds * 1000); + this.cookie.setAuthCookie(jwt, { secure, expires }); } this.passcodeState.read().reset(userID).write(); diff --git a/frontend/frontend-sdk/tests/lib/Cookie.spec.ts b/frontend/frontend-sdk/tests/lib/Cookie.spec.ts index 4c48da760..78a645389 100644 --- a/frontend/frontend-sdk/tests/lib/Cookie.spec.ts +++ b/frontend/frontend-sdk/tests/lib/Cookie.spec.ts @@ -1,5 +1,6 @@ import JSCookie from "js-cookie"; import { Cookie } from "../../src/lib/Cookie"; +import { fakeTimerNow } from "../setup"; describe("Cookie()", () => { let cookie: Cookie; @@ -11,7 +12,7 @@ describe("Cookie()", () => { describe("cookie.setAuthCookie()", () => { it("should set a new cookie", async () => { jest.spyOn(JSCookie, "set"); - cookie.setAuthCookie("test-token", false); + cookie.setAuthCookie("test-token", { secure: false }); expect(JSCookie.set).toHaveBeenCalledWith("hanko", "test-token", { secure: false, }); @@ -25,6 +26,16 @@ describe("Cookie()", () => { secure: true, }); }); + + it("should set a new cookie with expiration", async () => { + jest.spyOn(JSCookie, "set"); + const expires = new Date(fakeTimerNow + 60); + cookie.setAuthCookie("test-token", { secure: true, expires }); + expect(JSCookie.set).toHaveBeenCalledWith("hanko", "test-token", { + secure: true, + expires, + }); + }); }); describe("cookie.getAuthCookie()", () => { diff --git a/frontend/frontend-sdk/tests/lib/client/HttpClient.spec.ts b/frontend/frontend-sdk/tests/lib/client/HttpClient.spec.ts index 734c038a3..4f73ae472 100644 --- a/frontend/frontend-sdk/tests/lib/client/HttpClient.spec.ts +++ b/frontend/frontend-sdk/tests/lib/client/HttpClient.spec.ts @@ -4,6 +4,7 @@ import { HttpClient, } from "../../../src/lib/client/HttpClient"; import { RequestTimeoutError, TechnicalError } from "../../../src"; +import { fakeTimerNow } from "../../setup"; const jwt = "test-token"; let httpClient: HttpClient; @@ -224,7 +225,10 @@ describe("httpClient.processResponseHeadersOnLogin()", () => { ); expect(client.sessionState.setUserID).toHaveBeenCalledWith(userID); - expect(client.cookie.setAuthCookie).toHaveBeenCalledWith(jwt, false); + expect(client.cookie.setAuthCookie).toHaveBeenCalledWith(jwt, { + secure: false, + expires: new Date(fakeTimerNow + expirationSeconds * 1000), + }); expect(client.cookie.setAuthCookie).toBeCalledTimes(1); }); @@ -240,7 +244,10 @@ describe("httpClient.processResponseHeadersOnLogin()", () => { jest.spyOn(client.cookie, "setAuthCookie"); client.processResponseHeadersOnLogin(userID, response); - expect(client.cookie.setAuthCookie).toHaveBeenCalledWith(jwt, true); + expect(client.cookie.setAuthCookie).toHaveBeenCalledWith(jwt, { + secure: true, + expires: new Date(fakeTimerNow + expirationSeconds * 1000), + }); expect(client.cookie.setAuthCookie).toBeCalledTimes(1); }); }); diff --git a/frontend/frontend-sdk/tests/setup.ts b/frontend/frontend-sdk/tests/setup.ts index 3fdc190ea..5cea5c7f3 100644 --- a/frontend/frontend-sdk/tests/setup.ts +++ b/frontend/frontend-sdk/tests/setup.ts @@ -82,12 +82,15 @@ export const fakeXMLHttpRequest = (function () { })); })(); + Object.defineProperty(global, "XMLHttpRequest", { value: fakeXMLHttpRequest, configurable: true, writable: true, }); +export const fakeTimerNow = 1664379699000; + jest.useFakeTimers({ - now: 1664379699000, + now: fakeTimerNow, }); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 87a8932dd..af5ef0908 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -16,11 +16,11 @@ }, "elements": { "name": "@teamhanko/hanko-elements", - "version": "0.8.3", + "version": "0.8.4", "license": "MIT", "dependencies": { "@denysvuika/preact-translate": "^0.5.0", - "@teamhanko/hanko-frontend-sdk": "^0.8.2", + "@teamhanko/hanko-frontend-sdk": "^0.8.4", "@teamhanko/preact-custom-element": "^4.2.2", "classnames": "^2.3.2", "preact": "^10.13.1" @@ -56,7 +56,7 @@ "@angular/platform-browser": "^15.2.8", "@angular/platform-browser-dynamic": "^15.2.8", "@angular/router": "^15.2.8", - "@teamhanko/hanko-elements": "^0.8.3", + "@teamhanko/hanko-elements": "^0.8.4", "angular-in-memory-web-api": "~0.15.0", "rxjs": "~7.8.0", "tslib": "^2.3.0", @@ -513,7 +513,7 @@ "examples/nextjs": { "name": "example-nextjs", "dependencies": { - "@teamhanko/hanko-elements": "^0.8.3", + "@teamhanko/hanko-elements": "^0.8.4", "next": "^13.2.1", "react": "^18.2.0", "react-dom": "^18.2.0" @@ -530,7 +530,7 @@ "examples/react": { "name": "example-react", "dependencies": { - "@teamhanko/hanko-elements": "^0.8.3", + "@teamhanko/hanko-elements": "^0.8.4", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.7", "react": "^18.2.0", @@ -543,7 +543,7 @@ "examples/svelte": { "name": "example-svelte", "dependencies": { - "@teamhanko/hanko-elements": "^0.8.3", + "@teamhanko/hanko-elements": "^0.8.4", "svelte-navigator": "^3.2.2" }, "devDependencies": { @@ -560,7 +560,7 @@ "examples/vue": { "name": "example-vue", "dependencies": { - "@teamhanko/hanko-elements": "^0.8.3", + "@teamhanko/hanko-elements": "^0.8.4", "vue": "^3.2.47", "vue-router": "^4.1.6" }, @@ -616,7 +616,7 @@ }, "frontend-sdk": { "name": "@teamhanko/hanko-frontend-sdk", - "version": "0.8.3", + "version": "0.8.4", "license": "MIT", "dependencies": { "@types/js-cookie": "^3.0.3"