SessionContext
is available off of ctx
which is provided as the second
parameter to all queries and mutations.
// src/queries/someQuery.ts
import { Ctx } from "blitz"
export default async function someQuery(input: any, ctx: Ctx) {
// Access the SessionContext class
ctx.session.userId
ctx.session.role
ctx.session.$create(/*...*/)
return
}
getServerSideProps
You can get the session context inside getServerSideProps
by wrapping it
with the gSSP
function exported from src/blitz-server
:
import { SessionContext } from "@blitzjs/auth"
import { gSSP } from "src/blitz-server"
type Props = {
userId: unknown
publicData: SessionContext["$publicData"]
}
export const getServerSideProps = gSSP<Props>(async ({ ctx }) => {
const { session } = ctx
return {
props: {
userId: session.userId,
publicData: session.$publicData,
publishedAt: new Date(0),
},
}
})
function PageWithGssp(props: Props) {
return <div>{JSON.stringify(props, null, 2)}</div>
}
export default PageWithGssp
You can get the session context inside API routes by wrapping it with the
withBlitzAuth
function exported from src/blitz-server
:
//app/api/logout/route.ts
import { withBlitzAuth } from "app/blitz-server"
export const POST = withBlitzAuth(async (_request, _params, ctx) => {
const session = ctx.session
await session.$revoke()
return new Response(
JSON.stringify({
userId: session.userId,
}),
{ status: 200 }
)
})
withBlitzAuth
APIThe function supports both single handler as an input as well as an object of handlers and has the following signature:
function withBlitzAuth(handlers: { [method: string]: Handler })
handlers: { [method: string]: Handler })
- An object of handlers where
the key is the HTTP method and the value is the handler function.type Handler = (
request: Request,
params: Record<string, string>,
ctx: { session: SessionContext }
) => Promise<Response>
{ [method: string]: Handler }
- The wrapper function returns an object
of handlers where the key is the HTTP method and the value is the
handler function wrapped with the session management of @blitzjs/auth
.
//app/api/logout/route.ts
import { withBlitzAuth } from "app/blitz-server"
export const { POST } = withBlitzAuth({
POST: async (_request, _params, { session }) => {
// logout the user
await session.$revoke()
return new Response(
JSON.stringify({
userId: session.userId,
}),
{ status: 200 }
)
},
})
//app/api/multiple/route.ts
import { withBlitzAuth } from "app/blitz-server"
export const { GET, POST } = withBlitzAuth({
GET: async (_request, _params, { session }) => {
return new Response(
JSON.stringify({
userId: session.userId,
}),
{ status: 200 }
)
},
POST: async (_request, _params, { session }) => {
return new Response(
JSON.stringify({
userId: session.userId,
}),
{ status: 200 }
)
},
})
You can get the session context inside API routes by wrapping it with the
api
function exported from src/blitz-server
:
import { api } from "src/blitz-server"
import db from "db"
export default api(async (_req, res, ctx) => {
ctx.session.$authorize()
const publicData = ctx.session.$publicData
res.status(200).json({
userId: ctx.session.userId,
publicData: { ...publicData },
})
})
generateToken()
generateToken(numberOfCharacters: number = 32) => string
This is a convenience wrapper around nanoid for generating tokens for things like password resets.
import { generateToken } from "@blitzjs/auth"
const token = generateToken()
hash256()
hash256(value: string) => string
This is a convenience wrapper that uses the node
crypto module to hash a string with
the sha256
algorithm. It is used for things like hashing password reset
tokens before saving them in the database.
Hash256 is also useful for storing strings like API keys in the database because the returned hash will always be the same for a given string. Therefore, you can still verify that an API key exists in the database when the only value you have to reference is the hashed key.
import { hash256 } from "@blitzjs/auth"
const hashedToken = hash256(token)
SecurePassword
SecurePassword
is a convenience wrapper around
secure-password to provide
a nice way to hash passwords and verify password hashes.
import { SecurePassword } from "@blitzjs/auth"
await SecurePassword.hash(password)
await SecurePassword.verify(passwordHash, password)
SecurePassword.hash(password: string) => Promise<string>
This is used when a user sets a new password.
It takes a password string and returns a secure hash for storing in your database.
SecurePassword.hash
will return a different hash when given the same
string, hence the necessity of SecurePassword.verify
to compare hashes.
SecurePassword.verify(passwordHash: string, password: string) => Promise<ResultCode>
This is used when a user logs in to verify they used the correct password.
It takes a password hash from your database and the given password. It
will verify the given password is correct and return a result code, or if
incorrect, it will throw AuthenticationError
.
SecurePassword.VALID
The password was verified and is valid
SecurePassword.VALID_NEEDS_REHASH
The password was verified and is valid, but needs to be rehashed with new parameters
SecurePassword.HASH_BYTES
Size of the hash
Buffer returned by hash
and hashSync
and used by
verify
and verifySync
.
import { AuthenticationError } from "blitz"
import { SecurePassword } from "@blitzjs/auth"
import db from "db"
export const authenticateUser = async (
email: string,
password: string
) => {
const user = await db.user.findFirst({ where: { email } })
if (!user) throw new AuthenticationError()
const result = await SecurePassword.verify(
user.hashedPassword,
password
)
if (result === SecurePassword.VALID_NEEDS_REHASH) {
// Upgrade hashed password with a more secure hash
const improvedHash = await SecurePassword.hash(password)
await db.user.update({
where: { id: user.id },
data: { hashedPassword: improvedHash },
})
}
const { hashedPassword, ...rest } = user
return rest
}
setPublicDataForUser()
setPublicDataForUser(userId: PublicData['userId'], publicData: Record<any, any>) => void
This can be used to update the publicData
of a user's sessions. It can
be useful when changing a user's role, since the new permissions can be
enforced as soon as the user is doing the next request.
import { setPublicDataForUser } from "@blitzjs/auth"
import db from "db"
export const updateUserRole = async (
userId: PublicData["userId"],
role: string
) => {
// update the user's role
await db.user.update({ where: { id: userId }, data: { role } })
// update role in all active sessions
await setPublicDataForUser(userId, { role })
}
The following methods are meant for internal usage or for advanced use cases. They are not needed for general use.
getSession
This function is used internally by Blitz to get the session context from
the request either from an IncomingMessage
and ServerResponse
pair or
from a Request
object.
req: IncomingMessage | Request
- The request object from the server.res: ServerResponse | never
- The response object from the server.isRsc: boolean
- A boolean that determines if the request is for a
resource.SessionContext
- The session context object.SessionContext.setSession
This function is used along with getSession to set the session context on the response object after the session has been created or updated.
response: Response | ServerResponse
- The response object from the
server.void
Request
async function handler(request: Request, params: Record<string, string>) {
const session = await getSession(request)
const response = await handler(request, params, { session })
session.setSession(response)
return response
}
IncomingMessage
and ServerResponse
async function handler(req: IncomingMessage, res: ServerResponse) {
const session = await getSession(req, res)
await handler(req, res, { session })
session.setSession(res)
}
handler
is a function that processes the request and can mutate the
session stateresponse
| res
will contain the session state after the handler
has been processed