@authduo/authduo
Version:
Free User-sovereign Authentication for the World
202 lines (152 loc) ⢠7.4 kB
Markdown

# š½ [Authduo.org](https://authduo.org/) ā Free Auth for Everybody
[Authduo.org](https://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.
⨠**No emails** ā users can remain anonymous
š **No passwords** ā passports are cryptographic keypairs
šæ **No databases** ā everything is stored locally on the user's device
š½ **User-sovereign** ā users can directly download their passport files
š„· **Privacy-focused** ā no tracking, except for whatever github pages does
š **Free and open-source** ā zero cost at worldwide scale
š± **Clientside** ā statically hosted on github pages, no api servers
šļø **Federated** ā your app can get login tokens from an authduo.org popup
š **Protocol** ā permissionless integration, you can do it your way
š„§ **Easy as pie** ā setup your app with an easy snippet
š„ **Easy as pancakes** ā logins are fast and painless for users
> ***Pre-release:** Authduo is an unfinished prototype, use at your own risk.*
<br/>
## šŖŖ [Authduo.org](https://authduo.org/) Login Button
Try out the login button at the [Federated Test Page](https://authduo.org/federated/)
### š Easy HTML Installation
*Choose this installation method if you don't know any better.*
1. **Insert this in your `<head>`:**
```html
<script type="module" src="https://authduo.org/install.bundle.min.js"></script>
<script type="module">
document.querySelector("auth-button").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:
```js
login.name // Cetdok Pizafoaba
login.thumbprint // "0d196fc3..."
login.expiry // 1731740481065
```
- When the user logs out, `login` is `null`.
1. **Put these elements in your `<body>`:**
```html
<auth-user></auth-user>
<auth-button></auth-button>
```
- 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.*
1. **Install the npm package**
```sh
npm i /authduo
```
1. **Register components and listen for auth changes.** `main.ts`
```ts
import {Auth, components, register_to_dom} from "@authduo/authduo"
register_to_dom(components)
const auth = Auth.get()
auth.onChange(login => {
if (login) console.log("logged in", login)
else console.log("logged out")
})
```
1. **Throw down some elements.** `index.html`
```html
<auth-user></auth-user>
<auth-button></auth-button>
```
<br/>
## š [Authduo.org](https://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:
```html
<auth-button src="https://authduo.org/"></auth-button>
```
- Just swap `https://authduo.org/` with your own url
- This is what "decentralized", "user-sovereign", and "protocol" is all about
<br/>
## š The More You Know, about [Authduo.org](https://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
<br/>
## š ļø 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.
```js
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 a user on your app clicks to login, this opens an Authduo.org popup for them to login.
- The authduo signs some tokens with your user's passport keypair, and sends them back to your application.
- Your app receives a `Login` object, which has some useful things:
- `login.proof.token` -- this is a `Proof` token and it's public, so you can send it around anywhere so your user can prove their identity
- `login.keys.signClaimToken(~)` -- you can use this to sign arbitrary data into a token, which is verifiably signed on behalf of the user's passport
#### Example of signing and verifying claim tokens
- **Sign a fresh claim token.**
```js
import {Future} from "@authduo/authduo"
const idToken = await login.keys.signClaimToken({
expiresAt: Future.hours(24),
// you can pack any abitrary data you want into this token
data: {
username: "Rec Doamge",
avatarId: "d15aea1a",
// perhaps we want to scope this claim to a specific game session,
// so that it cannot be stolen by other users and reused in other
// game sessions.
gameSessionId: "9c22b17e",
},
})
```
- **Send this *idToken* along with the user's *proofToken.***
```js
await sendElsewhere(login.proof.token, idToken)
```
- Each `login` object comes with a proof token that is required to verify any claim tokens.
- **Verify the proof and claim**
```js
import {Proof, Claim} from "@authduo/authduo"
receiveElsewhere(async(proofToken, idToken) => {
// the origin of your site that triggered the authduo popup
const allowedAudiences = ["https://example.benev.gg"]
// verifying the proof
const proof = await Proof.verify(proofToken, {allowedAudiences})
// proving the claim
const claim = await Claim.verify(proof, idToken)
// here's that data you packed into the claim
console.log(claim.data.username) // "Rec Doamge"
console.log(claim.data.avatarId) // "d15aea1a"
console.log(claim.data.gameSessionId) // "9c22b17e"
// user passport public thumbprint, the true user identifier
console.log(claim.thumbprint) // "a32e638e..."
console.log(proof.thumbprint) // "a32e638e..."
})
```
- The same proof can be used to verify multiple claims from the same login.
<br/>
## š [Authduo](https://authduo.org/) is free and open source
- I built Authduo because I wanted free user-centric auth to power https://benevolent.games/
- 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