-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
v1 (technically v1.1.0 but who cares)
- Loading branch information
Showing
7 changed files
with
490 additions
and
146 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,73 +1,128 @@ | ||
# repl-auth | ||
# replace-replit | ||
|
||
Use Replit's Repl Auth in your project without hosting on Replit. | ||
Use some of Replit's features in your project without hosting on Replit. | ||
|
||
## Usage | ||
|
||
### Replit | ||
### ReplAuth | ||
|
||
Use this exactly how you'd use [`@replit/repl-auth`](https://npm.im/@replit/repl-auth): | ||
The ReplAuth module only supports express and socket.io currently. | ||
|
||
```js | ||
import { getUserInfo } from "repl-auth"; | ||
import { auth } from "replace-replit"; | ||
import express from "express"; | ||
import { createServer } from 'node:http'; | ||
import { Server } from 'socket.io'; | ||
|
||
const app = express(); | ||
const server = createServer(app); | ||
const io = new Server(server); | ||
app.use(auth.express()); | ||
|
||
app.get('/', (req, res) => { | ||
const user = getUserInfo(req); | ||
const username = req.get("X-Replit-User-Name"); | ||
|
||
if (user) | ||
res.send(`Hello, ${user.name}!`); | ||
if (username) | ||
res.send(`Hello, ${username}!`); | ||
else | ||
res.send(`Hello, World!`); | ||
}); | ||
|
||
app.listen(8000, () => { | ||
io.use(auth.socketIo({ exposeAs: "user" })) | ||
|
||
io.on('connection', (socket) => { | ||
console.log('connection from', socket.user.name) | ||
}) | ||
|
||
server.listen(8000, () => { | ||
console.log("App is running on port 8000"); | ||
}); | ||
``` | ||
|
||
### Anywhere else | ||
### ReplDB | ||
|
||
The module only supports express currently. | ||
The ReplDB module only supports express and socket.io currently. | ||
|
||
```js | ||
import { express as replAuth } from "repl-auth"; | ||
// server.js | ||
import { db } from "replace-replit"; | ||
import express from "express"; | ||
|
||
const app = express(); | ||
app.use(replAuth()); | ||
|
||
app.get('/', (req, res) => { | ||
const username = req.get("X-Replit-User-Name"); | ||
|
||
if (username) | ||
res.send(`Hello, ${username}!`); | ||
else | ||
res.send(`Hello, World!`); | ||
}); | ||
app.use(db.express({ | ||
file: "database.json", | ||
fileType: "json" | ||
})); | ||
|
||
app.listen(8000, () => { | ||
console.log("App is running on port 8000"); | ||
}); | ||
|
||
// test.js | ||
import Database from "@replit/database"; | ||
|
||
const db = new Database("localhost:8000"); | ||
|
||
await db.set("hello", "world") | ||
|
||
await db.get("hello") // world | ||
``` | ||
|
||
## Options | ||
|
||
Currently there is only one option passable to the `replAuth` middleware: | ||
### ReplAuth | ||
Currently there is only one option passable to the `auth` middleware: | ||
|
||
`exposeAs` will allow you to control what an object containing the user data will be set to: | ||
|
||
```js | ||
app.use(replAuth({ exposeAs: "user" })) | ||
app.use(auth.express({ exposeAs: "user" })) | ||
|
||
// In a route handler... | ||
req.user.name // contains the user's username | ||
``` | ||
|
||
### ReplDB | ||
There are 4 options passable to the `db` middleware: | ||
|
||
`file`: Controls what file your database will be saved to. | ||
`fileType`: Controls what type your file will use. Values can either be `json`, `toml`, `ini`, or `custom` (see below): | ||
|
||
`parse`: Function that takes two arguments, data (the file contents) and fileType (the fileType passed to the middleware). | ||
|
||
```js | ||
db.express({ | ||
// ... | ||
parse(data, fileType) { | ||
if (fileType == "...") { | ||
// do stuff | ||
return TheResultingDataInAnObject | ||
} else { | ||
throw new Error('i dunno what this file type is') | ||
} | ||
} | ||
}) | ||
``` | ||
|
||
`stringify`: Function that takes two arguments, data (the current db object) and fileType (the fileType passed to the middleware). | ||
|
||
```js | ||
db.express({ | ||
// ... | ||
stringify(data, fileType) { | ||
if (fileType == "...") { | ||
// do stuff | ||
return TheResultingDataInAString | ||
} else { | ||
throw new Error('i dunno what this file type is') | ||
} | ||
} | ||
}) | ||
``` | ||
|
||
# Acknowledgements | ||
|
||
[PotentialStyx](https://replit.com/@PotentialStyx) - Helped me with verifying the JWT | ||
[PikachuB2005](https://replit.com/@PikachuB2005) - Donated the package name to me | ||
[PikachuB2005](https://replit.com/@PikachuB2005) - Donated the package name to me | ||
[coding398](https://replit.com/@codingMASTER398) - Cool tester + has great ideas + bug fixer | ||
[DillonB07](https://replit.com/@DillonB07) - Helped on the README |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,113 +1,2 @@ | ||
import type { Request, Response, NextFunction } from 'express'; | ||
import { verify } from 'jsonwebtoken'; | ||
|
||
const PUBKEY = `-----BEGIN PUBLIC KEY----- | ||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEv+0QT2+9KdAHZMXROxnLmfE9qkry | ||
1W4bieh/LIyXyl9v2aexV8hef2iMaYmjz9yji2Iae1/sgiywvwflRD5O9Q== | ||
-----END PUBLIC KEY----- | ||
`; | ||
|
||
export type Options = { | ||
exposeAs?: string; | ||
}; | ||
|
||
export function express( | ||
opts?: Options, | ||
): (req: Request, res: Response, next: NextFunction) => void { | ||
return function middleware( | ||
req: Request, | ||
res: Response, | ||
next: NextFunction, | ||
) { | ||
if (req.path == '/__replauth') { | ||
const REPL_AUTH = req.query.token as string; | ||
|
||
let user; | ||
|
||
try { | ||
user = verify(REPL_AUTH, PUBKEY); | ||
} catch (err) { | ||
return res.status(400).send('bad jwt'); | ||
} | ||
|
||
return res | ||
.cookie('REPL_AUTH', REPL_AUTH) | ||
.status(304) | ||
.redirect(req.query.redirect); | ||
} else if (req.path == '/__replauthuser') { | ||
const cookies: { [key: string]: string } = Object.fromEntries( | ||
req.headers.cookie.split(';').map((x) => { | ||
const a = x.trim().split('='); | ||
return [a.shift(), a.join('=')]; | ||
}), | ||
); | ||
|
||
const REPL_AUTH = cookies.REPL_AUTH; | ||
|
||
let user; | ||
|
||
try { | ||
user = verify(REPL_AUTH, PUBKEY); | ||
} catch (err) { | ||
return res.send('User is not logged in'); | ||
} | ||
|
||
return res.json({ | ||
id: user.sub, | ||
name: user.name, | ||
bio: user.bio, | ||
url: user.url, | ||
profileImage: user.profile_image, | ||
roles: user.roles.split(','), | ||
teams: user.teams.split(','), | ||
}); | ||
} | ||
|
||
if(!req.headers.cookie){ | ||
return next(); | ||
} | ||
|
||
const cookies: { [key: string]: string } = Object.fromEntries( | ||
req.headers.cookie.split(';').map((x) => { | ||
const a = x.trim().split('='); | ||
return [a.shift(), a.join('=')]; | ||
}), | ||
); | ||
|
||
if(!cookies.REPL_AUTH) return next(); | ||
|
||
const REPL_AUTH = cookies.REPL_AUTH; | ||
|
||
let user; | ||
|
||
try { | ||
user = verify(REPL_AUTH, PUBKEY); | ||
} catch (err) { | ||
return next(err); | ||
} | ||
|
||
req.headers['x-replit-user-name'] = user.name; | ||
req.headers['x-replit-user-id'] = user.sub; | ||
req.headers['x-replit-user-bio'] = user.bio; | ||
req.headers['x-replit-user-url'] = user.url; | ||
req.headers['x-replit-user-profile-image'] = user.profile_image; | ||
req.headers['x-replit-user-teams'] = user.teams; | ||
req.headers['x-replit-user-roles'] = user.roles; | ||
|
||
if (opts.exposeAs) { | ||
req[opts.exposeAs] = { | ||
id: user.sub, | ||
name: user.name, | ||
bio: user.bio, | ||
url: user.url, | ||
profileImage: user.profile_image, | ||
roles: user.roles.split(','), | ||
teams: user.teams.split(','), | ||
}; | ||
} | ||
|
||
next(); | ||
}; | ||
} | ||
|
||
export { getUserInfo } from '@replit/repl-auth'; | ||
export * as auth from "./replauth"; | ||
export * as db from "./repldb"; |
Oops, something went wrong.