-
-
Save Fyko/1295f2f93237a68178bcab616411fac8 to your computer and use it in GitHub Desktop.
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
async (req, res) => { | |
const authorized = await oauth.token(req, res); // oauth is an instance of the OAuth2 class | |
const me = await rest(authorized.access_token, { tokenType: 'Bearer' }).get('/users/@me'); // rest just fetches the url | |
const [user] = await app.db.model('user').findCreateFind({ | |
where: {}, | |
include: [{ | |
model: app.db.model('profile'), | |
where: { | |
id: me.id, | |
provider: 'DISCORD', | |
}, | |
}], | |
}); | |
await app.db.model('profile').upsert({ | |
id: me.id, | |
userId: user.id, | |
provider: 'DISCORD', | |
accessToken: authorized.access_token, | |
refreshToken: authorized.refresh_token, | |
accessExpiresAt: Date.now() + (authorized.expires_in * 1000), | |
}); | |
const token = await app.jwt.sign(user.id); | |
const redirect = req.cookies.get('redirect_to', { signed: true }); | |
if (redirect) { | |
res.cookies.set('redirect_to'); | |
res.cookies.set('authorization', token, { httpOnly: false }); | |
res.statusCode = 301; | |
res.setHeader('Location', redirect); | |
} else { | |
res.setHeader('Content-Type', 'application/json'); | |
res.write(JSON.stringify({ token })); | |
} | |
res.end(); | |
}; |
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
const { randomBytes } = require('crypto'); | |
const fetch = require('node-fetch'); | |
const FormData = require('form-data'); | |
const { parse } = require('url'); | |
module.exports = class OAuth2 { | |
constructor({ | |
endpoint, | |
clientID, | |
clientSecret, | |
responseType = 'code', | |
scopes = [], | |
redirectURI, | |
}) { | |
this.endpoint = endpoint; | |
this.clientID = clientID; | |
this.clientSecret = clientSecret; | |
this.responseType = responseType; | |
this.scopes = scopes; | |
this.redirectURI = redirectURI; | |
} | |
get authorizeURL() { | |
return `${this.endpoint}/authorize`; | |
} | |
get tokenURL() { | |
return `${this.endpoint}/token`; | |
} | |
get revokeURL() { | |
return `${this.endpoint}/token/revoke`; | |
} | |
clone() { | |
return new this.constructor({ | |
endpoint: this.endpoint, | |
clientID: this.clientID, | |
clientSecret: this.clientSecret, | |
responseType: this.responseType, | |
scopes: this.scopes.slice(), | |
redirectURI: this.redirectURI, | |
}); | |
} | |
generateState(cookies) { | |
const id = randomBytes(20).toString('hex'); | |
cookies.set('state', id, { signed: true }); | |
return id; | |
} | |
authorize() { | |
return (req, res) => { | |
/* eslint-disable camelcase */ | |
const params = new URLSearchParams({ | |
response_type: this.responseType, | |
scope: this.scopes.join(' '), | |
redirect_uri: this.redirectURI, | |
client_id: this.clientID, | |
state: this.generateState(res.cookies), | |
}); | |
/* eslint-enable camelcase */ | |
res.setHeader('Location', `${this.authorizeURL}?${params}`); | |
res.statusCode = 302; | |
res.end(); | |
}; | |
} | |
token(req, res, grantType = 'authorization_code') { | |
const url = parse(req.url, true); | |
const state = req.cookies.get('state', { signed: true }); | |
if (!state || url.query.state !== state) { | |
res.statusCode = 401; | |
res.end('no or invalid state provided'); | |
return; | |
} | |
const form = new FormData(); | |
form.append('client_id', this.clientID); | |
form.append('client_secret', this.clientSecret); | |
form.append('grant_type', grantType); | |
form.append('code', url.query.code); | |
form.append('redirect_uri', this.redirectURI); | |
form.append('scope', this.scopes.join(' ')); | |
return fetch(this.tokenURL, { | |
method: 'POST', | |
body: form, | |
}).then(r => r.json()); | |
} | |
refresh(token) { | |
const form = new FormData(); | |
form.append('client_id', this.clientID); | |
form.append('client_secret', this.clientSecret); | |
form.append('grant_type', 'refresh_token'); | |
form.append('refresh_token', token); | |
form.append('redirect_uri', this.redirectURI); | |
form.append('scope', this.scopes.join(' ')); | |
return fetch(this.tokenURL, { | |
method: 'POST', | |
body: form, | |
}).then(r => r.json()); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment