Skip to main content

@repo/auth

Introduction

This library is designed specifically for use in a monorepo. It is a simple wrapper that handles access control, using the principles of Gates to systematically and securely grant or deny access.

This library was inspired by the authorization methods from Laravel

Installation

npm install @repo/auth

Sessions

Sessions is the state of the current entity that is using the application. Usually this is a user.

Getting sessions

There are two ways of getting a session:

import { getSession } from '@repo/auth/server'

const session = await getSession()

You can also directly get the user session. This means that the user object is not null. It will throw a 401 error if it is empty.

import { getUserSession } from '@repo/auth/server'

const session = await getUserSession()

System session

Sometimes you want to overwrite the session so that other repositories can still use getSession or getUserSession. This can be done by using useSystemSession

import { useSystemSession, getSession } from '@repo/auth/server'

await useSystemSession(organization.id, user.id, async () => {
const session = getSession() // This is now a system session
})

Access control

Gates

You can easily create gates yourself:

import type { Gate } from '@repo/auth';

export function createAuthorityGate(authorities: string[]): Gate {
return (session) =>
authorities.every((val) => session?.user?.authorities.includes(val) || false);
}

Error Code

There is a possibility to change the error code by returning a GateResult.

export function createAuthorityGate(authorities: string[]): Gate {
return (session) => {
const = authorities.every((val) => session?.user?.authorities.includes(val) || false);

if (!authorities) {
return createGateResult(false, 401);
}

return true;
}
}

Checking access

We recommend wrapping the validate session per application since the auth logic can differ.

  • onUnauthenticated is called when the gate result is 401. This should only be done when there is no user
  • onUnauthorized is called on a 403. This is the default behaviour.
export async function validateSession(gates?: Gate[]) {
await validateAccessInSvelte({
gates,
onUnauthenticated: () => {
const request = getRequestEvent()
const redirectTarget = encodeURIComponent(request.url.pathname + request.url.search)
redirect(307, `/login?redirect=${redirectTarget}`)
},
onUnauthorized: () => {
redirect(307, '/dashboard')
},
})
}

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License

This library is licensed under the MIT License.

Contact

Jessie Liauw A Fong - github