
Security News
Vite+ Joins the Push to Consolidate JavaScript Tooling
Evan You announces Vite+, a commercial, Rust-powered toolchain built on the Vite ecosystem to unify JavaScript development and fund open source.
@lokalise/auth
Advanced tools
A flexible, type-safe authentication library for Fastify applications built with TypeScript. This library provides a clean abstraction for JWT-based authentication with support for multiple authentication strategies and token verification methods.
A flexible, type-safe authentication library for Fastify applications built with TypeScript. This library provides a clean abstraction for JWT-based authentication with support for multiple authentication strategies and token verification methods.
import { FastifyInstance } from 'fastify'
import {
JwtBasedAuthenticator,
KeyBasedTokenDecoder,
createAuthenticationPreHandler,
type BaseAuthInfo
} from '@lokalise/auth'
// Define your authentication info type
type MyAuthInfo = BaseAuthInfo<'my-provider'> & {
userId: string
email: string
}
// Create a custom authenticator
class MyAuthenticator extends JwtBasedAuthenticator<MyAuthInfo> {
protected internalAuthenticate(reqContext, jwtPayload, rawToken) {
// Validate the JWT payload and extract user information
if (!jwtPayload.sub || !jwtPayload.email) {
return { success: false, failure: 'INVALID_CREDENTIALS' }
}
return {
success: true,
authInfo: {
authType: 'my-provider',
rawToken,
userId: jwtPayload.sub,
email: jwtPayload.email
}
}
}
}
// Set up authentication
const tokenDecoder = new KeyBasedTokenDecoder('your-secret-key')
const authenticator = new MyAuthenticator(tokenDecoder)
const authPreHandler = createAuthenticationPreHandler(authenticator)
// Register with Fastify
const fastify: FastifyInstance = // ... your fastify instance
fastify.addHook('preHandler', authPreHandler)
// Now your routes have access to authentication info
fastify.get('/protected', async (request, reply) => {
const authInfo = request.reqContext.auth // MyAuthInfo | undefined
return { message: `Hello ${authInfo?.email}!` }
})
import { JwksTokenDecoder } from '@lokalise/auth'
import { createJwksClient } from 'jwks-rsa'
// Set up JWKS client for OAuth provider
const jwksClient = createJwksClient({
jwksUri: 'https://your-oauth-provider.com/.well-known/jwks',
cache: true,
cacheMaxAge: 600000, // 10 minutes
})
const tokenDecoder = new JwksTokenDecoder(jwksClient, {
algorithms: ['RS256'],
issuer: 'https://your-oauth-provider.com'
})
const authenticator = new MyAuthenticator(tokenDecoder)
const authPreHandler = createAuthenticationPreHandler(authenticator)
import { AuthenticatorChain } from '@lokalise/auth'
// Create multiple authenticators
const jwtAuthenticator = new MyJwtAuthenticator(jwtDecoder)
const apiKeyAuthenticator = new MyApiKeyAuthenticator()
// Chain them together
const chain = new AuthenticatorChain([
jwtAuthenticator,
apiKeyAuthenticator
])
const authPreHandler = createAuthenticationPreHandler(chain)
BaseAuthInfo<AuthType>
Base interface for authentication information:
type BaseAuthInfo<AuthType extends string> = {
authType: AuthType
rawToken: string
}
AuthResult<AuthInfo>
Result of authentication attempt:
type AuthResult<AuthInfo> =
| { success: true; authInfo: AuthInfo }
| { success: false; failure: 'INVALID_CREDENTIALS' | 'EXPIRED_CREDENTIALS' }
Authenticator<AuthInfo>
Base interface for all authenticators:
interface Authenticator<AuthInfo extends BaseAuthInfo<string>> {
authenticate(request: FastifyRequest): Promise<AuthResult<AuthInfo>>
}
JwtBasedAuthenticator<AuthInfo>
Abstract base class for JWT-based authentication:
abstract class JwtBasedAuthenticator<AuthInfo extends BaseAuthInfo<string>> {
constructor(tokenDecoder: TokenDecoder, tokenHeader?: string)
// Must be implemented by subclasses
protected abstract internalAuthenticate(
reqContext: RequestContext,
jwtPayload: object,
rawToken: string
): AuthResult<AuthInfo> | Promise<AuthResult<AuthInfo>>
}
AuthenticatorChain<AuthInfo>
Chains multiple authenticators, trying each until one succeeds:
class AuthenticatorChain<AuthInfo extends BaseAuthInfo<string>> {
constructor(authentators: Authenticator<AuthInfo>[])
}
TokenDecoder
Base class for token verification:
class TokenDecoder {
constructor(decode: (token: string) => Promise<unknown> | unknown)
decode(requestContext: RequestContext, token: string): Promise<Either<TokenValidationError, object>>
}
KeyBasedTokenDecoder
Uses a static key for JWT verification:
class KeyBasedTokenDecoder extends TokenDecoder {
constructor(key: string, options?: Partial<VerifierOptions>)
}
JwksTokenDecoder
Uses JWKS endpoint for JWT verification:
class JwksTokenDecoder extends TokenDecoder {
constructor(jwksClient: JwksClient, options?: Partial<VerifierOptions>)
}
createAuthenticationPreHandler<AuthInfo>
Creates a Fastify pre-handler for authentication:
function createAuthenticationPreHandler<AuthInfo extends BaseAuthInfo<string>>(
authenticator: Authenticator<AuthInfo>
): (request: FastifyRequest) => Promise<void>
The library provides consistent error handling with proper HTTP status codes:
INVALID_CREDENTIALS
or EXPIRED_CREDENTIALS
// Errors are thrown as PublicNonRecoverableError
try {
await authPreHandler(request)
} catch (error) {
if (error instanceof PublicNonRecoverableError) {
console.log(error.httpStatusCode) // 401
console.log(error.errorCode) // 'INVALID_CREDENTIALS' or 'EXPIRED_CREDENTIALS'
}
}
The library extends Fastify-extras RequestContext
with authentication information:
declare module '@lokalise/fastify-extras' {
interface RequestContext {
auth?: BaseAuthInfo<string>
}
}
You can specify custom headers for token extraction:
const authenticator = new MyAuthenticator(tokenDecoder, 'x-custom-auth')
// Will look for tokens in the 'x-custom-auth' header instead of 'authorization'
FAQs
A flexible, type-safe authentication library for Fastify applications built with TypeScript. This library provides a clean abstraction for JWT-based authentication with support for multiple authentication strategies and token verification methods.
The npm package @lokalise/auth receives a total of 115 weekly downloads. As such, @lokalise/auth popularity was classified as not popular.
We found that @lokalise/auth demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 20 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Evan You announces Vite+, a commercial, Rust-powered toolchain built on the Vite ecosystem to unify JavaScript development and fund open source.
Security News
Ruby Central’s incident report on the RubyGems.org access dispute sparks backlash from former maintainers and renewed debate over project governance.
Research
/Security News
Socket researchers uncover how threat actors weaponize Discord across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.