Skip to content

Instantly share code, notes, and snippets.

View alancasagrande's full-sized avatar

Alan Casagrande alancasagrande

  • Berlin, Germany
View GitHub Profile
app.post('/login', (req, res) => {
let authenticatedUser;
const { body } = req;
if (body.username) {
// try password login
const user = getUser(body.username);
if (user && user.password === body.password) {
authenticatedUser = user;
// create session
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import { login } from './api';
import App from './App';
(async () => {
// try to login with cookie
const { user, requireMfa } = await login();
// init app
import React from 'react';
import Login from './Login';
import OneTimePassword from './OneTimePassword';
export default function App({ user, requireMfa }) {
// User enabled MFA but did not verify code, show OTP form
if (requireMfa) {
return <OneTimePassword enabled={true} />;
}
export async function login(username, password) {
const res = await fetch('/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
});
if (res.status === 401) {
return { requireMfa: false };
}
import express from 'express';
import cookieSession from 'cookie-session';
import bodyParser from 'body-parser';
import { initStorage, getUser, setUser } from './storage';
import crypto from 'crypto';
import util from 'util';
import qrcode from 'qrcode';
import base32Encode from 'base32-encode';
import { verifyTOTP } from './otp';
import React, { useCallback, useState } from 'react';
import Login from './Login';
import OneTimePassword from './OneTimePassword';
export default function App({ user }) {
// user not logged in, show login form
if (!user) return <Login />;
return (
<div>
export async function verifyOtp(code) {
const res = await fetch('/verify_otp', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code }),
});
return res.json();
}
import React, { useCallback, useState } from 'react';
import { verifyOtp } from './api';
import Input from './Input';
export default function OneTimePassword({ enabled }) {
const [verificationCode, setVerificationCode] = useState('');
const [invalidCode, setInvalidCode] = useState(false);
const handleSubmit = useCallback(
async (e) => {
import crypto from 'crypto';
import base32Decode from 'base32-decode';
export function generateHOTP(secret, counter) {
const decodedSecret = base32Decode(secret, 'RFC4648');
const buffer = Buffer.alloc(8);
for (let i = 0; i < 8; i++) {
buffer[7 - i] = counter & 0xff;
counter = counter >> 8;
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import { login } from './api';
import App from './App';
(async () => {
// try to login with cookie
const res = await login();
// init app