@iagocalazans/elysia-oauth2
A plugin for Elysia.js for server-side OAuth 2.0 Authorization Code Flow
Installation
bun add @iagocalazans/elysia-oauth2
Usage
import { Elysia } from 'elysia';
import oauth2, { github } from '@iagocalazans/elysia-oauth2';
import { randomBytes } from 'crypto';
const globalState = randomBytes(8).toString('hex');
let globalToken = null;
const app = new Elysia();
const auth = oauth2({
profiles: {
github: {
provider: github(),
scope: ['user']
}
},
state: {
check(req, name, state) {
return state === globalState;
},
generate(req, name) {
return globalState;
}
},
storage: {
async get ({ cookie }, name) {
return jwt.verify(cookie[`${name}_session`]);
},
async set ({ setCookie, jwt }, name, token) {
setCookie(`${name}_session`, await jwt.sign(token), { maxAge: token.expires_in });
return token;
},
async delete ({ setCookie }, name) {
setCookie(`${name}_session`, '', { maxAge: 0, expires: new Date(Date.now()) });
return {};
}
}
});
function userPage(user: {}, logout: string) {
const html = `<!DOCTYPE html>
<html lang="en">
<body>
User:
<pre>${JSON.stringify(user, null, '\t')}</pre>
<a href="${logout}">Logout</a>
</body>
</html>`;
return new Response(html, { headers: { 'Content-Type': 'text/html' } });
}
app
.use(auth)
.use(cookie({
maxAge: 3600,
secure: true,
httpOnly: true,
sameSite: 'none',
signed: true,
secret: ['Johnny has a cage']
}))
.use(jwt({
name: 'jwt',
secret: 'Lorem Ipsum Dolor Sit Amet'
}))
.get('/', async (ctx) => {
const profiles = ctx.profiles('github');
if (await ctx.authorized('github')) {
const user = await fetch('https://api.github.com/user', {
headers: await ctx.tokenHeaders('github')
});
return userPage(await user.json(), profiles.github.logout);
}
const html = `<!DOCTYPE html>
<html lang="en">
<body>
<h2>Login with <a href="${profiles.github.login}">Github</a></h2>
</body>
</html>`;
return new Response(html, { headers: { 'Content-Type': 'text/html' } });
})
.listen(3000);
console.log('Listening on http://localhost:3000');
Where are the client credentials?
-
Generate a client id
and client secret
for an OAuth app on Github
-
Use http://localhost:3000/login/github/authorized
as your Authorization callback URL
-
Create an .env
file based on the previously generated client credentials:
GITHUB_OAUTH_CLIENT_ID=client id
GITHUB_OAUTH_CLIENT_SECRET=client secret
-
Bun automatically loads environment variables from .env
files
If you are unsure which URL should be used as Authorization callback URL
call ctx.profiles()
without an argument to get all URLs of all registered OAuth 2.0 Profiles:
app
.use(auth)
.get('/', (ctx) => {
return ctx.profiles();
})
.listen(3000);
Use predefined OAuth 2.0 providers
import { azure, discord, github, ... } from '@iagocalazans/elysia-oauth2';
Define your own OAuth 2.0 provider
import oauth2, { TOAuth2Provider } from '@iagocalazans/elysia-oauth2';
function myGithub(): TOAuth2Provider {
return {
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
auth: {
url: 'https://github.com/login/oauth/authorize',
params: {
allow_signup: true
}
},
token: {
url: 'https://github.com/login/oauth/access_token',
params: {}
}
};
}
const auth = oauth2({
profiles: {
github: {
provider: myGithub(),
scope: ['user']
}
}
});
Author
bogeychan
License
MIT