npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@solid-auth/core

v0.0.6

Published

This is a ported and improved version of [Remix Auth](https://github.com/sergiodxa/remix-auth), it is using [Solid Sessions](https://start.solidjs.com/advanced/session) to manage the user sessions / cookies - based on [Solid Start](https://start.solidjs.c

Downloads

23

Readme

@solid-auth/core

This is a ported and improved version of Remix Auth, it is using Solid Sessions to manage the user sessions / cookies - based on Solid Start

Packages

  • @solid-auth/oauth2 - OAuth2 strategy based on the @solid-auth/core strategy
  • @solid-auth/socials - OAuth2 socials providers (like discord, github, google, etc) based on the @solid-auth/oauth2 strategy
  • @solid-auth/auth0 - Auth0 strategy based on the @solid-auth/core and @solid-auth/oauth2 strategy
  • @solid-auth/credentials - Use your own conditions, just return the user to the strategy and we will handle the rest for you.

Getting Started

It is highly recommended to use Create JD App to create your app, it will create a new app with all the necessary packages and configurations, so you won't need to worry about anything.

Installation

npm i @solid-auth/core
# if you want to use social providers
npm i @solid-auth/socials

Creating The Server Authenticator

As mentioned previously, @soid-auth/core is based on Solid Sessions, so first you need to create a sessionStorage:

// src/utils/auth.ts
import { createCookieSessionStorage } from 'solid-start'
import { createSolidAuthClient } from '@solid-auth/core'

const getBaseUrl = () => {
  if (typeof window !== 'undefined') return ''
  return `http://localhost:${process.env.PORT ?? 3000}`
}

export const sessionStorage = createCookieSessionStorage({
  cookie: {
    name: '_session',
    secrets: ['your-secret'],
    secure: true,
    maxAge: 60 * 60 * 24 * 30,
  },
})

// Create the Solid Auth Client So You Can Actually Manage The User From The Client Side
export const authClient = createSolidAuthClient(`${getBaseUrl()}/api/auth`)

Now that you have a session you can create the actual authenticator:

// src/server/auth.ts
import { type User } from '@prisma/client' // the type of your user
import { DiscordStrategy } from '@solid-auth/socials' // or any other provider
import { serverEnv } from '~/env/server' // type safed process.env, doesn't really matter
import { sessionStorage } from '~/utils/auth' // the sessionStorage we created before
import { prisma } from './db/client' // or any other orm you wish to use
import { Authenticator } from '@solid-auth/core'

export const authenticator = new Authenticator<User>(sessionStorage).use(
  new DiscordStrategy(
    {
      clientID: serverEnv.DISCORD_CLIENT_ID,
      clientSecret: serverEnv.DISCORD_CLIENT_SECRET,
      // SITE_URL should be set to: http://localhost:3000 locally and https://yourdomain.com in production
      callbackURL: serverEnv.SITE_URL + '/api/auth/discord/callback',
    },
    async ({ profile }) => {
      let user = await prisma.user.findUnique({
        where: {
          id: profile.id,
        },
      })
      if (!user) {
        user = await prisma.user.create({
          data: {
            id: profile.id,
            displayName: profile.__json.username,
            avatar: profile.photos[0].value,
          },
        })
      }
      return user
    }
  )
)

Handling Auth Requests

But just because we created the authenticator doesn't mean it will work, we need to create the routes to actually handle the authentication:

// src/routes/api/auth/[...solidauth].ts
import { authenticator } from '~/server/auth' // the authenticator we created before
import { type User } from '@prisma/client' // the type of your user
import { createSolidAuthHandler } from '@solid-auth/core'

const handler = createSolidAuthHandler<User>(authenticator)

export const POST = handler // handle the login, logout etc
export const GET = handler // handle the callback

Making Auth Requests

Now that we have the routes to handle the authentication, we need to make the requests to them, we can do that using the authClient we created before:

import { authClient } from '~/utils/auth' // the authClient we created before
// Sign In
authClient.login('discord' /* or any other provider*/, {
  successRedirect: '/', // where to redirect the user after the login
  failureRedirect: '/account', // where to redirect the user if the login failed
})

// Sign Out
authClient.logout({ redirectTo: '/account' })

Getting The Logged In User

// src/routes/example.tsx
import { useRouteData } from "solid-start";
import { createServerData$ } from "solid-start/server";
import { authenticator } from '~/server/auth' // the authenticator we created before

export const routeData = () => {
  return createServerData$(async (_, { request }) => {
    return await authenticator.isAuthenticated(request);
  });
};

export default function Example() {
  const user = useRouteData<typeof routeData>(); // resource with type User | null | undefined
  return (
    {...}
  );
}

Protected Routes

Creating Protected Layout

// src/layouts/Protected.tsx
import { Match, Switch, type Component } from 'solid-js'
import { useRouteData } from 'solid-start'
import { createServerData$, redirect } from 'solid-start/server'
import { authenticator } from '~/server/auth' // the authenticator we created before
import { type User } from '@prisma/client' // the type of your user

export const withProtected = (Component: ProtectedRouter) => {
  const routeData = () => {
    return createServerData$(async (_, { request }) => {
      const user = await authenticator.isAuthenticated(request) // check if user session exists
      if (!user) {
        // if not login redirect to login page
        throw redirect('/login') // we use throw and not return because we dont't want to mess the return type
      }
      return user
    })
  }
  return {
    routeData,
    Page: () => {
      const current = useRouteData<typeof routeData>()
      return (
        //  not loading, and current is not instance of Response, the user is logged in - we should render the page
        <Switch fallback={<Component {...(current() as User)} />}>
          {/* if current() is instance of Response, meaning that the user is being redirected to the login page */}
          <Match when={current.loading || current() instanceof Response}>
            <p>Loading</p>
          </Match>
        </Switch>
      )
    },
  }
}

export type ProtectedRouter = Component<User>

Using The Protected Layout

// src/routes/protected.tsx
import { withProtected } from '../layouts/Protected' // the protected layout we created before
// we export the routeData to get the useRouteData to work
export const { routeData, Page } = withProtected((user) => {
  // type safed user, no need to use ?. anymore
  return <h1>Hey {user.displayName}</h1>
})

export default Page // The page should be default exported, we export `Page` above because we want to export the routeData and its just cleaner

Credits / Inspired By