passlessjs
v0.1.2
Published
Tiny helper for Google, Yandex OAuth and WebAuthn passkeys with .env support
Maintainers
Readme
passless - English 🇺🇸
A mini-library for Node.js that makes it easy to integrate OAuth login via Google and Yandex, as well as add Passkey (WebAuthn) authentication. Configuration is done via .env, with no unnecessary magic.
Installation
npm install passlessjsRequires Node.js 18+ (uses the built-in fetch).
Environment Variables
Create a .env file (see .env.example):
PASSLESS_GOOGLE_CLIENT_ID=
PASSLESS_GOOGLE_CLIENT_SECRET=
PASSLESS_GOOGLE_REDIRECT_URI=
PASSLESS_YANDEX_CLIENT_ID=
PASSLESS_YANDEX_CLIENT_SECRET=
PASSLESS_YANDEX_REDIRECT_URI=
PASSLESS_RP_NAME=Passless Demo
PASSLESS_RP_ID=localhost
PASSLESS_ORIGIN=http://localhost:3000Quick Start (OAuth)
const express = require('express');
const { Passless } = require('passlessjs');
require('dotenv').config();
const app = express();
const passless = new Passless();
app.get('/auth/google', (req, res) => {
const url = passless.getAuthUrl('google', req.query.state || '');
res.redirect(url);
});
app.get('/auth/google/callback', async (req, res) => {
const { code } = req.query;
const result = await passless.exchangeCode('google', code);
// result.token and result.profile
res.json(result.profile);
});
app.get('/auth/yandex', (req, res) => {
const url = passless.getAuthUrl('yandex', req.query.state || '');
res.redirect(url);
});
app.get('/auth/yandex/callback', async (req, res) => {
const { code } = req.query;
const result = await passless.exchangeCode('yandex', code);
res.json(result.profile);
});
app.listen(3000, () => console.log('http://localhost:3000'));Passkey (WebAuthn) Example
In a real project, replace Map with your database. Store credentialStore and challengeStore between restarts.
const passless = new Passless({
passkey: {
rpId: 'localhost',
origin: 'http://localhost:3000',
rpName: 'Passless Demo',
},
credentialStore: new Map(),
challengeStore: new Map(),
});
// Registration
app.get('/passkey/register/options', async (req, res) => {
const opts = await passless.createPasskeyRegistrationOptions({
userId: '123',
username: 'demo',
displayName: 'Demo User',
});
res.json(opts);
});
app.post('/passkey/register/verify', express.json(), async (req, res) => {
const verification = await passless.verifyPasskeyRegistrationResponse({
response: req.body,
expectedChallenge: req.body.expectedChallenge,
});
res.json({ verified: verification.verified });
});
// Authentication
app.get('/passkey/authn/options', async (req, res) => {
const opts = await passless.createPasskeyAuthenticationOptions({ userId: '123' });
res.json(opts);
});
app.post('/passkey/authn/verify', express.json(), async (req, res) => {
const verification = await passless.verifyPasskeyAuthenticationResponse({
response: req.body,
expectedChallenge: req.body.expectedChallenge,
});
res.json({ verified: verification.verified });
});API Overview
new Passless(config?)— acceptsgoogle,yandex,passkey, as well as customcredentialStore/challengeStore(default isMap).getAuthUrl(provider, state?)— returns the authorization URL (provider:google|yandex).exchangeCode(provider, code, overrideRedirectUri?)— exchangecodefor a token and profile.createPasskeyRegistrationOptions({ userId, username, displayName })— get options for WebAuthn registration.verifyPasskeyRegistrationResponse({ response, expectedChallenge })— verify the registration response.createPasskeyAuthenticationOptions({ userId })— options for passkey login.verifyPasskeyAuthenticationResponse({ response, expectedChallenge })— verify the authentication response.
Limitations
- The examples use in-memory stores; replace them with a persistent database.
- For production, add checks for the expiration of
state/challengeand use HTTPS. - Ensure that
PASSLESS_ORIGINandPASSLESS_RP_IDmatch the real domain.
Extensibility
Passless uses a provider-based architecture. Any OAuth2 provider (Apple, GitHub, Discord, etc.) can be added without changing the core.
Pull Requests
I welcome any contributions!
passless - Ru 🇷🇺
Мини-библиотека для Node.js, которая помогает быстро подружиться с OAuth входом через Google и Yandex, а также добавить вход по Passkey (WebAuthn). Конфигурация через .env, без лишней магии.
Установка
npm install passlessjsТребуется Node.js 18+ (используется встроенный fetch).
Переменные окружения
Создайте файл .env (см. .env.example):
PASSLESS_GOOGLE_CLIENT_ID=
PASSLESS_GOOGLE_CLIENT_SECRET=
PASSLESS_GOOGLE_REDIRECT_URI=
PASSLESS_YANDEX_CLIENT_ID=
PASSLESS_YANDEX_CLIENT_SECRET=
PASSLESS_YANDEX_REDIRECT_URI=
PASSLESS_RP_NAME=Passless Demo
PASSLESS_RP_ID=localhost
PASSLESS_ORIGIN=http://localhost:3000Быстрый старт (OAuth)
const express = require('express');
const { Passless } = require('passlessjs');
require('dotenv').config();
const app = express();
const passless = new Passless();
app.get('/auth/google', (req, res) => {
const url = passless.getAuthUrl('google', req.query.state || '');
res.redirect(url);
});
app.get('/auth/google/callback', async (req, res) => {
const { code } = req.query;
const result = await passless.exchangeCode('google', code);
// result.token и result.profile
res.json(result.profile);
});
app.get('/auth/yandex', (req, res) => {
const url = passless.getAuthUrl('yandex', req.query.state || '');
res.redirect(url);
});
app.get('/auth/yandex/callback', async (req, res) => {
const { code } = req.query;
const result = await passless.exchangeCode('yandex', code);
res.json(result.profile);
});
app.listen(3000, () => console.log('http://localhost:3000'));Passkey (WebAuthn) пример
В реальном проекте замените Map на свою БД. Храните credentialStore и challengeStore между перезапусками.
const passless = new Passless({
passkey: {
rpId: 'localhost',
origin: 'http://localhost:3000',
rpName: 'Passless Demo',
},
credentialStore: new Map(),
challengeStore: new Map(),
});
// Регистрация
app.get('/passkey/register/options', async (req, res) => {
const opts = await passless.createPasskeyRegistrationOptions({
userId: '123',
username: 'demo',
displayName: 'Demo User',
});
res.json(opts);
});
app.post('/passkey/register/verify', express.json(), async (req, res) => {
const verification = await passless.verifyPasskeyRegistrationResponse({
response: req.body,
expectedChallenge: req.body.expectedChallenge,
});
res.json({ verified: verification.verified });
});
// Аутентификация
app.get('/passkey/authn/options', async (req, res) => {
const opts = await passless.createPasskeyAuthenticationOptions({ userId: '123' });
res.json(opts);
});
app.post('/passkey/authn/verify', express.json(), async (req, res) => {
const verification = await passless.verifyPasskeyAuthenticationResponse({
response: req.body,
expectedChallenge: req.body.expectedChallenge,
});
res.json({ verified: verification.verified });
});API поверхностно
new Passless(config?)— принимаетgoogle,yandex,passkey, а также своиcredentialStore/challengeStore(по умолчаниюMap).getAuthUrl(provider, state?)— вернуть URL авторизации (provider:google|yandex).exchangeCode(provider, code, overrideRedirectUri?)— обменятьcodeна токен и профиль.createPasskeyRegistrationOptions({ userId, username, displayName })— получить options для WebAuthn регистрации.verifyPasskeyRegistrationResponse({ response, expectedChallenge })— проверить ответ регистрации.createPasskeyAuthenticationOptions({ userId })— options для входа по passkey.verifyPasskeyAuthenticationResponse({ response, expectedChallenge })— проверить ответ входа.
Ограничения
- В примерах используются in-memory хранилища; замените на постоянную БД.
- Для продакшена добавьте проверку срока жизни
state/challengeи HTTPS. - Следите, чтобы
PASSLESS_ORIGINиPASSLESS_RP_IDсовпадали с реальным доменом.
Расширяемость
Passless использует провайдерную архитектуру. Любой OAuth2-провайдер (Apple, GitHub, Discord и др.) может быть добавлен без изменения ядра.
Pull requests
буду рад видеть любые запросы
