Dead simple cookie-based session for Deno Fresh.

Overview

Fresh Session 🍋

Dead simple cookie-based session for Deno Fresh.

Get started

Fresh Session comes with a simple middleware to add at the root of your project, which will create or resolve a session from the request cookie.

Install / Import

You can import Fresh Session like so:

import {
  cookieSession,
  createCookieSessionStorage,
  CookieSessionStorage
  WithSession,
  Session,
} from "https://deno.land/x/[email protected]/mod.ts";

Setup secret key

Fresh Session currently use JSON Web Token under the hood to create and manage session in the cookies.

JWT requires to have a secret key to encrypt new token. Fresh Session use the session from your environment variable APP_KEY.

If you don't know how to setup environment variable locally, I wrote an article about .env file in Deno Fresh.

Create a root middleware (./routes/_middleware.ts)

import { MiddlewareHandlerContext } from "$fresh/server.ts";
import {
  cookieSession,
  WithSession,
} from "https://deno.land/x/[email protected]/mod.ts";

export type State = WithSession;

export function handler(
  req: Request,
  ctx: MiddlewareHandlerContext<State>,
) {
  return cookieSession(req, ctx);
}

Learn more about Fresh route middleware.

Interact with the session in your routes

Now that the middleware is setup, it's going to handle creating/resolving session based on the request cookie. So all that you need to worry about is interacting with your session.

// ./routes/dashboard.tsx
/** @jsx h */
import { h } from "preact";
import { Handlers, PageProps } from "$fresh/server.ts";
import { WithSession } from "https://deno.land/x/[email protected]/mod.ts";

export type Data = { session: Record<string, string> };

export const handler: Handlers<
  Data,
  WithSession // indicate with Typescript that the session is in the `ctx.state`
> = {
  GET(_req, ctx) {
    // The session is accessible via the `ctx.state`
    const { session } = ctx.state;

    // Access data stored in the session
    session.get("email");
    // Set new value in the session
    session.set("email", "[email protected]");
    // returns `true` if the session has a value with a specific key, else `false`
    session.has("email");
    // clear all the session data
    session.clear();
    // Access all session data value as an object
    session.data;
    // Add flash data which will disappear after accessing it
    session.flash("success", "Successfully flashed a message!");
    // Accessing the flashed data
    // /!\ This flashed data will disappear after accessing it one time.
    session.flash("success");

    return ctx.render({
      session: session.data, // You can pass the whole session data to the page
    });
  },
};

export default function Dashboard({ data }: PageProps<Data>) {
  return <div>You are logged in as {data.session.email}</div>;
}

Credit

Inspiration taken from Oak Sessions & thanks to @jcs224 for all the insight!

