@authduo/authduo v0.1.1
š½ Authduo.org ā Free Auth for Everybody
Authduo.org is an app where users can create and manage digital login passports.
You can add a "Login with Authduo" button to your website, allowing users to login using an Authduo passport.
š Passwordless ā passports are cryptographic keypairs
š½ User-sovereign ā users can directly download their passport files
š„· Privacy-focused ā users can be anonymous: no emails, no tracking
š Free and open source ā zero cost at worldwide scale
š„ Easy as pancakes ā paste in a tiny amount of code to get logins
š± Clientside ā statically hosted on github pages, no api servers
šļø Federated ā get login tokens from the authduo.org popup flow
š Decentralized ā fork and self-host if you'd rather
š Protocol ā permissionless integration, you can do it your way
*Pre-release: Authduo is an unfinished prototype, use at your own risk.*
šŖŖ Authduo.org Login Button
Try out the login button at the Federated Test Page
š Easy HTML Installation
Choose this installation method if you don't know any better.
Insert this in your
<head>
:<script type="module" src="https://authduo.org/install.bundle.min.js"></script> <script type="module"> document.querySelector("auth-login").auth.onChange(login => { if (login) console.log("logged in", login) else console.log("logged out") }) </script>
- Customize that second script to handle logins/logouts your way.
- When the user logs in, the
login
object looks like this:login.name // Kaylim Bojrumaj login.thumbprint // "4e77bccf..." login.expiry // 1729381451374
- When the user logs out,
login
isnull
.
Put this button in your
<body>
:<auth-login></auth-login>
- This provides a nice little status/button ui for users to login or logout.
- The login state is automatically stored in
localStorage
.
š§ Sophisticated Installation for App Devs
Choose this installation method if you're familiar with npm, package.json, typescript ā stuff like that.
- Install the npm package
npm i @authduo/authduo
Register components and listen for auth changes.
main.ts
import {auth, components, register_to_dom} from "@authduo/authduo" register_to_dom(components) auth.onChange(login => { if (login) console.log("logged in", login) else console.log("logged out") })
Throw down some login buttons.
index.html
<auth-login></auth-login>
š Authduo.org is for convenience, not vendor lock-in
- You can fork Authduo to make your own passport management app, and users can take their passport files there instead
- You can point the login button to your own fork:
<auth-login src="https://authduo.org/"></auth-login>
- Just swap
https://authduo.org/
with your own url - This is what "decentralized", "user-sovereign", and "protocol" is all about
- Just swap
š The More You Know, about Authduo.org
What if my users lose their passports?
- They'll just generate new passports.
- If you associate important services to your users' passports, you should provide a recovery mechanism so users can re-associate those services with new passports.
Opt-in services for casual user experience
- While Authduo's core must stay lean to retain user-sovereignty and privacy, we can still build optional services which allow users to trade a little sovereignty for some conveniences:
- Username and password logins
- Email-based recovery
- OTP/QR codes to easily transfer passports across devices
- Two-factor auth
š ļø More advanced integration examples
Programmatically trigger a login
You can use
auth.popup
to trigger a login, but you should do this in reaction to a user input event, otherwise the browser will block the popup.import {auth} from "@authduo/authduo" myButton.onclick = async() => { const login = await auth.popup("https://authduo.org/") if (login) console.log("logged in", login) }
Understanding the Authduo flow and tokens
- When your user logs in, you receive a Login object (a verified login token).
- Don't pass this around, anybody with the login token can impersonate your user.
- Instead of passing the login token around, you can use the login object to sign your own challenge tokens.
- Let's consider an example: you're making a player-hosted multiplayer game.
- Your user logs in, and you get a Login object.
- You want to send your user's identity to the host of the game, so they can verify it, and nobody can impersonate your user.
- So you use your Login object to sign a fresh challenge token containing your user's name and other info.
- You send this challenge token along with your login.proof.token to the game host.
- The game host receives your
challengeToken
andproofToken
, and now can verify that your challenge was authentically signed on behalf of the user's passport.
Login
, Proof
, and Challenge
tokens
Sign a fresh challenge token.
import {FromNow} from "@authduo/authduo" const challengeToken = await login.signChallengeToken({ expiry: FromNow.hours(24), // you can pack any abitrary data you want into this token data: { username: "Rec Doamge", // we've scoped this token to this game session, // so that it cannot be stolen and reused in other game sessions. gameSessionId: "9c22b17e", }, })
Send the challengeToken along with a proofToken.
await sendElsewhere({ proofToken: login.proof.token, challengeToken, })
- Each
login
object comes with aproofToken
that is required to verify a challenge token.
- Each
Verify the proof and challenge
import {Proof, Challenge} from "@authduo/authduo" receiveElsewhere(async(proofToken, challengeToken) => { const proof = await Proof.verify(proofToken) const challenge = await Challenge.verify(proof, challengeToken) // here's that data you packed into the challenge console.log(challenge.data.username) // "Rec Doamge" console.log(challenge.data.gameSessionId) // "9c22b17e" // user passport public thumbprint, the true user identifier console.log(challenge.thumbprint) // "a32e638e..." console.log(proof.thumbprint) // "a32e638e..." })
- The same proof can be used to verify multiple challenges from the same login.
š Authduo is free and open source
- I built Authduo because I wanted free user-centric auth for my apps.
- Got questions or feedback? Don't hesitate to open a github issue or discussion anytime.
- My name is Chase Moskal, ping me on discord: https://discord.gg/BnZx2utdev