Comments
  • Add Redis session store example.

    Add Redis session store example.

    Hello, @xstevenyung.

    I have created a sample that uses the Redis store. (I apologize for having to recreate it.)

    I have also created a README, so please follow it and try to run it.

    Note that the following part of import _map.json is written for the next release.

     "fresh-session/": "https://deno.land/x/[email protected]/"
    

    If you try to run it, rewrite the following.

    "fresh-session/": "https://raw.githubusercontent.com/xstevenyung/fresh-session/main/"
    

    https://github.com/xstevenyung/fresh-session/issues/6

    documentation 
    opened by Octo8080X 4
  • Error on deno deploy

    Error on deno deploy

    Whenever I try to load a page which requires the session this error appears.

    An error occurred during route handling or page rendering. ReferenceError: Worker is not defined
        at hash (https://deno.land/x/[email protected]/src/main.ts:11:18)
        at Register (file:///src/src/database/controller.ts:19:25)
        at GET (file:///src/routes/signup.tsx:12:26)
        at routes.<computed> (https://deno.land/x/[email protected]/src/server/context.ts:319:81)
        at https://crux.land/api/get/uYQG.ts:83:42
        at https://deno.land/x/[email protected]/src/server/context.ts:208:31
        at Object.next (https://deno.land/x/[email protected]/src/server/context.ts:200:44)
        at cookieSession (https://deno.land/x/[email protected]/src/stores/cookie.ts:65:32)
        at async Server.#respond (https://deno.land/[email protected]/http/server.ts:219:24)
    

    What is the cause and the required fix?

    bug 
    opened by KorigamiK 4
  • Add Redis session store.

    Add Redis session store.

    Nice to meet you.

    I have added a Redis store as a starting point for a database session.

    Here's how to use it.

    I also confirmed that it works with upstash for redis, not just Redis.

    import { MiddlewareHandlerContext } from "$fresh/server.ts";
    import {
      CreateRedisSession,
      WithSession,
    } from "fresh-session/mod.ts";
    export type State = WithSession;
    
    import { connect } from 'https://deno.land/x/[email protected]/mod.ts'
    const redis = await connect({
      hostname: 'redis',
      port: 6379,
    })
    
    // or
    
    import { Redis } from "https://deno.land/x/upstash_redis/mod.ts";
    const redis = new Redis({
      url: Deno.env.get("UPSTASH_URL")!,
      token: Deno.env.get("UPSTASH_TOKEN")!,
      automaticDeserialization: false,
    });
    
    const redisSession = new CreateRedisSession(redis)
    
    export function handler(
      req: Request,
      ctx: MiddlewareHandlerContext<State>,
    ) {
      return redisSession(req, ctx);
    }
    
    opened by Octo8080X 4
  • "Headers are immutable" Error when implementing oAuth2

    Hey Steven, just want to thank you for making this. Works perfectly on my new portfolio site. I'm sure you're busy but was hoping you could help me with a noob issue.

    I'm getting a Typescript "Headers are immutable." error when using a "deno_grant" library for oauth2.

    Basically when the client is redirecting the user to another site (https://discord.com/api/oauth2/authorize...), I'm getting this error.

    I am still trying to wrap my head around the cookie session flow. Anyway, appreciate it!

    bug help wanted good first issue question 
    opened by trchristensen 3
  • Setup cookie option

    Setup cookie option

    Hello, @xstevenyung.

    Both cookie sessions and redis sessions use cookies, but I was unable to set cookie options, so I added a feature. Specifically, I wanted to set max-age, http-only, etc.

    For example.

    /// _middleware.ts
    import { MiddlewareHandlerContext } from "$fresh/server.ts";
    import { CreateCookieSession, WithSession } from "fresh-session";
    
    export type State = {} & WithSession;
    
    const cookieSession = CreateCookieSession({maxAge: 30, httpOnly: true});
    
    export function handler(req: Request, ctx: MiddlewareHandlerContext<State>) {
      return cookieSession(req, ctx);
    }
    
    
    /// _middleware.ts
    import { MiddlewareHandlerContext } from "$fresh/server.ts";
    import { CreateRedisSession, WithSession } from "fresh-session/mod.ts";
    import { connect } from "redis/mod.ts";
    export type State = WithSession;
    
    const redis = await connect({
      hostname: "redis",
      port: 6379,
    });
    
    const redisSession = CreateRedisSession(redis, "session_", { maxAge: 10 });
    
    function session(req: Request, ctx: MiddlewareHandlerContext<State>) {
      if (req.url === `http://localhost:${ctx.localAddr?.port}/`) {
        return redisSession(req, ctx);
      }
      return ctx.next();
    }
    export const handler = [session];
    
    
    opened by Octo8080X 3
  • Regist letest version(0.1.9) to deno.land/x

    Regist letest version(0.1.9) to deno.land/x

    Hello @xstevenyung san.

    The latest version on github and the latest version on deno.land/x seem to be out of sync.

    I think the next one will be 0.1.9, can I tag it?

    opened by Octo8080X 2
  • Readme faq

    Readme faq

    Change: Added an FAQ section in the README with the Response.redirect issue.

    Apologize if I'm doing this wrong. This is my first official pull request (haha!).

    opened by trchristensen 2
  • Add documentation for Redis Store with example

    Add documentation for Redis Store with example

    Thanks to @Octo8080X work, we now have access to a Redis store for session.

    We need to add some documentation (inspiration can be taken from the PR https://github.com/xstevenyung/fresh-session/pull/3) to help people understand how to work with it.

    documentation help wanted good first issue 
    opened by xstevenyung 2
  • Add Redis session store example.

    Add Redis session store example.

    Hello, @xstevenyung.

    I have created a sample that uses the Redis store.

    I have also created a README, so please follow it and try to run it.

    Note that the following part of import _map.json is written for the next release.

     "fresh-session/": "https://deno.land/x/[email protected]/"
    

    If you try to run it, rewrite the following.

    "fresh-session/": "https://raw.githubusercontent.com/xstevenyung/fresh-session/main/"
    

    https://github.com/xstevenyung/fresh-session/issues/6

    documentation 
    opened by Octo8080X 1
  • Improve session typing

    Improve session typing

    Currently, session are not typed, we are loosing typing when accessing data.

    As a quick fix, we can always use as but it's not ideal. Typing session directly from the session creation would be better.

    enhancement 
    opened by xstevenyung 0
  • add support for user-land session implementation

    add support for user-land session implementation

    At the moment, Fresh Session only support cookie session based on JWT and Redis (thanks to @Octo8080X ).

    Remix provide a nice way to create session storage that we can take inspiration from https://remix.run/docs/en/v1/api/remix#createsessionstorage

    After implementing this, we should rewrite all existing adapter to use our new function

    enhancement help wanted 
    opened by xstevenyung 3
Owner
Steven Yung
Freelance fullstack developer 🥞 | Serial unlaunched side-projects maker 🚀 | Bouldering fanatic 🧗
Steven Yung
Simple store for Deno Fresh, to pass state between islands

Fresh Store A minimal store for Fresh, to allow communication between islands. It attach stores to the window component. It uses "pointers" or "keys"

Alexandre Moreau-Lemay 9 Sep 12, 2022
A fresh (deno) app

Welcome to fresh-deno-app ?? A fresh (deno) app ?? Homepage ✨ Demo Prerequisites Deno version 1.22.3 or higher installed. - A modern runtime for JavaS

Dung Duc Huynh (Kaka) 4 Oct 17, 2022
The fastest way ⚡️ to create sitemap in your Deno Fresh project 🍋

Fresh SEO ??     Quickly creating sitemaps for your Deno Fresh project. Getting Started Run the setup at the root of your project. deno run

Steven Yung 34 Dec 19, 2022
A minimal blog template using the Fresh framework for Deno.

Fresh Blog This is a minimal blog template using the awesome framework Fresh from Deno. Usage Start the project: deno task start This will watch the

Little Sticks 21 Dec 16, 2022
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
Opinionated collection of TypeScript definitions and utilities for Deno and Deno Deploy. With complete types for Deno/NPM/TS config files, constructed from official JSON schemas.

Schemas Note: You can also import any type from the default module, ./mod.ts deno.json import { type DenoJson } from "https://deno.land/x/[email protected]

deno911 2 Oct 12, 2022
A dead simple JWT-based authentication library for Next.js framework.

nexauth A dead simple JWT-based authentication library for Next.js framework. Getting Started Visit https://betagouv.github.io/nexauth/#/install to ge

beta.gouv.fr 12 Aug 2, 2022
Dead simple program to upload NFT data to IPFS via nft.storage

NFTP The simplest way to publish files and folders to IPFS, with one command. 100% FREE to upload as much files as you want, powered by nft.storage. N

factoria 35 Dec 11, 2022
A dead-simple Bookmarklet and Chrome Extension implementation of something like Bionic Reading

What is it? Inspired by Bionic Reading, this Bookmarklet modifies a webpage to display the first half of each word in bold. Can also be installed as a

null 35 Dec 5, 2022
🛡️ Dead-simple, yet highly customizable security middleware for Apollo GraphQL servers and Envelop 🛡️

GraphQL Armor ??️ GraphQL Armor is a dead-simple yet highly customizable security middleware for various GraphQL server engines. Contents Contents Sup

Escape – GraphQL Security 267 Jan 9, 2023
Dead simple, single file, tiny byte formatter

tiny-byte-size Dead simple, no configuration needed, tiny byte formatter npm install tiny-byte-size Usage const byteSize = require('tiny-byte-size')

Mathias Buus 17 Aug 24, 2022
Dead-simple CORS handling for any itty-router API (test with Cloudflare Workers, but works anywhere)!

Simple CORS-handling for any itty-router API. Designed on Cloudflare Workers, but works anywhere. Features Tiny. Currently ~600 bytes, with zero-depen

Kevin R. Whitley 6 Dec 16, 2022
Angular 14 JWT Authentication & Authorization with Web API and HttpOnly Cookie - Token Based Auth, Router, Forms, HttpClient, BootstrapBootstrap

Angular 14 JWT Authentication with Web API and HttpOnly Cookie example Build Angular 14 JWT Authentication & Authorization example with Web Api, HttpO

null 20 Dec 26, 2022
This is a simple boilerplate for a Deno website, deployed with Deno Deploy.

Simple Deno Website Boilerplate This is a simple website boilerplate built using Deno and deployed using Deno Deploy. Demo at simple-deno-website-boil

Bruno Bernardino 15 Dec 3, 2022
A simple cookie consent plugin for jQuery

jquery.cookie-consent A simple jQuery plugin for requesting consent for cookie usage. Live demo See a live demo on CodePen Installation Using npm npm

null 3 Nov 29, 2022
A fresh look for the Hackage. Follow us: https://twitter.com/HackageUI

Hackage UI Fresh look for the https://hackage.haskell.org/. Work in progress. Search Search on Hoogle. Search on Hackage. Full-text search integration

visortelle 97 Dec 28, 2022
A demonstration app for Fresh that shows how to use SSR, the islands functionality, APIs and more

Fresh Pokemon Demo Code This is a demonstration app for Fresh that shows how to use SSR, the islands functionality, APIs and more. You do need to conn

Jack Herrington 23 Dec 18, 2022